void CreateMergedLODGroup() { string path = EditorUtility.SaveFilePanelInProject("Save merged mesh", "", "", "Please enter a file name to save the merged mesh to"); if (path.Length != 0) { if (_lodGroupVegetationMeshCombiner.TargetGameObject == null) { return; } LODGroup lodGroup = _lodGroupVegetationMeshCombiner.TargetGameObject.GetComponentInChildren <LODGroup>(); GameObject sourceObject = _lodGroupVegetationMeshCombiner.TargetGameObject; Vector3 targetPosition = sourceObject.transform.position; Quaternion targetRotation = sourceObject.transform.rotation; Vector3 targetScale = sourceObject.transform.localScale; sourceObject.transform.position = new Vector3(0, 0, 0); sourceObject.transform.rotation = Quaternion.identity; sourceObject.transform.localScale = Vector3.one; if (lodGroup == null) { return; } GameObject mergedLODGroupObject = new GameObject("Merged_" + sourceObject.name); LODGroup newLODGroup = mergedLODGroupObject.AddComponent <LODGroup>(); LOD[] lods = lodGroup.GetLODs(); // ReSharper disable once InconsistentNaming LOD[] newLODs = lodGroup.GetLODs(); for (int i = 0; i <= lods.Length - 1; i++) { LOD lod = lods[i]; if (lod.renderers.Length > 0) { GameObject lodObject = new GameObject(sourceObject.name + "_LOD" + i.ToString()); lodObject.transform.SetParent(mergedLODGroupObject.transform); MeshRenderer meshRenderer = lodObject.AddComponent <MeshRenderer>(); MeshFilter meshFilter = lodObject.AddComponent <MeshFilter>(); Renderer renderer = lod.renderers[0]; MeshFilter tempMeshFilter = lod.renderers[0].gameObject.GetComponent <MeshFilter>(); Renderer[] newRenderers = new Renderer[1]; newRenderers[0] = meshRenderer; newLODs[i].renderers = newRenderers; newLODs[i].screenRelativeTransitionHeight = (float)1 / (i + 1); Mesh mesh = Instantiate(tempMeshFilter.sharedMesh); Material[] materials = renderer.sharedMaterials; SubmeshCombiner submeshCombiner = new SubmeshCombiner(); for (int j = 0; j <= mesh.subMeshCount - 1; j++) { submeshCombiner.AddSubmesh(mesh.GetIndices(j), materials[j]); } submeshCombiner.UpdateMesh(mesh); materials = submeshCombiner.GetMaterials(); meshFilter.sharedMesh = mesh; AssetDatabase.CreateAsset(meshFilter.sharedMesh, path + "_LOD" + i.ToString() + ".asset"); meshRenderer.materials = materials; } } newLODGroup.SetLODs(newLODs); sourceObject.transform.position = targetPosition; sourceObject.transform.rotation = targetRotation; sourceObject.transform.localScale = targetScale; } }
public void SaveAsPrefab(bool groupedSave = false) { string name = gameObject.name; string path = saveTreeFolder; if (string.IsNullOrEmpty(path)) { return; } bool replacePrefab = false; if (!System.IO.Directory.Exists(path)) { EditorUtility.DisplayDialog("Invalid Path", "The path is not valid, you can chose it with the find folder button", "Ok"); return; } if (AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject))) // Overriding prefab dialog { if (EditorUtility.DisplayDialog("Are you sure?", "The prefab already exists. Do you want to overwrite it?", "Yes", "No")) { FileUtil.DeleteFileOrDirectory(Path.Combine(path, name + "_meshes")); AssetDatabase.Refresh(); replacePrefab = true; } else { name += "_1"; } } Mesh[] meshes = new Mesh[4]; string meshesFolder = AssetDatabase.CreateFolder(path, name + "_meshes"); meshesFolder = AssetDatabase.GUIDToAssetPath(meshesFolder) + Path.DirectorySeparatorChar; Material[] materials = SaveMaterials(meshesFolder); GameObject TreeObject = new GameObject(name); // Tree game object LODGroup group = TreeObject.AddComponent <LODGroup>(); // LOD Group group.fadeMode = LODFadeMode.CrossFade; int lodNumber = 4; // Creating LODs LOD[] lods = new LOD[lodNumber + 1]; // Generating Billboard Lod = 3; GenerateTree(true); GameObject billboard = CreateBillboard(meshesFolder, name); Renderer[] bill_re = new Renderer[1] { billboard.GetComponent <MeshRenderer>() }; lods[lodNumber] = new LOD(.01f, bill_re); for (int lod = lodNumber - 1; lod > -1; lod--) // create and save all LOD meshes { string meshPath = meshesFolder + name + "_LOD" + lod.ToString() + ".mesh"; //updating path for each LOD Lod = lod; Mesh mesh = GenerateTree(ao: true); meshes[lod] = mesh; AssetDatabase.CreateAsset(mesh, meshPath); } for (int i = 0; i < lodNumber; i++) // assigning lod meshes to LOD array { GameObject go = new GameObject(name + "_LOD" + i.ToString()); go.transform.parent = TreeObject.transform; MeshFilter mf = go.AddComponent <MeshFilter>(); mf.mesh = meshes[i]; Renderer[] re = new Renderer[1] { go.AddComponent <MeshRenderer>() }; // the renderer to put in LODs re[0].sharedMaterials = materials; float t = Mathf.Pow((i + 1) * 1f / (lodNumber + 1), 1); // float between 0 and 1 following f(x) = pow(x, n) lods[i] = new LOD((1 - t) * 0.9f + t * .01f, re); // assigning renderer lods[i].fadeTransitionWidth = 0.25f; } billboard.transform.parent = TreeObject.transform; // making billboard child of tree object group.SetLODs(lods); // assigning LODs to lod group group.RecalculateBounds(); string prefabPath = path + "/" + name + ".prefab"; TreeObject.AddComponent <MtreeWind>(); Object prefab; if (replacePrefab) { Object targetPrefab = AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject)); prefab = PrefabUtility.ReplacePrefab(TreeObject, targetPrefab, ReplacePrefabOptions.ConnectToPrefab); } else { prefab = PrefabUtility.CreatePrefab(prefabPath, TreeObject, ReplacePrefabOptions.ConnectToPrefab); } AssetDatabase.SaveAssets(); DestroyImmediate(TreeObject); if (!groupedSave) { // select newly created prefab in folder Selection.activeObject = prefab; // Also flash the folder yellow to highlight it EditorGUIUtility.PingObject(prefab); EditorUtility.DisplayDialog("Prefab saved !", "The prefab is saved, you can now delete the tree and use the prefab instead", "Ok"); } }
public void MergeMeshes() { // else Debug.LogWarning("Please assign rooftop material in CS Rooftops Component"); rooftopHolder[iteration].transform.localScale = new Vector3(1, 1, 1); MeshFilter[] meshFilters = rooftopHolder[iteration].GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; int index = 0; for (int x = 0; x < meshFilters.Length; x++) { if (meshFilters[x].sharedMesh != null) { // if (meshFilters[i].sharedMesh == null) continue; combine[index].mesh = meshFilters[x].sharedMesh; combine[index++].transform = meshFilters[x].transform.localToWorldMatrix; } } MeshFilter meshF = rooftopHolder[iteration].transform.GetComponent <MeshFilter>(); meshF.sharedMesh = new Mesh(); meshF.sharedMesh.CombineMeshes(combine); meshF.sharedMesh.RecalculateBounds(); if (lodComponent != null) { lodComponent.RecalculateBounds(); } foreach (Transform go in rooftopHolder[iteration].transform.Cast <Transform>().Reverse()) { DestroyImmediate(go.gameObject); } if (rooftopHolder[iteration].GetComponent <MeshRenderer>() == null) { rh = rooftopHolder[iteration].AddComponent <MeshRenderer>() as MeshRenderer; rh = rooftopHolder[iteration].GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat[iteration]; } rh = rooftopHolder[iteration].GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat[iteration]; Renderer[] renderers = new Renderer[1]; LOD[] lod = new LOD[1]; renderers[0] = rooftopHolder[iteration].GetComponent <Renderer>(); lod[0] = new LOD(lodDistance, renderers); lodComponent.SetLODs(lod); if (animateLodFade) { lodComponent.fadeMode = LODFadeMode.CrossFade; } else { lodComponent.fadeMode = LODFadeMode.None; } lodComponent.animateCrossFading = animateLodFade; rooftopHolder[iteration].transform.position = gameObject.transform.position; rooftopHolder[iteration].transform.rotation = gameObject.transform.rotation; rooftopHolder[iteration].transform.localScale = new Vector3(1, bmComponent.scale, 1); }
public static void CreateObjects(TerrainData terrainData, Transform transform, List <MeshInfo>[,] meshes) { Material matBase = new Material(Shader.Find("Diffuse")); matBase.mainTexture = BakeBaseTexture(terrainData); List <Material> matAdd = new List <Material>(); List <Material> matFirst = new List <Material>(); for (int l = 0; l < terrainData.alphamapLayers; l++) { matAdd.Add(GetMaterial(terrainData, l, false)); matFirst.Add(GetMaterial(terrainData, l, true)); } for (int i = 0; i < meshes.GetLength(0); i++) { for (int j = 0; j < meshes.GetLength(1); j++) { Mesh fullMesh = null; int maxValidLayer = 0; int maxValidNum = 0; List <MeshInfo> group = meshes[i, j]; group.Sort((MeshInfo m0, MeshInfo m1) => { return(m1.validNum.CompareTo(m0.validNum)); }); foreach (var m in group) { if (m.layer == -1) { fullMesh = m.mesh; } else { if (m.validNum > maxValidNum) { maxValidNum = m.validNum; maxValidLayer = m.layer; } } } if (group.Count > 0) { GameObject obj = new GameObject("mesh_" + group[0].gridX.ToString() + "_" + group[0].gridY.ToString()); obj.transform.SetParent(transform); Renderer[] baseRenderer = new Renderer[1]; GameObject baseObj = new GameObject("base"); { MeshRenderer renderer = baseObj.AddComponent <MeshRenderer>(); MeshFilter filter = baseObj.AddComponent <MeshFilter>(); filter.sharedMesh = fullMesh; renderer.sharedMaterial = matBase; baseObj.transform.SetParent(obj.transform); baseRenderer[0] = renderer; } List <Renderer> splatRenderers = new List <Renderer>(); foreach (var m in group) { if (m.layer != -1) { GameObject subObj = new GameObject("mesh_" + m.gridX.ToString() + "_" + m.gridY.ToString() + "_" + m.layer.ToString()); MeshRenderer renderer = subObj.AddComponent <MeshRenderer>(); MeshFilter filter = subObj.AddComponent <MeshFilter>(); filter.sharedMesh = m.layer == maxValidLayer ? fullMesh : m.mesh; renderer.sharedMaterial = m.layer == maxValidLayer ? matFirst[m.layer] : matAdd[m.layer]; subObj.transform.SetParent(obj.transform); splatRenderers.Add(renderer); } } LOD[] lods = new LOD[2]; lods[0].renderers = splatRenderers.ToArray(); lods[0].screenRelativeTransitionHeight = 0.4f; lods[1].renderers = baseRenderer; lods[1].screenRelativeTransitionHeight = 0f; LODGroup lodg = obj.AddComponent <LODGroup>(); lodg.SetLODs(lods); } } } }
public static void GenerateBillboards(Bounds bounds, FoliageCell cell, GameObject owner, List <FoliageInstance> trees, FoliageType type, bool addLodGroup, float screenFadeSize, bool animatedCrossFade) { int[] originalTriangles = m_SystemQuadTriangles; GameObject meshObj = new GameObject(); // Mark object as static #if UNITY_EDITOR GameObjectUtility.SetStaticEditorFlags(meshObj, StaticEditorFlags.OccludeeStatic | StaticEditorFlags.ReflectionProbeStatic); #endif string name = string.Format("MeshCell[{0}_{1}]", cell.GetHashCode(), type.m_Prefab.name); Transform existing = owner.transform.Find(name); if (existing != null) { #if UNITY_EDITOR if (UnityEditor.EditorApplication.isPlaying == false) { Object.DestroyImmediate(existing.gameObject); } else { Object.Destroy(existing.gameObject); } #else Object.Destroy(existing.gameObject); #endif existing = null; } meshObj.transform.SetParent(owner.transform); meshObj.name = name; var data = type.m_RuntimeData.m_SpeedTreeData; Vector3 worldScale = new Vector3(data.m_Size.x, data.m_Size.y, data.m_Size.x); // Set material MeshRenderer rend = meshObj.AddComponent <MeshRenderer>(); rend.sharedMaterial = GenerateBillboardMaterial(type.m_RuntimeData.m_SpeedTreeData); MeshFilter filter = meshObj.AddComponent <MeshFilter>(); Mesh treeMesh = new Mesh(); treeMesh.name = meshObj.name; List <Vector4> m_TempWorldPositions = new List <Vector4>(); List <Vector3> m_TempWorldScales = new List <Vector3>(); List <Vector3> m_TempQuadVertices = new List <Vector3>(); List <Vector4> m_TempQuadTangents = new List <Vector4>(); List <Vector3> m_TempQuadNormals = new List <Vector3>(); List <int> m_TempQuadIndices = new List <int>(); for (int treeIndex = 0; treeIndex < trees.Count; treeIndex++) { Vector3 position = trees[treeIndex].m_Position; Vector3 scale = trees[treeIndex].m_Scale; float rot = trees[treeIndex].m_Rotation.eulerAngles.y * Mathf.Deg2Rad; // Offset world position, by the grounding factor Vector3 instancePos = position; // Don't use this, but offset in shader, so that we can have that correct hue // instancePos.y += data.m_Size.z; // Scale by the world scale too so that we don't have to do an extra multip Vector3 instanceScale = scale; instanceScale.Scale(worldScale); // Add the world and scale data for (int index = 0; index < 4; index++) { Vector4 posAndRot = instancePos; posAndRot.w = rot; m_TempWorldPositions.Add(posAndRot); m_TempWorldScales.Add(instanceScale); } // Add stanard quad data m_TempQuadVertices.AddRange(m_SystemQuadVertices); m_TempQuadTangents.AddRange(m_SystemQuadTangents); m_TempQuadNormals.AddRange(m_SystemQuadNormals); // Calculate triangle indixes m_TempQuadIndices.AddRange(originalTriangles); for (int triIndex = 0; triIndex < 6; triIndex++) { // Just add to the triangles the existing triangles + the new indices m_TempQuadIndices[triIndex + 6 * treeIndex] = originalTriangles[triIndex] + 4 * treeIndex; } } treeMesh.Clear(); // Set standard data treeMesh.SetVertices(m_TempQuadVertices); treeMesh.SetNormals(m_TempQuadNormals); treeMesh.SetTangents(m_TempQuadTangents); // Set the custom data treeMesh.SetUVs(1, m_TempWorldPositions); treeMesh.SetUVs(2, m_TempWorldScales); // Set triangles and do not calculate bounds treeMesh.SetTriangles(m_TempQuadIndices, 0, false); // Set the manually calculated bounds treeMesh.bounds = bounds; treeMesh.UploadMeshData(true); // Set the mesh filter.mesh = treeMesh; if (addLodGroup) { // Add the mesh' lod group LODGroup group = meshObj.AddComponent <LODGroup>(); group.animateCrossFading = false; if (animatedCrossFade) { group.fadeMode = LODFadeMode.CrossFade; group.animateCrossFading = true; } else { group.fadeMode = LODFadeMode.None; group.animateCrossFading = false; } group.SetLODs(new LOD[] { new LOD(screenFadeSize, new Renderer[] { rend }) }); group.RecalculateBounds(); } #if UNITY_EDITOR UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(meshObj.scene); #endif }
public void MergeMeshes() { // else Debug.LogWarning("Please assign rooftop material in CS Rooftops Component"); MeshFilter[] meshFilters = rooftopHolder.GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length - 1]; int index = 0; for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].sharedMesh != null) { // if (meshFilters[i].sharedMesh == null) continue; combine[index].mesh = meshFilters[i].sharedMesh; combine[index++].transform = meshFilters[i].transform.localToWorldMatrix; } } MeshFilter meshF = rooftopHolder.transform.GetComponent <MeshFilter>(); meshF.sharedMesh = new Mesh(); meshF.sharedMesh.CombineMeshes(combine); ///assign new color // Mesh newMesh = new Mesh(); // newMesh.vertices = meshF.sharedMesh.vertices; // newMesh.normals = meshF.sharedMesh.normals; // newMesh.uv = meshF.sharedMesh.uv; // newMesh.colors = new Color[meshF.sharedMesh.vertices.Length]; // newMesh.triangles = meshF.sharedMesh.triangles; // for (int v = 0; v < newMesh.colors.Length; v++) // { // newMesh.colors[v] = new Color(0, 0, 1, 0); // } //meshF.sharedMesh = newMesh; meshF.sharedMesh.RecalculateBounds(); if (lodComponent != null) { lodComponent.RecalculateBounds(); } foreach (Transform go in rooftopHolder.transform.Cast <Transform>().Reverse()) { DestroyImmediate(go.gameObject); } if (rooftopHolder.GetComponent <MeshRenderer>() == null) { rh = rooftopHolder.AddComponent <MeshRenderer>() as MeshRenderer; rh = rooftopHolder.GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat; } rh = rooftopHolder.GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat; Renderer[] renderers = new Renderer[1]; LOD[] lod = new LOD[1]; renderers[0] = rooftopHolder.GetComponent <Renderer>(); lod[0] = new LOD(lodDistance, renderers); lodComponent.SetLODs(lod); if (animateLodFade) { lodComponent.fadeMode = LODFadeMode.CrossFade; } else { lodComponent.fadeMode = LODFadeMode.None; } lodComponent.animateCrossFading = animateLodFade; //if (meshF.sharedMesh.vertices.Length < 3) //{ // DestroyImmediate(rooftopHolder); // noMesh = true; //} //else noMesh = false; }
public override GameObject GetGameObject() { // Instantiate root prefab GameObject prefab = GameObject.Instantiate(Resources.Load <GameObject>("Submarine/Build/Aquarium")); prefab.name = this.ClassID; // Get sub objects GameObject model = prefab.FindChild("model"); GameObject bubbles = prefab.FindChild("Bubbles"); GameObject xBubbles = bubbles.FindChild("xBubbles"); GameObject storage = prefab.FindChild("StorageRoot"); GameObject collider = prefab.FindChild("Collider"); GameObject coral = model.FindChild("Coral"); GameObject coral1 = coral.FindChild("coral_reef_grass_11"); GameObject coral2 = coral.FindChild("coral_reef_grass_10"); GameObject coral3 = coral.FindChild("coral_reef_grass_09"); GameObject coral4 = coral.FindChild("coral_reef_grass_07"); GameObject coral5 = coral.FindChild("coral_reef_plant_middle_03"); GameObject coral6 = coral.FindChild("coral_reef_small_deco_15_red"); GameObject coral7 = coral.FindChild("coral_reef_grass_03_04"); GameObject coral8 = coral.FindChild("coral_reef_small_deco_14"); GameObject coral9 = coral.FindChild("coral_reef_grass_03_03"); GameObject coral10 = coral.FindChild("coral_reef_grass_03_02"); GameObject coral11 = coral.FindChild("Coral_reef_purple_fan"); GameObject aquariumAnim2 = model.FindChild("Aquarium_animation2"); GameObject aquariumAnim2Root = aquariumAnim2.FindChild("root"); GameObject aquariumAnim2Geo = aquariumAnim2.FindChild("Aquarium_geo"); GameObject aquariumAnim2GeoAquarium = aquariumAnim2Geo.FindChild("Aquarium"); GameObject aquariumAnim2GeoAquariumGlass = aquariumAnim2Geo.FindChild("Aquarium_glass"); GameObject aquariumAnim2Fish1 = aquariumAnim2Root.FindChild("fish1"); GameObject aquariumAnim2Fish2 = aquariumAnim2Root.FindChild("fish2"); GameObject aquariumAnim2Fish3 = aquariumAnim2Root.FindChild("fish3"); GameObject aquariumAnim2Fish4 = aquariumAnim2Root.FindChild("fish4"); GameObject aquariumAnim2Attach4 = aquariumAnim2Fish4.FindChild("fish_attach4"); GameObject aquariumAnim1 = model.FindChild("Aquarium_animation"); GameObject aquariumAnim1Root = aquariumAnim1.FindChild("root"); GameObject aquariumAnim1Geo = aquariumAnim1.FindChild("Aquarium_geo"); GameObject aquariumAnim1GeoAquarium = aquariumAnim1Geo.FindChild("Aquarium"); GameObject aquariumAnim1GeoAquariumGlass = aquariumAnim1Geo.FindChild("Aquarium_glass"); GameObject aquariumAnim1Fish1 = aquariumAnim1Root.FindChild("fish1"); GameObject aquariumAnim1Fish2 = aquariumAnim1Root.FindChild("fish2"); GameObject aquariumAnim1Fish3 = aquariumAnim1Root.FindChild("fish3"); GameObject aquariumAnim1Fish4 = aquariumAnim1Root.FindChild("fish4"); // Load resources #if BELOWZERO GameObject greenCoral = Resources.Load <GameObject>("WorldEntities/flora/shared/coral_reef_small_deco_13"); GameObject blueCoral = Resources.Load <GameObject>("WorldEntities/flora/unused/Coral_reef_blue_coral_tubes"); GameObject brownCoral = Resources.Load <GameObject>("WorldEntities/flora/shared/coral_reef_brown_coral_tubes_02_01"); GameObject brownCoral1 = Resources.Load <GameObject>("WorldEntities/flora/shared/coral_reef_brown_coral_tubes_02_03"); #else GameObject greenCoral = Resources.Load <GameObject>("WorldEntities/Doodads/Coral_reef/coral_reef_small_deco_13"); GameObject blueCoral = Resources.Load <GameObject>("WorldEntities/Doodads/Coral_reef/Coral_reef_blue_coral_tubes"); GameObject brownCoral = Resources.Load <GameObject>("WorldEntities/Doodads/Coral_reef/coral_reef_brown_coral_tubes_02_01"); GameObject brownCoral1 = Resources.Load <GameObject>("WorldEntities/Doodads/Coral_reef/coral_reef_brown_coral_tubes_02_03"); #endif // Setup green coral if (greenCoral != null) { GameObject iGreenCoral = GameObject.Instantiate(greenCoral); iGreenCoral.name = "SmallDeco13"; iGreenCoral.transform.parent = coral.transform; iGreenCoral.transform.localScale *= 0.179f; iGreenCoral.transform.localPosition = new Vector3(iGreenCoral.transform.localPosition.x, iGreenCoral.transform.localPosition.y + 0.17f, iGreenCoral.transform.localPosition.z - 0.635f); GameObject.DestroyImmediate(iGreenCoral.GetComponent <LargeWorldEntity>()); GameObject.DestroyImmediate(iGreenCoral.GetComponent <PrefabIdentifier>()); } // Setup blue coral if (blueCoral != null) { coral9.GetComponent <MeshRenderer>().enabled = false; GameObject iBlueCoral = GameObject.Instantiate(blueCoral); iBlueCoral.name = "BlueCoralTubes1"; iBlueCoral.transform.parent = coral.transform; iBlueCoral.transform.localPosition = Vector3.zero; iBlueCoral.transform.localScale *= 0.31f; iBlueCoral.transform.localPosition = new Vector3(iBlueCoral.transform.localPosition.x + 0.22f, iBlueCoral.transform.localPosition.y + 0.16f, iBlueCoral.transform.localPosition.z - 0.77f); var lwe = iBlueCoral.GetComponent <LargeWorldEntity>(); if (lwe != null) { GameObject.DestroyImmediate(lwe); } var lmi = iBlueCoral.GetComponent <LiveMixin>(); if (lmi != null) { GameObject.DestroyImmediate(lmi); } var pid = iBlueCoral.GetComponent <PrefabIdentifier>(); if (pid != null) { GameObject.DestroyImmediate(pid); } var blueCoralModel = iBlueCoral.FindChild("Coral_reef_blue_coral_tubes"); var blueCoralAnim = blueCoralModel.GetComponent <Animator>(); var blueCoralBase = blueCoralModel.FindChild("base1"); var blueCoralGeos = blueCoralModel.FindChild("geos"); LODGroup lodBlueCoral = iBlueCoral.GetComponent <LODGroup>(); lodBlueCoral.ForceLOD(0); LOD[] lods = lodBlueCoral.GetLODs(); lodBlueCoral.SetLODs(new LOD[] { lods[0] }); lodBlueCoral.ForceLOD(0); lodBlueCoral.size = 3.0f; } // Setup brown coral 2 if (brownCoral != null) { GameObject iBrownCoral = GameObject.Instantiate(brownCoral); iBrownCoral.name = "BrownCoralTubes2"; iBrownCoral.transform.parent = coral.transform; iBrownCoral.transform.localPosition = Vector3.zero; iBrownCoral.transform.localScale *= 0.3f; iBrownCoral.transform.localPosition = new Vector3(iBrownCoral.transform.localPosition.x + 0.249f, iBrownCoral.transform.localPosition.y + 0.17f, iBrownCoral.transform.localPosition.z - 0.26f); iBrownCoral.transform.localEulerAngles = new Vector3(iBrownCoral.transform.localEulerAngles.x, iBrownCoral.transform.localEulerAngles.y + 15f, iBrownCoral.transform.localEulerAngles.z); var lwe = iBrownCoral.GetComponent <LargeWorldEntity>(); if (lwe != null) { GameObject.DestroyImmediate(lwe); } var rbo = iBrownCoral.GetComponent <Rigidbody>(); if (rbo != null) { GameObject.DestroyImmediate(rbo); } var lmi = iBrownCoral.GetComponent <LiveMixin>(); if (lmi != null) { GameObject.DestroyImmediate(lmi); } var pid = iBrownCoral.GetComponent <PrefabIdentifier>(); if (pid != null) { GameObject.DestroyImmediate(pid); } var bco = iBrownCoral.GetComponentInChildren <BoxCollider>(); if (bco != null) { GameObject.DestroyImmediate(bco); } // Scale models iBrownCoral.FindChild("coral_reef_brown_coral_tubes_02_01").transform.localScale *= 0.4f; iBrownCoral.FindChild("coral_reef_brown_coral_tubes_02_01_LOD1").transform.localScale *= 0.4f; iBrownCoral.FindChild("coral_reef_brown_coral_tubes_02_01_LOD2").transform.localScale *= 0.4f; iBrownCoral.FindChild("coral_reef_brown_coral_tubes_02_01_LOD3").transform.localScale *= 0.4f; var lodBrownCoral = iBrownCoral.GetComponent <LODGroup>(); lodBrownCoral.ForceLOD(0); LOD[] lods = lodBrownCoral.GetLODs(); lodBrownCoral.SetLODs(new LOD[] { lods[0] }); lodBrownCoral.ForceLOD(0); lodBrownCoral.size = 3.0f; } // Setup brown coral 2 bis if (brownCoral != null) { GameObject iBrownCoralB = GameObject.Instantiate(brownCoral); iBrownCoralB.name = "BrownCoralTubes2"; iBrownCoralB.transform.parent = coral.transform; iBrownCoralB.transform.localPosition = Vector3.zero; iBrownCoralB.transform.localScale *= 0.3f; iBrownCoralB.transform.localPosition = new Vector3(iBrownCoralB.transform.localPosition.x - 0.18f, iBrownCoralB.transform.localPosition.y + 0.055f, iBrownCoralB.transform.localPosition.z - 0.115f); iBrownCoralB.transform.localEulerAngles = new Vector3(iBrownCoralB.transform.localEulerAngles.x, iBrownCoralB.transform.localEulerAngles.y - 105.0f, iBrownCoralB.transform.localEulerAngles.z + 15.0f); var lwe = iBrownCoralB.GetComponent <LargeWorldEntity>(); if (lwe != null) { GameObject.DestroyImmediate(lwe); } var rbo = iBrownCoralB.GetComponent <Rigidbody>(); if (rbo != null) { GameObject.DestroyImmediate(rbo); } var lmi = iBrownCoralB.GetComponent <LiveMixin>(); if (lmi != null) { GameObject.DestroyImmediate(lmi); } var pid = iBrownCoralB.GetComponent <PrefabIdentifier>(); if (pid != null) { GameObject.DestroyImmediate(pid); } var bco = iBrownCoralB.GetComponentInChildren <BoxCollider>(); if (bco != null) { GameObject.DestroyImmediate(bco); } // Scale models iBrownCoralB.FindChild("coral_reef_brown_coral_tubes_02_01").transform.localScale *= 0.4f; iBrownCoralB.FindChild("coral_reef_brown_coral_tubes_02_01_LOD1").transform.localScale *= 0.4f; iBrownCoralB.FindChild("coral_reef_brown_coral_tubes_02_01_LOD2").transform.localScale *= 0.4f; iBrownCoralB.FindChild("coral_reef_brown_coral_tubes_02_01_LOD3").transform.localScale *= 0.4f; var lodBrownCoral = iBrownCoralB.GetComponent <LODGroup>(); lodBrownCoral.ForceLOD(0); LOD[] lods = lodBrownCoral.GetLODs(); lodBrownCoral.SetLODs(new LOD[] { lods[0] }); lodBrownCoral.ForceLOD(0); lodBrownCoral.size = 3.0f; iBrownCoralB.transform.localScale *= 1.4f; } // Setup brown coral 1 if (brownCoral1 != null) { GameObject iBrownCoral1 = GameObject.Instantiate(brownCoral1); iBrownCoral1.name = "BrownCoralTubes2"; iBrownCoral1.transform.parent = coral.transform; iBrownCoral1.transform.localPosition = Vector3.zero; iBrownCoral1.transform.localScale *= 0.4f; iBrownCoral1.transform.localPosition = new Vector3(iBrownCoral1.transform.localPosition.x - 0.08f, iBrownCoral1.transform.localPosition.y + 0.055f, iBrownCoral1.transform.localPosition.z - 0.1144f); iBrownCoral1.transform.localEulerAngles = new Vector3(iBrownCoral1.transform.localEulerAngles.x, iBrownCoral1.transform.localEulerAngles.y - 30.0f, iBrownCoral1.transform.localEulerAngles.z); var lwe = iBrownCoral1.GetComponent <LargeWorldEntity>(); if (lwe != null) { GameObject.DestroyImmediate(lwe); } var rbo = iBrownCoral1.GetComponent <Rigidbody>(); if (rbo != null) { GameObject.DestroyImmediate(rbo); } var lmi = iBrownCoral1.GetComponent <LiveMixin>(); if (lmi != null) { GameObject.DestroyImmediate(lmi); } var pid = iBrownCoral1.GetComponent <PrefabIdentifier>(); if (pid != null) { GameObject.DestroyImmediate(pid); } var bco = iBrownCoral1.GetComponentInChildren <BoxCollider>(); if (bco != null) { GameObject.DestroyImmediate(bco); } // Scale models iBrownCoral1.FindChild("coral_reef_brown_coral_tubes_02_03").transform.localScale *= 0.4f; iBrownCoral1.FindChild("coral_reef_brown_coral_tubes_02_03_LOD1").transform.localScale *= 0.4f; iBrownCoral1.FindChild("coral_reef_brown_coral_tubes_02_03_LOD2").transform.localScale *= 0.4f; iBrownCoral1.FindChild("coral_reef_brown_coral_tubes_02_03_LOD3").transform.localScale *= 0.4f; // Adjust LOD var lodBrownCoral = iBrownCoral1.GetComponent <LODGroup>(); if (lodBrownCoral != null) { lodBrownCoral.ForceLOD(0); LOD[] lods = lodBrownCoral.GetLODs(); lodBrownCoral.SetLODs(new LOD[] { lods[0] }); lodBrownCoral.ForceLOD(0); lodBrownCoral.size = 3.0f; } } // Adjust corals coral1.SetActive(false); // petite fougere jaune (gauche) coral2.SetActive(false); // grande fougere jaune 1 (droite) coral3.SetActive(false); // grande fougere jaune 2 (droite) coral4.SetActive(false); // grande fougere jaune 3 (droite) coral5.SetActive(false); // grande plante rose (centre gauche) coral6.SetActive(false); // corail rouge foncé a petit points blanc (droite) coral7.SetActive(false); // plante rose (droite) coral8.SetActive(false); // corail bleu foncé a pointes en spirales et bout rouge (gauche) coral9.SetActive(false); // plante rose (centre gauche) coral10.SetActive(true); // plante rose (centre gauche) coral11.SetActive(true); // algue en courone bleu/violet foncée (centre gauche) coral.transform.localScale *= 0.6f; coral10.transform.localScale *= 0.5f; coral10.transform.localPosition = new Vector3(coral10.transform.localPosition.x + 0.10f, coral10.transform.localPosition.y - 0.17f, coral10.transform.localPosition.z - 0.43f); coral11.transform.localPosition = new Vector3(coral11.transform.localPosition.x - 0.2f, coral11.transform.localPosition.y - 0.23f, coral11.transform.localPosition.z); // Adjust aquarium aquariumAnim2Geo.transform.localScale = new Vector3(aquariumAnim2Geo.transform.localScale.x * (1.0f / 0.239f), aquariumAnim2Geo.transform.localScale.y * (1.0f / 0.24f), aquariumAnim2Geo.transform.localScale.z * (1.0f / 0.239f)); aquariumAnim1Geo.transform.localScale = new Vector3(aquariumAnim1Geo.transform.localScale.x * (1.0f / 0.239f), aquariumAnim1Geo.transform.localScale.y * (1.0f / 0.24f), aquariumAnim1Geo.transform.localScale.z * (1.0f / 0.239f)); aquariumAnim2Geo.transform.localPosition = new Vector3(aquariumAnim2Geo.transform.localPosition.x, aquariumAnim2Geo.transform.localPosition.y - (0.20f * (1.0f / 0.24f)), aquariumAnim2Geo.transform.localPosition.z); aquariumAnim1Geo.transform.localPosition = new Vector3(aquariumAnim1Geo.transform.localPosition.x, aquariumAnim1Geo.transform.localPosition.y - (0.20f * (1.0f / 0.24f)), aquariumAnim1Geo.transform.localPosition.z); aquariumAnim2Geo.transform.localScale = new Vector3(aquariumAnim2Geo.transform.localScale.x * 0.50f, aquariumAnim2Geo.transform.localScale.y * 0.285f, aquariumAnim2Geo.transform.localScale.z * 0.16f); aquariumAnim1Geo.transform.localScale = new Vector3(aquariumAnim1Geo.transform.localScale.x * 0.50f, aquariumAnim1Geo.transform.localScale.y * 0.285f, aquariumAnim1Geo.transform.localScale.z * 0.16f); aquariumAnim2Geo.transform.localPosition = new Vector3(aquariumAnim2Geo.transform.localPosition.x, aquariumAnim2Geo.transform.localPosition.y, aquariumAnim2Geo.transform.localPosition.z + (0.145f * (1.0f / 0.239f))); aquariumAnim1Geo.transform.localPosition = new Vector3(aquariumAnim1Geo.transform.localPosition.x, aquariumAnim1Geo.transform.localPosition.y, aquariumAnim1Geo.transform.localPosition.z + (0.145f * (1.0f / 0.239f))); aquariumAnim2GeoAquarium.transform.localPosition = new Vector3(aquariumAnim2GeoAquarium.transform.localPosition.x, aquariumAnim2GeoAquarium.transform.localPosition.y, aquariumAnim2GeoAquarium.transform.localPosition.z - ((0.145f * 2.0f) * (1.0f / 0.16f))); aquariumAnim1GeoAquarium.transform.localPosition = new Vector3(aquariumAnim1GeoAquarium.transform.localPosition.x, aquariumAnim1GeoAquarium.transform.localPosition.y, aquariumAnim1GeoAquarium.transform.localPosition.z - ((0.145f * 2.0f) * (1.0f / 0.16f))); // Adjust fish aquariumAnim2Attach4.transform.localScale = new Vector3(aquariumAnim2Attach4.transform.localScale.x * 2.2f, aquariumAnim2Attach4.transform.localScale.y * 2.2f, aquariumAnim2Attach4.transform.localScale.z * 2.2f); // Adjust animators Animator anim = aquariumAnim1.GetComponent <Animator>(); anim.transform.localScale = new Vector3(anim.transform.localScale.x * 0.239f, anim.transform.localScale.y * 0.24f, anim.transform.localScale.z * 0.239f); anim.transform.localPosition = new Vector3(anim.transform.localPosition.x + 0.145f, anim.transform.localPosition.y + 0.20f, anim.transform.localPosition.z); Animator anim2 = aquariumAnim2.GetComponent <Animator>(); anim2.transform.localScale = new Vector3(anim2.transform.localScale.x * 0.239f, anim2.transform.localScale.y * 0.24f, anim2.transform.localScale.z * 0.239f); anim2.transform.localPosition = new Vector3(anim2.transform.localPosition.x + 0.145f, anim2.transform.localPosition.y + 0.20f, anim2.transform.localPosition.z); // Adjust bubbles bubbles.transform.localScale = new Vector3(bubbles.transform.localScale.x * 0.07f, bubbles.transform.localScale.y * 0.07f, bubbles.transform.localScale.z * 0.07f); xBubbles.transform.localScale = new Vector3(xBubbles.transform.localScale.x * 0.07f, xBubbles.transform.localScale.y * 0.07f, xBubbles.transform.localScale.z * 0.07f); xBubbles.transform.localPosition = new Vector3(xBubbles.transform.localPosition.x + 4.0f, xBubbles.transform.localPosition.y + 1.0f, xBubbles.transform.localPosition.z); var ps = xBubbles.GetComponent <ParticleSystem>(); var psr = xBubbles.GetComponent <ParticleSystemRenderer>(); #pragma warning disable CS0618 ps.startSize *= 0.5f; ps.startLifetime *= 0.18f; ps.startSpeed = 0f; ps.emissionRate = 6f; ps.maxParticles = 5; ps.playbackSpeed *= 0.4f; #pragma warning restore CS0618 psr.lengthScale *= 0.35f; psr.maxParticleSize *= 0.35f; foreach (Transform tr in xBubbles.transform) { tr.localPosition = new Vector3(0.5f, 0.0f, 0.0f); psr = tr.GetComponent <ParticleSystemRenderer>(); if (tr.name.StartsWith("xDots", true, CultureInfo.InvariantCulture)) { ps = tr.GetComponent <ParticleSystem>(); #pragma warning disable CS0618 ps.startSize *= 0.3f; ps.startLifetime *= 0.11f; ps.startSpeed = 0.3f; ps.emissionRate = 3f; ps.maxParticles = 6; ps.playbackSpeed *= 0.5f; #pragma warning restore CS0618 psr.lengthScale *= 0.11f; psr.maxParticleSize *= 0.11f; } else if (tr.name.StartsWith("xLateralBubbles", true, CultureInfo.InvariantCulture)) { psr.enabled = false; } } // Adjust prefab identifier var prefabId = prefab.GetComponent <PrefabIdentifier>(); prefabId.ClassId = this.ClassID; // Adjust tech tag var techTag = prefab.GetComponent <TechTag>(); techTag.type = this.TechType; // Adjust contructable Constructable constructable = prefab.GetComponent <Constructable>(); constructable.allowedInBase = true; constructable.allowedInSub = true; constructable.allowedOutside = true; constructable.allowedOnCeiling = false; constructable.allowedOnGround = true; constructable.allowedOnConstructables = true; #if BELOWZERO constructable.allowedUnderwater = true; #endif constructable.controlModelState = true; constructable.deconstructionAllowed = true; constructable.rotationEnabled = true; //constructable.model = model; constructable.techType = this.TechType; constructable.enabled = true; // Adjust constructable bounds ConstructableBounds bounds = prefab.GetComponent <ConstructableBounds>(); bounds.bounds = new OrientedBounds(new Vector3((bounds.bounds.position.x * 0.16f) + (0.145f * 2.0f), bounds.bounds.position.y * 0.285f, bounds.bounds.position.z * 0.5f), bounds.bounds.rotation, new Vector3(bounds.bounds.extents.x * 0.16f, bounds.bounds.extents.y * 0.285f, bounds.bounds.extents.z * 0.5f)); // Adjust collider BoxCollider c = collider.GetComponent <BoxCollider>(); c.size = new Vector3(c.size.x * 0.16f, c.size.y * 0.285f, c.size.z * 0.5f); c.center = new Vector3((c.center.x * 0.16f) + (0.145f * 2.0f), c.center.y * 0.285f, c.center.z * 0.5f); // Adjust aquarium var aquarium = prefab.GetComponent <Aquarium>(); aquarium.storageContainer.width = 1; aquarium.storageContainer.height = 1; aquarium.trackObjects = new GameObject[] { aquariumAnim2Attach4 }; // Adjust rendering var sas = prefab.GetComponents <SkyApplier>(); List <Renderer> rendsA = new List <Renderer>(); List <Renderer> rendsB = new List <Renderer>(); int i = 0; foreach (SkyApplier sa in sas) { foreach (Renderer rend in sa.renderers) { if (string.Compare(rend.name, "Aquarium", true, CultureInfo.InvariantCulture) != 0) { if (ConfigSwitcher.GlowingAquariumGlass && string.Compare(rend.name, "Aquarium_glass", true, CultureInfo.InvariantCulture) == 0) { foreach (Material mat in rend.materials) { mat.EnableKeyword("MARMO_EMISSION"); mat.EnableKeyword("MARMO_GLOW"); mat.SetFloat("_SpecInt", 16f); mat.SetFloat("_EnableGlow", 1); mat.SetColor("_GlowColor", new Color(0.79f, 0.9785799f, 1.0f, 0.08f)); mat.SetFloat("_GlowStrength", 0.18f); } } if (i == 0) { rendsA.Add(rend); } else { rendsB.Add(rend); } } } i++; } sas[0].renderers = rendsA.ToArray(); sas[1].renderers = rendsB.ToArray(); Renderer[] tmpRends = prefab.GetAllComponentsInChildren <Renderer>(); List <Renderer> rends = new List <Renderer>(); foreach (Renderer tmpRend in tmpRends) { if (string.Compare(tmpRend.name, "Aquarium", true, CultureInfo.InvariantCulture) == 0) { rends.Add(tmpRend); } } var fixedSa = prefab.AddComponent <SkyApplier>(); fixedSa.anchorSky = Skies.Auto; fixedSa.dynamic = true; fixedSa.renderers = rends.ToArray(); fixedSa.updaterIndex = 0; // Adjust bubbles LOD var lodBubbles = bubbles.GetComponent <LODGroup>(); lodBubbles.size *= (1.0f / 0.07f); // Remove unwanted elements GameObject.DestroyImmediate(aquariumAnim2Fish1); GameObject.DestroyImmediate(aquariumAnim2Fish2); GameObject.DestroyImmediate(aquariumAnim2Fish3); GameObject.DestroyImmediate(aquariumAnim1Fish1); GameObject.DestroyImmediate(aquariumAnim1Fish2); GameObject.DestroyImmediate(aquariumAnim1Fish3); GameObject.DestroyImmediate(aquariumAnim1Fish4); // Adjust prefab position foreach (Transform tr in prefab.transform) { tr.transform.localPosition = new Vector3(tr.transform.localPosition.x - 0.29f, tr.transform.localPosition.y, tr.transform.localPosition.z); } return(prefab); }
// Token: 0x06000E20 RID: 3616 RVA: 0x00064CCC File Offset: 0x00062ECC private void UpdateMesh() { MineRock5.m_tempInstancesA.Clear(); MineRock5.m_tempInstancesB.Clear(); Material y = this.m_meshRenderer.sharedMaterials[0]; Matrix4x4 inverse = base.transform.localToWorldMatrix.inverse; for (int i = 0; i < this.m_hitAreas.Count; i++) { MineRock5.HitArea hitArea = this.m_hitAreas[i]; if (hitArea.m_health > 0f) { CombineInstance item = default(CombineInstance); item.mesh = hitArea.m_meshFilter.sharedMesh; item.transform = inverse * hitArea.m_meshFilter.transform.localToWorldMatrix; for (int j = 0; j < hitArea.m_meshFilter.sharedMesh.subMeshCount; j++) { item.subMeshIndex = j; if (hitArea.m_meshRenderer.sharedMaterials[j] == y) { MineRock5.m_tempInstancesA.Add(item); } else { MineRock5.m_tempInstancesB.Add(item); } } hitArea.m_meshRenderer.enabled = false; hitArea.m_collider.gameObject.SetActive(true); } else { hitArea.m_collider.gameObject.SetActive(false); } } if (MineRock5.m_tempMeshA == null) { MineRock5.m_tempMeshA = new Mesh(); MineRock5.m_tempMeshB = new Mesh(); } MineRock5.m_tempMeshA.CombineMeshes(MineRock5.m_tempInstancesA.ToArray()); MineRock5.m_tempMeshB.CombineMeshes(MineRock5.m_tempInstancesB.ToArray()); CombineInstance combineInstance = default(CombineInstance); combineInstance.mesh = MineRock5.m_tempMeshA; CombineInstance combineInstance2 = default(CombineInstance); combineInstance2.mesh = MineRock5.m_tempMeshB; this.m_meshFilter.mesh.CombineMeshes(new CombineInstance[] { combineInstance, combineInstance2 }, false, false); this.m_meshRenderer.enabled = true; Renderer[] array = new Renderer[this.m_extraRenderers.Count + 1]; this.m_extraRenderers.CopyTo(0, array, 0, this.m_extraRenderers.Count); array[array.Length - 1] = this.m_meshRenderer; LODGroup component = base.gameObject.GetComponent <LODGroup>(); LOD[] lods = component.GetLODs(); lods[0].renderers = array; component.SetLODs(lods); }
void loadSubTree(GameObject parent, PiXYZ4UnityWrapper.ScenePath subTree, int currentMateriaId, bool editor, UnityEngine.Object prefab, bool importLines, int curLOD, ref Dictionary <int, List <Renderer> > lodToRenderers, ref Dictionary <int, double> lodToThreshold, bool isMaterialOverride = false) { if (!isPart(subTree.node()) && !isAssembly(subTree.node()) || isHidden(subTree)) //Last part is HOOPS workaround. { return; //no light or camera } GameObject obj = new GameObject(); Transform parentTransform = parent != null ? parent.transform : null; obj.name = PiXYZ4UnityWrapper.getNodeName(subTree.node()); obj.transform.parent = parentTransform; Matrix4x4 matrix = PiXYZ4UnityWrapper.getLocalMatrix(subTree.node()); int parentInstance = subTree.parentInstance(); if (parentInstance > 0) { Matrix4x4 parentMatrix = PiXYZ4UnityWrapper.getLocalMatrix(parentInstance); matrix = parentMatrix * matrix; } SetTransformFromMatrix(obj.transform, ref matrix); if (parent == null) //apply mirror and rotation once { lastImportedObject = obj; obj.transform.localScale *= _scale; if (_mirrorX) { obj.transform.localScale = new Vector3(-obj.transform.localScale.x, obj.transform.localScale.y, obj.transform.localScale.z); } if (_rotation.eulerAngles.sqrMagnitude > 0) { obj.transform.localRotation = _rotation; } } if (!isMaterialOverride || isAssembly(subTree.node()) || currentMateriaId == 0) { int materialId = PiXYZ4UnityWrapper.getOccurrenceMaterial(subTree); if (materialId > 0) { currentMateriaId = materialId; } } int lodCount = 0; bool isLodGroup = PiXYZ4UnityWrapper.isLODGroup(subTree.node(), out lodCount); if (_lodsMode != LODsMode.NONE) { if (isLodGroup) { lodToRenderers.Clear(); lodToThreshold.Clear(); } if (PiXYZ4UnityWrapper.isLOD(subTree.node())) { double threshold; curLOD = PiXYZ4UnityWrapper.getLODNumber(subTree.node(), out threshold); if (!lodToThreshold.ContainsKey(curLOD)) { lodToThreshold.Add(curLOD, threshold); } } } if (isPart(subTree.node())) { loadPart(obj, subTree.node(), currentMateriaId, editor, prefab, importLines, curLOD, ref lodToRenderers); } else if (isAssembly(subTree.node())) { foreach (PiXYZ4UnityWrapper.ScenePath child in PiXYZ4UnityWrapper.getChildren(subTree)) { try { loadSubTree(obj, child, currentMateriaId, editor, prefab, importLines, curLOD, ref lodToRenderers, ref lodToThreshold, isMaterialOverride || isAssembly(subTree.node())); } catch (KeyNotFoundException knf) { Debug.LogError("Key not found: " + knf.ToString()); } } } if (_lodsMode != LODsMode.NONE && isLodGroup) { LOD[] lods = new LOD[lodCount]; const double e = 0.00001; double minThreshold = 1; for (int iLOD = 0; iLOD < lodCount; ++iLOD) { double threshold = Math.Min(lodToThreshold[iLOD], minThreshold); if (!lodToRenderers.ContainsKey(iLOD)) { Debug.LogError("Key '" + iLOD + "' not found."); continue; } Renderer[] renderers = new Renderer[lodToRenderers[iLOD].Count]; for (int iRenderer = 0; iRenderer < lodToRenderers[iLOD].Count; ++iRenderer) { renderers[iRenderer] = lodToRenderers[iLOD][iRenderer]; } lods.SetValue(new LOD((float)threshold, renderers), iLOD); minThreshold = threshold - e; } LODGroup lodGroup = obj.AddComponent <LODGroup>(); lodGroup.SetLODs(lods); lodToRenderers.Clear(); lodToThreshold.Clear(); } }
protected override void OnFinished() { GameObject go = null; try { if (filename.Contains("_terrain_")) { TerrainObj tobj = parent.gameObject.GetComponent <TerrainObj>(); if (tobj == null) { parent.gameObject.AddComponent <TerrainObj>(); } else { tobj.enabled = true; } } count--; // This is executed by the Unity main thread when the job is finished if (niffile != null) { go = NIFLoader.loadNIF(niffile, filename); if (lodfile != null) { GameObject lodgo = NIFLoader.loadNIF(lodfile, filename); // terrain lod LODGroup group = parent.gameObject.GetComponent <LODGroup>(); if (group == null) { group = parent.gameObject.AddComponent <LODGroup>(); } group.enabled = true; group.animateCrossFading = true; group.fadeMode = LODFadeMode.SpeedTree; LOD[] lods = new LOD[2]; Renderer[] renderersMax = go.GetComponentsInChildren <Renderer>(); Renderer[] renderersLow = lodgo.GetComponentsInChildren <Renderer>(); lods[0] = new LOD(0.6f, renderersMax); lods[1] = new LOD(0.03f, renderersLow); //lods[1] = new LOD(1f - LODCutoff, renderers); group.SetLODs(lods); GameObject lodObj = new GameObject(); lodObj.name = "LOD-" + filename; lodgo.transform.SetParent(lodObj.transform); lodObj.transform.SetParent(go.transform); } lock (originals) { originals[filename] = go; } } else { go = getCachedObject(filename); } if (go != null) { if (Assets.GameWorld.useColliders) { GameObject.Destroy(parent.GetComponent <BoxCollider>()); GameObject.Destroy(parent.GetComponent <SphereCollider>()); } go.transform.SetParent(parent.transform); go.transform.localScale = Vector3.one; go.transform.localPosition = Vector3.zero; go.transform.localRotation = Quaternion.identity; if (parent.gameObject.GetComponent <LODGroup>() != null) { parent.gameObject.GetComponent <LODGroup>().RecalculateBounds(); } } } catch (Exception ex) { Debug.LogWarning("Unable to load nif:" + niffile + " " + filename); Debug.Log(ex); if (null != go) { GameObject.Destroy(go); } } finally { if (cacheWait.ContainsKey(filename)) { cacheWait[filename].Release(); } } }
public void BuildPrefabLod() { #if UNITY_EDITOR string path = EditorUtility.SaveFilePanelInProject("Save prefab", "", "prefab", "Please enter a file name to save the prefab to"); if (path.Length == 0) { return; } string prefabName = Path.GetFileNameWithoutExtension(path); string directory = Path.GetDirectoryName(path); string prefabFilename = path; string meshFilenameLod0 = directory + "/" + prefabName + "_LOD0.asset"; string meshFilenameLod1 = directory + "/" + prefabName + "_LOD1.asset"; string meshFilenameLod2 = directory + "/" + prefabName + "_LOD2.asset"; string materialFilename = Path.ChangeExtension(prefabFilename, ".mat"); Vector3 oldPosition = transform.position; Quaternion oldRotation = transform.rotation; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; //string patchID = Time.realtimeSinceStartup.ToString(); Material material; if (CustomMaterial) { material = new Material(CustomMaterial); material.SetTexture("_MainTex", GrassTexture); } else { material = new Material(Shader.Find("AwesomeTechnologies/Grass/Grass")); material.SetTexture("_MainTex", GrassTexture); material.SetColor("_Color", ColorTint1); material.SetColor("_ColorB", ColorTint2); material.SetFloat("_Cutoff", TextureCutoff); material.SetFloat("_RandomDarkening", RandomDarkening); material.SetFloat("_RootAmbient", RootAmbient); material.SetVector("_AG_ColorNoiseArea", new Vector4(0, 30, 0, 1)); material.SetTexture("_AG_ColorNoiseTex", Resources.Load("PerlinSeamless") as Texture2D); material.EnableKeyword("_ALPHATEST_ON"); } AssetDatabase.CreateAsset(material, materialFilename); GameObject go = new GameObject { name = prefabName }; // "New grass patch_" + patchID; go.transform.position = transform.position; go.transform.rotation = transform.localRotation; Mesh meshLod0 = GetCombinedMesh(0); Mesh meshLod1 = GetCombinedMesh(1); Mesh meshLod2 = GetCombinedMesh(2); GameObject goLod0 = new GameObject { name = prefabName + "_LOD0" }; goLod0.transform.SetParent(go.transform, false); goLod0.AddComponent <MeshFilter>().sharedMesh = meshLod0; goLod0.AddComponent <MeshRenderer>().sharedMaterial = material; GameObject goLod1 = new GameObject { name = prefabName + "_LOD1" }; goLod1.transform.SetParent(go.transform, false); goLod1.AddComponent <MeshFilter>().sharedMesh = meshLod1; goLod1.AddComponent <MeshRenderer>().sharedMaterial = material; GameObject goLod2 = new GameObject { name = prefabName + "_LOD2" }; goLod2.transform.SetParent(go.transform, false); goLod2.AddComponent <MeshFilter>().sharedMesh = meshLod2; goLod2.AddComponent <MeshRenderer>().sharedMaterial = material; AssetDatabase.CreateAsset(meshLod0, meshFilenameLod0); AssetDatabase.CreateAsset(meshLod1, meshFilenameLod1); AssetDatabase.CreateAsset(meshLod2, meshFilenameLod2); LODGroup lodGroup = go.AddComponent <LODGroup>(); LOD[] lods = new LOD[4]; lods[0] = CreateLOD(goLod0, 1f); lods[1] = CreateLOD(goLod0, 0.50f); lods[2] = CreateLOD(goLod1, 0.15f); lods[3] = CreateLOD(goLod2, 0.05f); lodGroup.SetLODs(lods); transform.position = oldPosition; transform.rotation = oldRotation; #if UNITY_2018_3_OR_NEWER PrefabUtility.SaveAsPrefabAsset(go, prefabFilename); #else PrefabUtility.CreatePrefab(prefabFilename, go); #endif AssetDatabase.Refresh(); #endif }
private void BuildTreeTypeCellMesh(GameObject owner, TreeSystemStructuredTrees cell, List <TreeSystemStoredInstance> trees, TreeSystemPrototypeData data) { int[] originalTriangles = m_SystemQuad.triangles; RowCol pos = cell.m_Position; GameObject mesh = new GameObject(); // Mark object as static GameObjectUtility.SetStaticEditorFlags(mesh, StaticEditorFlags.OccludeeStatic | StaticEditorFlags.ReflectionProbeStatic); mesh.transform.SetParent(owner.transform); mesh.name = "MeshCell[" + pos.m_Row + "_" + pos.m_Col + "_" + data.m_TreePrototype.name + "]"; Vector3 worldScale = new Vector3(data.m_Size.x, data.m_Size.y, data.m_Size.x); // Set material MeshRenderer rend = mesh.AddComponent <MeshRenderer>(); rend.sharedMaterial = data.m_BillboardBatchMaterial; MeshFilter filter = mesh.AddComponent <MeshFilter>(); Mesh treeMesh = new Mesh(); treeMesh.name = "TreeCell[" + pos.m_Row + "_" + pos.m_Col + "_" + data.m_TreePrototype.name + "]"; List <Vector4> m_TempWorldPositions = new List <Vector4>(); List <Vector3> m_TempWorldScales = new List <Vector3>(); List <Vector3> m_TempQuadVertices = new List <Vector3>(); List <Vector4> m_TempQuadTangents = new List <Vector4>(); List <Vector3> m_TempQuadNormals = new List <Vector3>(); List <int> m_TempQuadIndices = new List <int>(); Bounds newBounds = new Bounds(); newBounds.center = cell.m_BoundsBox.center; // TODO: populate mesh data for (int treeIndex = 0; treeIndex < trees.Count; treeIndex++) { Vector3 position = trees[treeIndex].m_WorldPosition; Vector3 scale = trees[treeIndex].m_WorldScale; float rot = trees[treeIndex].m_WorldRotation; // Offset world position, by the grounding factor Vector3 instancePos = position; instancePos.y += data.m_Size.z; // Scale by the world scale too so that we don't have to do an extra multip Vector3 instanceScale = scale; instanceScale.Scale(worldScale); // Encapsulate bottom and top also newBounds.Encapsulate(instancePos); newBounds.Encapsulate(instancePos + new Vector3(0, data.m_Size.y, 0)); // Add the world and scale data for (int index = 0; index < 4; index++) { Vector4 posAndRot = instancePos; posAndRot.w = rot; m_TempWorldPositions.Add(posAndRot); m_TempWorldScales.Add(instanceScale); } // Add stanard quad data m_TempQuadVertices.AddRange(m_SystemQuad.vertices); m_TempQuadTangents.AddRange(m_SystemQuad.tangents); m_TempQuadNormals.AddRange(m_SystemQuad.normals); // Calculate triangle indixes m_TempQuadIndices.AddRange(originalTriangles); for (int triIndex = 0; triIndex < 6; triIndex++) { // Just add to the triangles the existing triangles + the new indices m_TempQuadIndices[triIndex + 6 * treeIndex] = originalTriangles[triIndex] + 4 * treeIndex; } } treeMesh.Clear(); // Set standard data treeMesh.SetVertices(m_TempQuadVertices); treeMesh.SetNormals(m_TempQuadNormals); treeMesh.SetTangents(m_TempQuadTangents); // Set the custom data treeMesh.SetUVs(1, m_TempWorldPositions); treeMesh.SetUVs(2, m_TempWorldScales); // Set triangles and do not calculate bounds treeMesh.SetTriangles(m_TempQuadIndices, 0, false); // Set the manually calculated bounds treeMesh.bounds = newBounds; treeMesh.UploadMeshData(true); // Set the mesh filter.mesh = treeMesh; // Add the mesh' lod group if (m_AddLODGroupToBillboards) { LODGroup group = mesh.AddComponent <LODGroup>(); group.animateCrossFading = false; group.fadeMode = LODFadeMode.None; group.SetLODs(new LOD[] { new LOD(m_BillboardScreenSize, new Renderer[] { rend }) }); group.RecalculateBounds(); } }
void CreateMergedLODGroupFromSingleMaterialMeshes() { string path = EditorUtility.SaveFilePanelInProject("Save merged mesh", "", "", "Please enter a file name to save the merged mesh to"); if (path.Length != 0) { if (_lodGroupVegetationMeshCombiner.TargetGameObject == null) { return; } LODGroup lodGroup = _lodGroupVegetationMeshCombiner.TargetGameObject.GetComponentInChildren <LODGroup>(); GameObject sourceObject = _lodGroupVegetationMeshCombiner.TargetGameObject; Vector3 targetPosition = sourceObject.transform.position; Quaternion targetRotation = sourceObject.transform.rotation; Vector3 targetScale = sourceObject.transform.localScale; sourceObject.transform.position = new Vector3(0, 0, 0); sourceObject.transform.rotation = Quaternion.identity; sourceObject.transform.localScale = Vector3.one; if (lodGroup == null) { return; } GameObject mergedLODGroupObject = new GameObject("Merged_" + sourceObject.name); LODGroup newLODGroup = mergedLODGroupObject.AddComponent <LODGroup>(); List <CombineInstance> combineInstanceList = new List <CombineInstance>(); LOD[] lods = lodGroup.GetLODs(); // ReSharper disable once InconsistentNaming LOD[] newLODs = lodGroup.GetLODs(); for (int i = 0; i <= lods.Length - 1; i++) { combineInstanceList.Clear(); LOD lod = lods[i]; if (lod.renderers.Length > 0) { GameObject lodObject = new GameObject(sourceObject.name + "_LOD" + i.ToString()); lodObject.transform.SetParent(mergedLODGroupObject.transform); MeshRenderer meshRenderer = lodObject.AddComponent <MeshRenderer>(); MeshFilter meshFilter = lodObject.AddComponent <MeshFilter>(); Renderer[] newRenderers = new Renderer[1]; newRenderers[0] = meshRenderer; newLODs[i].renderers = newRenderers; List <Material> materialList = new List <Material>(); for (int j = 0; j <= lod.renderers.Length - 1; j++) { MeshFilter tempMeshFilter = lod.renderers[j].gameObject.GetComponent <MeshFilter>(); if (!tempMeshFilter) { continue; } CombineInstance combineInstance = new CombineInstance { mesh = tempMeshFilter.sharedMesh, transform = meshFilter.transform.localToWorldMatrix }; combineInstanceList.Add(combineInstance); materialList.Add(lod.renderers[j].sharedMaterial); } Mesh mesh = new Mesh(); Material[] materials = materialList.ToArray(); mesh.CombineMeshes(combineInstanceList.ToArray(), false, true); if (_lodGroupVegetationMeshCombiner.MergeSubmeshesWitEquialMaterial) { SubmeshCombiner submeshCombiner = new SubmeshCombiner(); for (int j = 0; j <= mesh.subMeshCount - 1; j++) { submeshCombiner.AddSubmesh(mesh.GetIndices(j), materials[j]); } submeshCombiner.UpdateMesh(mesh); materials = submeshCombiner.GetMaterials(); } meshFilter.sharedMesh = mesh; AssetDatabase.CreateAsset(meshFilter.sharedMesh, path + "_LOD" + i.ToString() + ".asset"); meshRenderer.materials = materials; } } newLODGroup.SetLODs(newLODs); sourceObject.transform.position = targetPosition; sourceObject.transform.rotation = targetRotation; sourceObject.transform.localScale = targetScale; } }
public static void GenerateLODs(LODGroup lodGroup, HashSet <Mesh> newMeshes = null) { LOD[] lods = lodGroup.GetLODs(); // Cleanup for (int i = 1; i < lods.Length; i++) { foreach (Renderer renderer in lods[i].renderers) { if (renderer != null) { Object.DestroyImmediate(renderer.gameObject); } } } if (newMeshes == null) { newMeshes = new HashSet <Mesh>(); } // Assign LOD0 Renderer[] renderers = lodGroup.GetComponentsInChildren <Renderer>(); lods[0].renderers = renderers; Dictionary <Mesh, ConnectedMesh> uniqueMeshes = new Dictionary <Mesh, ConnectedMesh>(); foreach (Renderer renderer in renderers) { if (renderer is MeshRenderer meshRenderer) { MeshFilter meshFilter = renderer.gameObject.GetComponent <MeshFilter>(); if (meshFilter) { Mesh mesh = meshFilter.sharedMesh; if (!uniqueMeshes.ContainsKey(mesh)) { uniqueMeshes.TryAdd(mesh, m => UnityConverter.ToSharedMesh(m).ToConnectedMesh()); } } } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { Mesh mesh = skinnedMeshRenderer.sharedMesh; if (!uniqueMeshes.ContainsKey(mesh)) { uniqueMeshes.TryAdd(mesh, m => UnityConverter.ToSharedMesh(m).ToConnectedMesh()); } } } foreach (KeyValuePair <Mesh, ConnectedMesh> uniqueMesh in uniqueMeshes) { uniqueMesh.Value.MergePositions(0.0001); uniqueMesh.Value.MergeAttributes(); uniqueMesh.Value.Compact(); } SceneDecimator sceneDecimator = new SceneDecimator(); sceneDecimator.Initialize(uniqueMeshes.Values); // Build LODs for (int i = 1; i < lods.Length; i++) { // Decimates gradually sceneDecimator.DecimateToRatio(lods[i - 1].screenRelativeTransitionHeight); Dictionary <Mesh, Mesh> optimizedMeshes = uniqueMeshes.ToDictionary(x => x.Key, x => x.Value.ToSharedMesh().ToUnityMesh()); List <Renderer> lodRenderers = new List <Renderer>(); foreach (Renderer renderer in renderers) { if (renderer is MeshRenderer meshRenderer) { MeshFilter meshFilter = renderer.gameObject.GetComponent <MeshFilter>(); if (meshFilter) { GameObject gameObject = new GameObject(renderer.gameObject.name + "_LOD" + i); gameObject.transform.parent = renderer.transform; gameObject.transform.localPosition = UnityEngine.Vector3.zero; gameObject.transform.localRotation = UnityEngine.Quaternion.identity; gameObject.transform.localScale = UnityEngine.Vector3.one; MeshRenderer mr = gameObject.AddComponent <MeshRenderer>(); MeshFilter mf = gameObject.AddComponent <MeshFilter>(); Mesh originalMesh = meshFilter.sharedMesh; Mesh optimizedMesh = optimizedMeshes[originalMesh]; // Todo : Don't create new mesh if it's the same (tri count); optimizedMesh.name = originalMesh.name + "_LOD" + i; mr.sharedMaterials = meshRenderer.sharedMaterials; mf.sharedMesh = optimizedMesh; newMeshes.Add(optimizedMesh); lodRenderers.Add(mr); } } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { GameObject gameObject = new GameObject(renderer.gameObject.name + "_LOD" + i); gameObject.transform.parent = renderer.transform; gameObject.transform.localPosition = UnityEngine.Vector3.zero; gameObject.transform.localRotation = UnityEngine.Quaternion.identity; gameObject.transform.localScale = UnityEngine.Vector3.one; SkinnedMeshRenderer smr = gameObject.AddComponent <SkinnedMeshRenderer>(); smr.bones = skinnedMeshRenderer.bones; smr.rootBone = skinnedMeshRenderer.rootBone; Mesh originalMesh = skinnedMeshRenderer.sharedMesh; Mesh optimizedMesh = optimizedMeshes[originalMesh]; // Todo : Don't create new mesh if it's the same (tri count); optimizedMesh.name = originalMesh.name + "_LOD" + i; smr.sharedMaterials = skinnedMeshRenderer.sharedMaterials; smr.sharedMesh = optimizedMesh; optimizedMesh.bindposes = originalMesh.bindposes; // Copy poses newMeshes.Add(optimizedMesh); lodRenderers.Add(smr); } } ///Debug.Log($"LOD{i} created with {lodRenderers.Count} renderers at {100f * lods[i - 1].screenRelativeTransitionHeight}% poly ratio"); lods[i].renderers = lodRenderers.ToArray(); } lodGroup.SetLODs(lods); }
//READING / SAVING XML FILE public void ReadXMLTiles() { var tileContainer = TileCollection.Load(Path.Combine(Application.dataPath, "Tiles.xml")); // var xmlData = @"<TileCollection><tiles><Tiles name=""a""><model_path></model_path>x<material_path>y</material_path></Tiles></tiles></TileCollection>"; // var tileContainer = TileCollection.LoadFromText(xmlData); // Debug.Log("Number of tiles in database: " + tileContainer.tiles.Length); // Debug.Log(tileContainer.tiles[0].model_path); // AddButton(tileContainer.tiles.Length); //ADD BUTTONS TO UI var parentDatabase = new GameObject(); parentDatabase.name = "Tile_Database"; parentDatabase.layer = 10; for (int c = 0; c < tileContainer.tiles.Length; c++) { FilePath = tileContainer.tiles[c].model_path; Debug.Log(tileContainer.tiles[c].model_path); // FilePath = "Models/Tiles/Floors/nukeguard/mesh1"; GameObject model = Resources.Load <GameObject>(FilePath); GameObject obj = (GameObject)Instantiate(model); // obj.AddComponent(typeof(LODGroup)); foreach (Transform child in obj.transform) { child.gameObject.layer = 10; } // obj.SetActive(false); obj.transform.SetParent(parentDatabase.transform); // obj.name = tileContainer.tiles[c].Name; obj.name = c.ToString(); newButton = Instantiate(Button); but = newButton.GetComponent <SelectTileButton>(); but.TileID = c; newButton.GetComponentInChildren <Text>().text = tileContainer.tiles[c].Name; newButton.transform.SetParent(BuildingMenu.transform); // TO REMOVE WHEN ALL TILES IS UNIFIED if (obj.transform.Find("Camera") != null) { obj.transform.Find("Camera").GetComponent <Camera>().enabled = false; } // END REMOVE //obj.GetComponent<LODGroup>(). // /* if (obj.transform.Find("model") != null) { group = obj.AddComponent <LODGroup>(); // Add 4 LOD levels LOD[] lods = new LOD[4]; for (int i = 0; i < 4; i++) { GameObject primType = obj.transform.Find("model").gameObject; switch (i) { case 1: primType = obj.transform.Find("lod1").gameObject; break; case 2: primType = obj.transform.Find("lod2").gameObject; break; case 3: primType = obj.transform.Find("lod3").gameObject; break; } Renderer[] renderers = new Renderer[1]; renderers[0] = primType.GetComponentInChildren <Renderer>(); lods[i] = new LOD(1.0F / (i + 1.2f), renderers); } group.SetLODs(lods); group.RecalculateBounds(); } } }
private static void ParseFile_SceneShapesAttributes(XmlReader xml, ref I3DModel model, Entity part) { Entity.ShapeType type; if (!Enum.TryParse(xml.LocalName, out type)) { throw new Exception($"Unrecognized shape type {xml.LocalName}"); } part.Type = type; string name = ParseString(xml.GetAttribute("name")); //I3DTransform I3DTransform t = part.gameObject.AddComponent <I3DTransform>(); t.Name = name; t.Id = ParseInt(xml.GetAttribute("nodeId")); t.IndexPath = ""; //TODO: Make this t.Visibility = ParseBool(xml.GetAttribute("visibility"), true); t.ClipDistance = ParseInt(xml.GetAttribute("clipDistance"), 1000000); t.MinClipDistance = ParseInt(xml.GetAttribute("minClipDistance")); t.ObjectMask = ParseInt(xml.GetAttribute("objectMask"), 0xffff); t.LOD = ParseBool(xml.GetAttribute("lodDistance")); //Transform part.gameObject.transform.localPosition = ParseVector3(xml.GetAttribute("translation")); part.gameObject.transform.localEulerAngles = ParseVector3(xml.GetAttribute("rotation")); Vector3 scale = xml.GetAttribute("scale") != null?ParseVector3(xml.GetAttribute("scale")) : Vector3.one; //scale.x *= -1; part.gameObject.transform.localScale = scale; //Rigidbody bool bStatic = ParseBool(xml.GetAttribute("static")); bool bDynamic = ParseBool(xml.GetAttribute("dynamic")); bool bKinematic = ParseBool(xml.GetAttribute("kinematic")); if (bStatic || bDynamic || bKinematic) { t.RigidBody = true; I3DRigidBody r = part.gameObject.AddComponent <I3DRigidBody>(); if (bStatic) { r.Type = RigidBodyType.Static; } else if (bDynamic) { r.Type = RigidBodyType.Dynamic; } else { r.Type = RigidBodyType.Kinematic; } r.Compound = ParseBool(xml.GetAttribute("compound")); r.CompoundChild = ParseBool(xml.GetAttribute("compoundChild")); r.Collision = ParseBool(xml.GetAttribute("collision"), true); r.Trigger = ParseBool(xml.GetAttribute("trigger")); r.CollisionMask = ParseInt(xml.GetAttribute("collisionMask")); r.Restitution = ParseFloat(xml.GetAttribute("restitution")); r.StaticFriction = ParseFloat(xml.GetAttribute("staticFriction"), 0.5f); r.DynamicFriction = ParseFloat(xml.GetAttribute("dynamicFriction"), 0.5f); r.LinearDamping = ParseFloat(xml.GetAttribute("linearDamping"), 0.5f); r.AngularDamping = ParseFloat(xml.GetAttribute("angularDamping"), 0.5f); r.Density = ParseFloat(xml.GetAttribute("density"), 1); r.SolverIterations = ParseInt(xml.GetAttribute("solverIterationCount"), 4); //r.Mass = ParseFloat(xml.GetAttribute("mass"), 0.5f); } //Shape if (part.Type == Entity.ShapeType.Shape) { if (name.EndsWith("_lod0") || name.EndsWith("_lod1") || name.EndsWith("_lod2")) { Transform parent = part.transform.parent; LODGroup lodGroup = parent.GetComponent <LODGroup>(); if (lodGroup == null) { lodGroup = parent.gameObject.AddComponent <LODGroup>(); lodGroup.SetLODs(new LOD[] {}); } int lodIndex = ParseInt(name.Substring(name.Length - 1)); LOD lod = new LOD { renderers = new Renderer[] { part.GetComponent <MeshRenderer>() } }; List <LOD> lods = lodGroup.GetLODs().ToList(); if (lodIndex > lods.Count) { lods.Add(lod); } else { lods.Insert(lodIndex, lod); } // Update the transition point for all LODs float lodGap = 1f / lods.Count; for (int i = 0; i < lods.Count; i++) { lods[i] = new LOD((lods.Count - i - 1) * lodGap, lods[i].renderers); } lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); } Shape s = part.gameObject.AddComponent <Shape>(); s.ID = ParseInt(xml.GetAttribute("shapeId")); s.CastShadows = ParseBool(xml.GetAttribute("castsShadows")); s.ReceiveShadows = ParseBool(xml.GetAttribute("receiveShadows")); s.NonRenderable = ParseBool(xml.GetAttribute("nonRenderable")); s.BuildNavMeshMask = ParseInt(xml.GetAttribute("buildNavMeshMask")); s._Materials = Shape.ParseMaterialString(ParseString(xml.GetAttribute("materialIds"))); part.Shape = s; //Assign the shape object according to ID foreach (I3DShapeData sh in model.ShapeDatas) { if (part.Shape.ID != sh.ID) { continue; } part.Shape.ID = sh.ID; part.Shape.Name = sh.Name; part.Shape.Mesh = sh.Mesh; part.GetComponent <MeshFilter>().mesh = sh.Mesh; break; } //Assign material according to ID part.Shape.Materials = new I3DMaterial[part.Shape._Materials.Length]; for (int i = 0; i < part.Shape._Materials.Length; i++) { int shapeMatId = part.Shape._Materials[i]; foreach (I3DMaterial mat in model.Materials) { if (mat.Id != shapeMatId) { continue; } part.Shape.Materials[i] = mat; } } } else if (part.Type == Entity.ShapeType.TerrainTransformGroup) { int heightMapId = ParseInt(xml.GetAttribute("heightMapId")); //int patchSize = ParseInt(xml.GetAttribute("patchSize")); float heightScale = ParseFloat(xml.GetAttribute("heightScale")); float unitsPerPixel = ParseFloat(xml.GetAttribute("unitsPerPixel")); I3DFile heightMapFile = model.GetFile(heightMapId); if (heightMapFile != null) { I3DTerrain i3DTerrain = part.gameObject.AddComponent <I3DTerrain>(); i3DTerrain.AlphaWidth = ParseInt(xml.GetAttribute("lodTextureSize")); i3DTerrain.AlphaHeight = ParseInt(xml.GetAttribute("lodTextureSize")); i3DTerrain.Terrain = part.gameObject.AddComponent <Terrain>(); i3DTerrain.TerrainData = new TerrainData(); i3DTerrain.TerrainCollider = part.gameObject.AddComponent <TerrainCollider>(); i3DTerrain.HeightMapScale = heightScale; i3DTerrain.HeightMapUnitsPerPixel = unitsPerPixel; i3DTerrain.HeightMap = TextureLoader.GetTexture(heightMapFile.AbsolutePath); i3DTerrain.BuildHeightmap(); } } else if (part.Type == Entity.ShapeType.Layer) { I3DFile detailMapFile = model.GetFile(ParseInt(xml.GetAttribute("detailMapId"))); // Detail map = diffuse texture I3DFile normalMapFile = model.GetFile(ParseInt(xml.GetAttribute("normalMapId"))); // Normal map = normal texture I3DFile weightMapFile = model.GetFile(ParseInt(xml.GetAttribute("weightMapId"))); // Weight map = splat map? //I3DFile distanceMapFile = model.GetFile(ParseInt(xml.GetAttribute("distanceMapId"))); // Distance map = low-res diffuse texture int unitSize = ParseInt(xml.GetAttribute("unitSize")); //int distanceMapUnitSize = ParseInt(xml.GetAttribute("distanceMapUnitSize")); // Unknown SplatPrototype splat = new SplatPrototype { texture = TextureLoader.GetTexture(detailMapFile.AbsolutePath), normalMap = TextureLoader.GetTexture(normalMapFile.AbsolutePath), tileSize = new Vector2(unitSize, unitSize), tileOffset = Vector2.zero }; I3DTerrain i3Dterrain = part.GetComponentInParent <I3DTerrain>(); i3Dterrain.Layers.Add(new I3DTerrainLayer { Priority = ParseInt(xml.GetAttribute("priority")), Attributes = ParseVector4(xml.GetAttribute("attributes")), SplatMap = splat, Weights = I3DTerrainUtil.Parse8BitMap(TextureLoader.GetTexture(weightMapFile.AbsolutePath)) }); } }
public void Generate() { //----------------- INITIALIZE VARIABLES/LISTS CombinableMeshObject[] CMOS = GetComponentsInChildren <CombinableMeshObject>(); if (CMOS.Length == 0) { throw new Exception("Object has no children"); } else if (CMOS.Length == 1) { throw new Exception("Object has only one child"); } TotalObjects = CMOS.Length; TotalVerts = CMOS[0].MeshLODS[0].sharedMesh.vertices.Length * CMOS.Length; if (TotalVerts > 60000) { throw new Exception("Object has too many vertices"); } CombinedPositions = new List <Vector3>(); CombinedRotations = new List <Quaternion>(); foreach (CombinableMeshObject CMO in CMOS) { CombinedPositions.Add(CMO.transform.position); CombinedRotations.Add(CMO.transform.rotation); } CombinedPrefab = PrefabUtility.GetCorrespondingObjectFromSource(CMOS[0].gameObject); //----------------- MAKE PARENT OBJECTS/COMPONENTS CombinedObject = new GameObject(); CombinedObject.name = "Combined Object"; CombinedObject.transform.SetParent(this.transform); MeshCollider CombinedObjectCollider = CombinedObject.AddComponent(typeof(MeshCollider)) as MeshCollider; LODGroup CombinedObjectLODGroup = CombinedObject.AddComponent(typeof(LODGroup)) as LODGroup; GameObject CombinedMapModel = new GameObject(); CombinedMapModel.name = "Combined Map Model"; CombinedMapModel.layer = 10; CombinedMapModel.transform.SetParent(CombinedObject.transform); Material MapMaterial = CMOS[0].MapMesh.GetComponent <MeshRenderer>().sharedMaterial; MeshRenderer MapMeshRenderer = CombinedMapModel.AddComponent(typeof(MeshRenderer)) as MeshRenderer; MeshFilter MapMeshFilter = CombinedMapModel.AddComponent(typeof(MeshFilter)) as MeshFilter; MapMeshRenderer.sharedMaterial = MapMaterial; MapMeshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; GameObject CombinedModel = new GameObject(); CombinedModel.name = "Combined Model"; CombinedModel.transform.SetParent(CombinedObject.transform); //----------------- MAKE LOD OBJECTS AND MERGE MESHES int LODCount = CMOS[0].MeshLODS.Count; MeshRenderer[] Rends = new MeshRenderer[LODCount]; for (int i = 0; i < CMOS.Length; i++) { PrefabUtility.UnpackPrefabInstance(CMOS[i].gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); } for (int i = 0; i < LODCount; i++) { GameObject CombinedLOD = new GameObject(); CombinedLOD.name = "Model_LOD" + i; CombinedLOD.transform.SetParent(CombinedModel.transform); Material ModelMaterial = CMOS[0].MeshLODS[i].GetComponent <MeshRenderer>().sharedMaterial; MeshFilter ModelMeshFilter = CombinedLOD.AddComponent(typeof(MeshFilter)) as MeshFilter; MeshFilter[] modelMeshFilters = new MeshFilter[CMOS.Length]; CombineInstance[] modelCombine = new CombineInstance[CMOS.Length]; for (int x = 0; x < CMOS.Length; x++) { modelMeshFilters[x] = CMOS[x].MeshLODS[i]; } for (int x = 0; x < CMOS.Length; x++) { modelCombine[x].mesh = modelMeshFilters[x].sharedMesh; modelCombine[x].transform = modelMeshFilters[x].transform.localToWorldMatrix; } ModelMeshFilter.sharedMesh = new Mesh(); ModelMeshFilter.sharedMesh.CombineMeshes(modelCombine); MeshRenderer ModelMeshRenderer = CombinedLOD.AddComponent(typeof(MeshRenderer)) as MeshRenderer; ModelMeshRenderer.sharedMaterial = ModelMaterial; ModelMeshRenderer.shadowCastingMode = CMOS[0].MeshLODS[i].GetComponent <MeshRenderer>().shadowCastingMode; Rends[i] = ModelMeshRenderer; } //----------------- GENERATE MAP MESH CombineInstance[] mapCombine = new CombineInstance[CMOS.Length]; MeshFilter[] mapMeshFilters = new MeshFilter[CMOS.Length]; for (int i = 0; i < CMOS.Length; i++) { mapMeshFilters[i] = CMOS[i].MapMesh; } for (int i = 0; i < CMOS.Length; i++) { mapCombine[i].mesh = mapMeshFilters[i].sharedMesh; mapCombine[i].transform = mapMeshFilters[i].transform.localToWorldMatrix; } MapMeshFilter.sharedMesh = new Mesh(); MapMeshFilter.sharedMesh.CombineMeshes(mapCombine); CombinedObjectCollider.sharedMesh = Rends[CMOS[0].ColliderLODIndex].GetComponent <MeshFilter>().sharedMesh; //Debug.Log(Rends[0].GetComponent<MeshFilter>().sharedMesh.vertices.Length); MeshRenderer[,] LODRenderers = new MeshRenderer[LODCount, 1]; //only 1 mesh per lod group for (int i = 0; i < LODCount; i++) { LODRenderers[i, 0] = Rends[i]; } //----------------- MAKE LODS WITH EACH RENDERER LOD[] CombinedMeshLODS = new LOD[LODCount]; for (int i = 0; i < LODCount; i++) { MeshRenderer[] MeshRenArray = new MeshRenderer[] { LODRenderers[i, 0] }; if (i < LODCount - 1) { CombinedMeshLODS[i] = new LOD(0.85f / (i + 1f), MeshRenArray); } else { CombinedMeshLODS[i] = new LOD(0.005f, MeshRenArray); } } CombinedObjectLODGroup.SetLODs(CombinedMeshLODS); //----------------- FINALIZE foreach (CombinableMeshObject CMO in CMOS) { DestroyImmediate(CMO.gameObject); } CombinedObjectLODGroup.RecalculateBounds(); AddTag(); Generated = true; }
public void SaveAsPrefab(bool groupedSave = false, bool usingHDRP = false) { var oldMesh = filter.sharedMesh; string name = gameObject.name; string path = saveTreeFolder; if (string.IsNullOrEmpty(path)) { return; } #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) bool replacePrefab = false; //=> value never Used, taged by dan_wipf => used for unity up to 2018.2 #endif if (!System.IO.Directory.Exists(path)) { EditorUtility.DisplayDialog("Invalid Path", "The path is not valid, you can chose it with the find folder button", "Ok"); return; } if (AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject))) // Overriding prefab dialog { if (EditorUtility.DisplayDialog("Are you sure?", "The prefab already exists. Do you want to overwrite it?", "Yes", "No")) { FileUtil.DeleteFileOrDirectory(Path.Combine(path, name + "_meshes")); #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) replacePrefab = true; // => value never Used, taged by dan_wipf => used for unity up to 2018.2 #endif } else { name += "_1"; } } Mesh[] meshes = new Mesh[LODs.Count]; string meshesFolder = AssetDatabase.CreateFolder(path, name + "_meshes"); meshesFolder = AssetDatabase.GUIDToAssetPath(meshesFolder) + Path.DirectorySeparatorChar; Material[] materials = SaveMaterials(meshesFolder); GameObject TreeObject = new GameObject(name); // Tree game object LODGroup group = TreeObject.AddComponent <LODGroup>(); // LOD Group group.fadeMode = LODFadeMode.CrossFade; LOD[] lods = new LOD[LODs.Count + 1]; // Generating Billboard LodIndex = LODs.Count - 1; GenerateTree(true); GameObject billboard = CreateBillboard(meshesFolder, name, usingHDRP); Renderer[] bill_re = new Renderer[1] { billboard.GetComponent <MeshRenderer>() }; lods[lods.Length - 1] = new LOD(.01f, bill_re); for (LodIndex = LODs.Count - 1; LodIndex >= 0; LodIndex--) // create and save all LOD meshes { string meshPath = meshesFolder + name + "_LOD" + LodIndex + ".mesh"; //updating path for each LOD Mesh mesh = GenerateTree(instantAo: true); meshes[LodIndex] = mesh; AssetDatabase.CreateAsset(mesh, meshPath); } for (int i = 0; i < LODs.Count; i++) // assigning lod meshes to LOD array { GameObject go = new GameObject(name + "_LOD" + i.ToString()); go.transform.parent = TreeObject.transform; MeshFilter mf = go.AddComponent <MeshFilter>(); mf.mesh = meshes[i]; Renderer[] re = new Renderer[1] { go.AddComponent <MeshRenderer>() }; // the renderer to put in LODs re[0].sharedMaterials = materials; float t = Mathf.Pow((i + 1) * 1f / (LODs.Count + 1), 1); // float between 0 and 1 following f(x) = pow(x, n) lods[i] = new LOD((1 - t) * 0.9f + t * .01f, re); // assigning renderer lods[i].fadeTransitionWidth = 0.25f; } billboard.transform.parent = TreeObject.transform; // making billboard child of tree object group.SetLODs(lods); // assigning LODs to lod group group.animateCrossFading = true; group.RecalculateBounds(); string prefabPath = path + "/" + name + ".prefab"; Object prefab; #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) if (replacePrefab) { Object targetPrefab = AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject)); prefab = PrefabUtility.ReplacePrefab(TreeObject, targetPrefab, ReplacePrefabOptions.ConnectToPrefab); } else { prefab = PrefabUtility.CreatePrefab(prefabPath, TreeObject, ReplacePrefabOptions.ConnectToPrefab); } #else prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(TreeObject, prefabPath, InteractionMode.AutomatedAction); #endif AssetDatabase.SaveAssets(); DestroyImmediate(TreeObject); if (!groupedSave) { // select newly created prefab in folder Selection.activeObject = prefab; // Also flash the folder yellow to highlight it EditorGUIUtility.PingObject(prefab); EditorUtility.DisplayDialog("Prefab saved !", "The prefab is saved, you can now delete the tree and use the prefab instead", "Ok"); } LodIndex = 0; filter.sharedMesh = oldMesh; }
override public void OnInspectorGUI() { //base.OnInspectorGUI(); if (m_foldout == null) { m_foldout = "foldout"; } if (LockIconOpen == null) { LockIconOpen = new GUIContent(EditorGUIUtility.IconContent("LockIcon-On")); } if (LockIconClosed == null) { LockIconClosed = new GUIContent(EditorGUIUtility.IconContent("LockIcon")); } if (TextureIcon == null) { TextureIcon = new GUIContent(EditorGUIUtility.IconContent("Texture Icon")); TextureIcon.text = " Bake Impostor"; } if (CreateIcon == null) { CreateIcon = new GUIContent(EditorGUIUtility.IconContent("Toolbar Plus")); CreateIcon.text = ""; } if (SettingsIcon == null) { SettingsIcon = new GUIContent(EditorGUIUtility.IconContent("icons/d_TerrainInspector.TerrainToolSettings.png")); } m_instance = (target as AmplifyImpostor); bool triangulateMesh = false; bool autoChangeToManual = false; bool bakeTextures = false; if (m_instance.LodGroup != null && m_instance.m_lastImpostor == null) { double deltaTime = Time.realtimeSinceStartup - lastTime; lastTime = Time.realtimeSinceStartup; m_flash = Color.Lerp(m_flash, Color.white, (float)deltaTime * 3f); } else { m_flash = Color.white; } EditorGUI.BeginChangeCheck(); m_instance.Data = EditorGUILayout.ObjectField(AssetFieldStr, m_instance.Data, typeof(AmplifyImpostorAsset), false) as AmplifyImpostorAsset; if (m_instance.Data != null) { m_currentData = m_instance.Data; } m_instance.LodGroup = EditorGUILayout.ObjectField(LODGroupStr, m_instance.LodGroup, typeof(LODGroup), true) as LODGroup; EditorGUILayout.BeginHorizontal(); Color tempC = GUI.color; GUI.color = m_flash; EditorGUILayout.PropertyField(m_renderers, RenderersStr, true); GUI.color = tempC; EditorGUILayout.EndHorizontal(); GUILayout.Space(9); EditorGUILayout.BeginHorizontal(); if (m_instance.Data != null) { EditorGUI.BeginChangeCheck(); ImpostorBakingTools.GlobalBakingOptions = GUILayout.Toggle(ImpostorBakingTools.GlobalBakingOptions, SettingsIcon, "buttonleft", GUILayout.Width(32), GUILayout.Height(24)); if (EditorGUI.EndChangeCheck()) { EditorPrefs.SetBool(ImpostorBakingTools.PrefGlobalBakingOptions, ImpostorBakingTools.GlobalBakingOptions); } } else { if (GUILayout.Button(CreateIcon, "buttonleft", GUILayout.Width(32), GUILayout.Height(24))) { m_instance.CreateAssetFile(m_currentData); } } if (GUILayout.Button(TextureIcon, "buttonright", GUILayout.Height(24))) { if (m_instance.m_alphaTex == null) { m_recalculatePreviewTexture = true; } bakeTextures = true; } EditorGUILayout.EndHorizontal(); if (!(m_instance.transform.transform.localScale.x == m_instance.transform.transform.localScale.y && m_instance.transform.transform.localScale.y == m_instance.transform.transform.localScale.z)) { EditorGUILayout.HelpBox("Impostors can't render non-uniform scales correctly. Please consider scaling the object uniformly or generate it as a child of one.", MessageType.Warning); } if ((m_currentData.HorizontalFrames > 16 || m_currentData.VerticalFrames > 16)) { EditorGUILayout.HelpBox("Creating impostors with the axis frame number above 16 may take a lot longer to bake and save and the extra frames usually aren't necessary.", MessageType.Info); } if ((m_currentData.TexSize.x > 2048 || m_currentData.TexSize.y > 2048)) { EditorGUILayout.HelpBox("Creating impostors with texture resolution above 2048px may take a while to bake and save.", MessageType.Info); } if (ImpostorBakingTools.GlobalBakingOptions && m_instance.Data != null) { EditorGUILayout.BeginVertical("helpbox"); { EditorGUI.BeginChangeCheck(); m_currentData.ImpostorType = (ImpostorType)EditorGUILayout.EnumPopup(BakeTypeStr, m_currentData.ImpostorType); if (EditorGUI.EndChangeCheck()) { m_recalculatePreviewTexture = true; m_instance.m_alphaTex = null; if (m_instance.m_cutMode == CutMode.Automatic) { m_recalculateMesh = true; } } EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); if (m_currentData.LockedSizes) { m_currentData.SelectedSize = EditorGUILayout.IntPopup(TextureSizeStr, m_currentData.SelectedSize, m_sizesStr, m_sizes); m_currentData.LockedSizes = GUILayout.Toggle(m_currentData.LockedSizes, LockIconOpen, "minibutton", GUILayout.Width(22)); m_currentData.TexSize.Set(m_currentData.SelectedSize, m_currentData.SelectedSize); } else { m_currentData.TexSize = EditorGUILayout.Vector2Field(TextureSizeStr, m_currentData.TexSize); m_currentData.LockedSizes = GUILayout.Toggle(m_currentData.LockedSizes, LockIconClosed, "minibutton", GUILayout.Width(22)); } if (EditorGUI.EndChangeCheck()) { m_instance.m_alphaTex = null; m_recalculatePreviewTexture = true; if (m_instance.m_cutMode == CutMode.Automatic) { m_recalculateMesh = true; } } EditorGUILayout.EndHorizontal(); if (!m_currentData.DecoupleAxisFrames || m_currentData.ImpostorType != ImpostorType.Spherical) { EditorGUILayout.BeginHorizontal(); m_currentData.HorizontalFrames = EditorGUILayout.IntSlider(AxisFramesStr, m_currentData.HorizontalFrames, 1, 32); m_currentData.VerticalFrames = m_currentData.HorizontalFrames; if (m_currentData.ImpostorType == ImpostorType.Spherical) { m_currentData.DecoupleAxisFrames = !GUILayout.Toggle(!m_currentData.DecoupleAxisFrames, LockIconOpen, "minibutton", GUILayout.Width(22)); } EditorGUILayout.EndHorizontal(); } else { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(AxisFramesStr, ""); m_currentData.DecoupleAxisFrames = !GUILayout.Toggle(!m_currentData.DecoupleAxisFrames, LockIconClosed, "minibutton", GUILayout.Width(22)); EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; m_currentData.HorizontalFrames = EditorGUILayout.IntSlider("X", m_currentData.HorizontalFrames, 1, 32); m_currentData.VerticalFrames = EditorGUILayout.IntSlider("Y", m_currentData.VerticalFrames, 1, 32); EditorGUI.indentLevel--; } m_currentData.PixelPadding = EditorGUILayout.IntSlider(PixelPaddingStr, m_currentData.PixelPadding, 0, 64); #if UNITY_2017_3_OR_NEWER m_currentData.BufferMask = (DeferredBuffers)EditorGUILayout.EnumFlagsField(RenderingMapsStr, m_currentData.BufferMask); #else m_currentData.BufferMask = (DeferredBuffers)EditorGUILayout.EnumMaskField(RenderingMapsStr, m_currentData.BufferMask); #endif m_currentData.NormalCompression = (NormalCompression)EditorGUILayout.EnumPopup(NormalCompressionStr, m_currentData.NormalCompression); EditorGUI.BeginDisabledGroup(m_instance.m_lastImpostor != null || m_instance.LodGroup == null); EditorGUI.BeginChangeCheck(); m_instance.m_lodReplacement = (LODReplacement)EditorGUILayout.EnumPopup(LODModeStr, m_instance.m_lodReplacement); EditorGUI.BeginDisabledGroup(m_instance.m_lodReplacement < LODReplacement.ReplaceSpecific || m_instance.LodGroup == null); { int maxLods = 0; if (m_instance.LodGroup != null) { maxLods = m_instance.LodGroup.lodCount - 1; } m_instance.m_insertIndex = EditorGUILayout.IntSlider(LODTargetIndexStr, m_instance.m_insertIndex, 0, maxLods); } EditorGUI.EndDisabledGroup(); if (EditorGUI.EndChangeCheck()) { ReCheckRenderers(); } EditorGUI.EndDisabledGroup(); if ((m_billboardMesh || m_recalculatePreviewTexture) && m_instance.m_alphaTex == null) { m_instance.RenderCombinedAlpha(m_currentData); RenderTexture.active = m_instance.CombinedAlphaTexture; m_instance.m_alphaTex = new Texture2D(m_instance.CombinedAlphaTexture.width, m_instance.CombinedAlphaTexture.height, TextureFormat.RGBAFloat, false); m_instance.m_alphaTex.ReadPixels(new Rect(0, 0, m_instance.CombinedAlphaTexture.width, m_instance.CombinedAlphaTexture.height), 0, 0); m_instance.m_alphaTex.Apply(); m_instance.ClearCombinedAlphaBuffer(); m_recalculatePreviewTexture = false; } EditorGUI.indentLevel++; m_billboardMesh = GUILayout.Toggle(m_billboardMesh, "Billboard Mesh", "foldout"); EditorGUI.indentLevel--; int cutPreviewSize = 160; EditorGUILayout.BeginHorizontal(); if (m_billboardMesh) { Rect rect = GUILayoutUtility.GetRect(cutPreviewSize + 10, cutPreviewSize + 10, cutPreviewSize + 10, cutPreviewSize + 10); int controlID = GUIUtility.GetControlID("miniShapeEditorControl".GetHashCode(), FocusType.Passive, rect); Rect texRect = new Rect(5, 5, cutPreviewSize, cutPreviewSize); Rect hotRect = new Rect(0, 0, cutPreviewSize + 10, cutPreviewSize + 10); GUI.BeginClip(rect); if (m_instance.m_alphaTex != null) { Graphics.DrawTexture(texRect, m_instance.m_alphaTex, m_alphaMaterial, 3); } else { Graphics.DrawTexture(texRect, Texture2D.blackTexture, m_alphaMaterial, 3); } switch (Event.current.GetTypeForControl(controlID)) { case EventType.MouseDown: if (hotRect.Contains(Event.current.mousePosition)) { for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { Rect handleRect = new Rect(m_currentData.ShapePoints[i].x * cutPreviewSize, m_currentData.ShapePoints[i].y * cutPreviewSize, 10, 10); if (Event.current.type == EventType.MouseDown && handleRect.Contains(Event.current.mousePosition)) { EditorGUI.FocusTextInControl(null); m_activeHandle = i; m_lastPointSelected = i; m_lastMousePos = Event.current.mousePosition; m_originalPos = m_currentData.ShapePoints[i]; } } GUIUtility.hotControl = controlID; //Event.current.Use(); } break; case EventType.Ignore: case EventType.MouseUp: if (GUIUtility.hotControl == controlID) { m_activeHandle = -1; triangulateMesh = true; GUIUtility.hotControl = 0; //Event.current.Use(); GUI.changed = true; } break; case EventType.MouseDrag: if (GUIUtility.hotControl == controlID && m_activeHandle > -1) { m_currentData.ShapePoints[m_activeHandle] = m_originalPos + (Event.current.mousePosition - m_lastMousePos) / (cutPreviewSize + 10); if (Event.current.modifiers != EventModifiers.Control) { m_currentData.ShapePoints[m_activeHandle].x = (float)Math.Round(m_currentData.ShapePoints[m_activeHandle].x, 2); m_currentData.ShapePoints[m_activeHandle].y = (float)Math.Round(m_currentData.ShapePoints[m_activeHandle].y, 2); } m_currentData.ShapePoints[m_activeHandle].x = Mathf.Clamp01(m_currentData.ShapePoints[m_activeHandle].x); m_currentData.ShapePoints[m_activeHandle].y = Mathf.Clamp01(m_currentData.ShapePoints[m_activeHandle].y); autoChangeToManual = true; //Event.current.Use(); } break; } if (Event.current.type == EventType.Repaint) { Vector3[] allpoints = new Vector3[m_currentData.ShapePoints.Length + 1]; for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { allpoints[i] = new Vector3(m_currentData.ShapePoints[i].x * cutPreviewSize + 5, m_currentData.ShapePoints[i].y * cutPreviewSize + 5, 0); } allpoints[m_currentData.ShapePoints.Length] = allpoints[0]; Dictionary <string, bool> drawnList = new Dictionary <string, bool>(); for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { if (i == m_currentData.ShapePoints.Length - 1) { drawnList.Add(("0" + i), true); } else { drawnList.Add((i + "" + (i + 1)), true); } } if (m_previewMesh != null && m_instance.m_cutMode == CutMode.Manual) { //draw inside Color cache = Handles.color; Handles.color = new Color(1, 1, 1, 0.5f); //Handles.color = Color.black; for (int i = 0; i < m_previewMesh.triangles.Length - 1; i += 3) { int vert = m_previewMesh.triangles[i]; int vert2 = m_previewMesh.triangles[i + 1]; int vert3 = m_previewMesh.triangles[i + 2]; string ab = vert < vert2 ? vert + "" + vert2 : vert2 + "" + vert; string bc = vert2 < vert3 ? vert2 + "" + vert3 : vert3 + "" + vert2; string ac = vert < vert3 ? vert + "" + vert3 : vert3 + "" + vert; Vector3 a = new Vector3(m_currentData.ShapePoints[vert].x * cutPreviewSize + 5, m_currentData.ShapePoints[vert].y * cutPreviewSize + 5, 0); Vector3 b = new Vector3(m_currentData.ShapePoints[vert2].x * cutPreviewSize + 5, m_currentData.ShapePoints[vert2].y * cutPreviewSize + 5, 0); Vector3 c = new Vector3(m_currentData.ShapePoints[vert3].x * cutPreviewSize + 5, m_currentData.ShapePoints[vert3].y * cutPreviewSize + 5, 0); if (!drawnList.ContainsKey(ab)) { Handles.DrawAAPolyLine(new Vector3[] { a, b }); drawnList.Add(ab, true); } if (!drawnList.ContainsKey(bc)) { Handles.DrawAAPolyLine(new Vector3[] { b, c }); drawnList.Add(bc, true); } if (!drawnList.ContainsKey(ac)) { Handles.DrawAAPolyLine(new Vector3[] { a, c }); drawnList.Add(ac, true); } } Handles.color = cache; } Handles.DrawAAPolyLine(allpoints); if (m_instance.m_cutMode == CutMode.Manual) { for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { Rect handleRect = new Rect(m_currentData.ShapePoints[i].x * cutPreviewSize + 1, m_currentData.ShapePoints[i].y * cutPreviewSize + 1, 8, 8); Handles.DrawSolidRectangleWithOutline(handleRect, (m_activeHandle == i ? Color.cyan : Color.clear), (m_lastPointSelected == i && m_instance.m_cutMode == CutMode.Manual ? Color.cyan : Color.white)); } } else { for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { Rect handleRect = new Rect(m_currentData.ShapePoints[i].x * cutPreviewSize + 3, m_currentData.ShapePoints[i].y * cutPreviewSize + 3, 4, 4); Handles.DrawSolidRectangleWithOutline(handleRect, Color.white, Color.white); } } } GUI.EndClip(); EditorGUILayout.BeginVertical(); { EditorGUI.BeginChangeCheck(); m_instance.m_cutMode = (CutMode)GUILayout.Toolbar((int)m_instance.m_cutMode, new[] { "Automatic", "Manual" }); if (EditorGUI.EndChangeCheck()) { if (m_instance.m_cutMode == CutMode.Automatic) { m_recalculateMesh = true; } } float cacheLabel = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 120; switch (m_instance.m_cutMode) { default: case CutMode.Automatic: { EditorGUI.BeginChangeCheck(); { m_currentData.MaxVertices = EditorGUILayout.IntSlider(MaxVerticesStr, m_currentData.MaxVertices, 4, 16); m_currentData.Tolerance = EditorGUILayout.Slider(OutlineToleranceStr, m_currentData.Tolerance * 5, 0, 1f) * 0.2f; m_currentData.NormalScale = EditorGUILayout.Slider(NormalScaleStr, m_currentData.NormalScale, 0, 1.0f); } if (EditorGUI.EndChangeCheck()) { m_recalculateMesh = true; } } break; case CutMode.Manual: { m_currentData.MaxVertices = EditorGUILayout.IntSlider(MaxVerticesStr, m_currentData.MaxVertices, 4, 16); m_currentData.Tolerance = EditorGUILayout.Slider(OutlineToleranceStr, m_currentData.Tolerance * 5, 0, 1f) * 0.2f; m_currentData.NormalScale = EditorGUILayout.Slider(NormalScaleStr, m_currentData.NormalScale, 0, 1.0f); if (GUILayout.Button("Update")) { m_recalculateMesh = true; } m_lastPointSelected = Mathf.Clamp(m_lastPointSelected, 0, m_currentData.ShapePoints.Length - 1); EditorGUILayout.Space(); m_currentData.ShapePoints[m_lastPointSelected] = EditorGUILayout.Vector2Field("", m_currentData.ShapePoints[m_lastPointSelected]); m_currentData.ShapePoints[m_lastPointSelected].x = Mathf.Clamp01(m_currentData.ShapePoints[m_lastPointSelected].x); m_currentData.ShapePoints[m_lastPointSelected].y = Mathf.Clamp01(m_currentData.ShapePoints[m_lastPointSelected].y); } break; } EditorGUIUtility.labelWidth = cacheLabel; } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } if (m_recalculateMesh && m_instance.m_alphaTex != null) { m_recalculateMesh = false; // create a 2d texture for calculations Rect testRect = new Rect(0, 0, m_instance.m_alphaTex.width, m_instance.m_alphaTex.height); Vector2[][] paths; SpriteUtilityEx.GenerateOutline(m_instance.m_alphaTex, testRect, m_currentData.Tolerance, 254, false, out paths); int sum = 0; for (int i = 0; i < paths.Length; i++) { sum += paths[i].Length; } m_currentData.ShapePoints = new Vector2[sum]; int index = 0; for (int i = 0; i < paths.Length; i++) { for (int j = 0; j < paths[i].Length; j++) { m_currentData.ShapePoints[index] = (Vector2)(paths[i][j]) + (new Vector2(m_instance.m_alphaTex.width * 0.5f, m_instance.m_alphaTex.height * 0.5f)); m_currentData.ShapePoints[index] = Vector2.Scale(m_currentData.ShapePoints[index], new Vector2(1.0f / m_instance.m_alphaTex.width, 1.0f / m_instance.m_alphaTex.height)); index++; } } // make it convex hull m_currentData.ShapePoints = Vector2Ex.ConvexHull(m_currentData.ShapePoints); // reduce vertices m_currentData.ShapePoints = Vector2Ex.ReduceVertices(m_currentData.ShapePoints, m_currentData.MaxVertices); // Resize the mesh using calculated normals m_currentData.ShapePoints = Vector2Ex.ScaleAlongNormals(m_currentData.ShapePoints, m_currentData.NormalScale); // clamp to box (needs a cut algorithm) for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { m_currentData.ShapePoints[i].x = Mathf.Clamp01(m_currentData.ShapePoints[i].x); m_currentData.ShapePoints[i].y = Mathf.Clamp01(m_currentData.ShapePoints[i].y); } // make it convex hull gain to clean edges m_currentData.ShapePoints = Vector2Ex.ConvexHull(m_currentData.ShapePoints); // invert Y for (int i = 0; i < m_currentData.ShapePoints.Length; i++) { m_currentData.ShapePoints[i] = new Vector2(m_currentData.ShapePoints[i].x, 1 - m_currentData.ShapePoints[i].y); } triangulateMesh = true; EditorUtility.SetDirty(m_instance); } if (EditorGUI.EndChangeCheck()) { if (m_instance.Data == null) { EditorPrefs.SetString(ImpostorBakingTools.PrefDataImpType, m_currentData.ImpostorType.ToString()); EditorPrefs.SetInt(ImpostorBakingTools.PrefDataTexSizeSelected, m_currentData.SelectedSize); EditorPrefs.SetBool(ImpostorBakingTools.PrefDataTexSizeLocked, m_currentData.LockedSizes); EditorPrefs.SetFloat(ImpostorBakingTools.PrefDataTexSizeX, m_currentData.TexSize.x); EditorPrefs.SetFloat(ImpostorBakingTools.PrefDataTexSizeY, m_currentData.TexSize.y); EditorPrefs.SetBool(ImpostorBakingTools.PrefDataDecoupledFrames, m_currentData.DecoupleAxisFrames); EditorPrefs.SetInt(ImpostorBakingTools.PrefDataXFrames, m_currentData.HorizontalFrames); EditorPrefs.SetInt(ImpostorBakingTools.PrefDataYFrames, m_currentData.VerticalFrames); EditorPrefs.SetInt(ImpostorBakingTools.PrefDataPixelBleeding, m_currentData.PixelPadding); EditorPrefs.SetFloat(ImpostorBakingTools.PrefDataTolerance, m_currentData.Tolerance); EditorPrefs.SetFloat(ImpostorBakingTools.PrefDataNormalScale, m_currentData.NormalScale); EditorPrefs.SetInt(ImpostorBakingTools.PrefDataMaxVertices, m_currentData.MaxVertices); } EditorUtility.SetDirty(m_instance); } if (triangulateMesh) { m_previewMesh = GeneratePreviewMesh(m_currentData.ShapePoints, true); } if (autoChangeToManual /*&& Event.current.type == EventType.Layout*/) { autoChangeToManual = false; m_instance.m_cutMode = CutMode.Manual; Event.current.Use(); } // Bake textures after alpha generation if (bakeTextures) { bakeTextures = false; m_instance.RenderAllDeferredGroups(m_currentData); bool createLodGroup = false; if (ImpostorBakingTools.GlobalCreateLodGroup) { LODGroup group = m_instance.RootTransform.GetComponentInParent <LODGroup>(); if (group == null) { group = m_instance.RootTransform.GetComponentInChildren <LODGroup>(); } if (group == null && m_instance.LodGroup == null) { createLodGroup = true; } } if (createLodGroup && m_instance.m_lastImpostor != null) { GameObject lodgo = new GameObject(m_instance.name + "_LODGroup"); LODGroup lodGroup = lodgo.AddComponent <LODGroup>(); lodGroup.transform.position = m_instance.transform.position; int hierIndex = m_instance.transform.GetSiblingIndex(); m_instance.transform.SetParent(lodGroup.transform, true); m_instance.m_lastImpostor.transform.SetParent(lodGroup.transform, true); LOD[] lods = lodGroup.GetLODs(); ArrayUtility.RemoveAt <LOD>(ref lods, 2); lods[0].fadeTransitionWidth = 0.5f; lods[0].screenRelativeTransitionHeight = 0.15f; lods[0].renderers = m_instance.RootTransform.GetComponentsInChildren <Renderer>(); lods[1].fadeTransitionWidth = 0.5f; lods[1].screenRelativeTransitionHeight = 0.01f; lods[1].renderers = m_instance.m_lastImpostor.GetComponentsInChildren <Renderer>(); lodGroup.fadeMode = LODFadeMode.CrossFade; lodGroup.animateCrossFading = true; lodGroup.SetLODs(lods); lodgo.transform.SetSiblingIndex(hierIndex); } } serializedObject.ApplyModifiedProperties(); }
public void CreateWMOObject() { if (terrainHandler.working) { WMO.WMOStruct data = WMO.AllWMOData.Dequeue(); GameObject WMOinstance = new GameObject(); terrainHandler.LoadedWMOIds[data.fileDataId] = WMOinstance; int nGroups = data.Info.nGroups; for (int g = 0; g < nGroups; g++) { // group object // GameObject GroupInstance = new GameObject(); GroupInstance.isStatic = true; GroupInstance.transform.SetParent(terrainHandler.LoadedWMOIds[data.fileDataId].transform); GroupInstance.name = data.groupsData[g].groupName; LODGroup Lodgroup = GroupInstance.AddComponent <LODGroup>(); LOD[] lods = new LOD[1]; Renderer[] renderers = new Renderer[data.groupsData[g].nBatches]; // Batches // for (int bn = 0; bn < data.groupsData[g].nBatches; bn++) { //////////////////////////////// #region object GameObject BatchInstance = new GameObject(); BatchInstance.isStatic = true; BatchInstance.transform.SetParent(GroupInstance.transform); BatchInstance.name = bn.ToString(); BatchInstance.transform.transform.eulerAngles = new Vector3(BatchInstance.transform.transform.eulerAngles.x, BatchInstance.transform.transform.eulerAngles.y - 180, GroupInstance.transform.transform.eulerAngles.z); #endregion //////////////////////////////// //////////////////////////////// #region mesh BatchInstance.AddComponent <MeshRenderer>(); BatchInstance.GetComponent <MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; renderers[bn] = BatchInstance.GetComponent <MeshRenderer>(); BatchInstance.AddComponent <MeshFilter>(); Mesh bmesh = new Mesh(); uint batchVertSize = data.groupsData[g].batch_MaxIndex[bn] - data.groupsData[g].batch_MinIndex[bn] + 1; Vector3[] batchVertices = new Vector3[batchVertSize]; Vector2[] batchUVs = new Vector2[batchVertSize]; Vector3[] batchNormals = new Vector3[batchVertSize]; Color32[] batchVertexColors = new Color32[batchVertSize]; List <int> batchTrianglesList = new List <int>(); int[] batchTriangles; int arrayPosition = 0; uint batch_startVertex = data.groupsData[g].batch_MinIndex[bn]; uint batch_endVertex = data.groupsData[g].batch_MaxIndex[bn]; for (uint v = batch_startVertex; v <= batch_endVertex; v++) { batchVertices[arrayPosition] = data.groupsData[g].vertices[v]; batchUVs[arrayPosition] = data.groupsData[g].UVs[v]; batchNormals[arrayPosition] = data.groupsData[g].normals[v]; if (!data.groupsData[g].flags.Hasvertexolors) { batchVertexColors[arrayPosition] = new Color32(127, 127, 127, 127); } else { batchVertexColors[arrayPosition] = data.groupsData[g].vertexColors[(int)v]; } arrayPosition++; } uint batch_startIndex = data.groupsData[g].batch_StartIndex[bn]; uint batch_nIndices = data.groupsData[g].batch_Count[bn]; for (uint idx = batch_startIndex; idx <= batch_startIndex + batch_nIndices - 2; idx = idx + 3) { uint in1 = data.groupsData[g].triangles[idx + 0]; uint in2 = data.groupsData[g].triangles[idx + 1]; uint in3 = data.groupsData[g].triangles[idx + 2]; int a = (int)(in1 - batch_startVertex); int b = (int)(in2 - batch_startVertex); int c = (int)(in3 - batch_startVertex); batchTrianglesList.Add(a); batchTrianglesList.Add(b); batchTrianglesList.Add(c); } batchTrianglesList.Reverse(); batchTriangles = batchTrianglesList.ToArray(); bmesh.vertices = batchVertices; bmesh.uv = batchUVs; bmesh.normals = batchNormals; bmesh.triangles = batchTriangles; bmesh.colors32 = batchVertexColors; BatchInstance.GetComponent <MeshFilter>().mesh = bmesh; BatchInstance.GetComponent <MeshRenderer>().sharedMaterial = missingMaterial; #endregion //////////////////////////////// //////////////////////////////// #region material uint TextureFileDataId = data.texturePaths[data.materials[data.groupsData[g].batchMaterialIDs[bn]].TextureId1]; BatchInstance.GetComponent <Renderer>().material = WMOmaterials[(int)data.materials[data.groupsData[g].batchMaterialIDs[bn]].ShaderType]; //////////////////////////////// #region Set Fragment Shader WMOFragmentShader shader = data.materials[data.groupsData[g].batchMaterialIDs[bn]].ShaderType; switch (shader) { case WMOFragmentShader.Diffuse: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderDiffuse", 1.0f); break; } case WMOFragmentShader.Specular: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderSpecular", 1.0f); break; } case WMOFragmentShader.Metal: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderMetal", 1.0f); break; } case WMOFragmentShader.Env: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderEnv", 1.0f); break; } case WMOFragmentShader.Opaque: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderOpaque", 1.0f); BatchInstance.GetComponent <Renderer>().material.SetFloat("_AlphaToMask", 1.0f); break; } default: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderDiffuse", 1.0f); break; } } #endregion //////////////////////////////// //////////////////////////////// #region Set Material Flags // F_UNCULLED // int Culling = 2; // on (only front) if (data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNCULLED) { Culling = 0; // off (both sides_ } BatchInstance.GetComponent <Renderer>().material.SetFloat("F_UNCULLED", Culling); // F_UNLIT // if (data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNLIT) { BatchInstance.GetComponent <Renderer>().material.EnableKeyword("F_UNLIT"); } //BatchInstance.GetComponent<Renderer>().material.SetFloat("_F_UNLIT", data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNLIT ? 1 : 0); // F_UNFOGGED // BatchInstance.GetComponent <Renderer>().material.SetFloat("_F_UNFOGGED", data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNFOGGED ? 1 : 0); #endregion //////////////////////////////// //////////////////////////////// #region Set Blending Mode // set default blend: One Zero, basicly off UnityEngine.Rendering.BlendMode source = UnityEngine.Rendering.BlendMode.One; UnityEngine.Rendering.BlendMode destination = UnityEngine.Rendering.BlendMode.Zero; BlendingMode blending = data.materials[data.groupsData[g].batchMaterialIDs[bn]].BlendMode; switch (blending) { case BlendingMode.Opaque: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.AlphaKey: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.Alpha: { source = UnityEngine.Rendering.BlendMode.SrcAlpha; destination = UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha; break; } case BlendingMode.Additive: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.One; break; } case BlendingMode.Modulate: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.Modulate2x: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.SrcColor; break; } case BlendingMode.ModulateAdditive: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.One; break; } default: { Debug.Log("BlendMode To Add: " + blending.ToString() + " Texture Used: " + TextureFileDataId); source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } } BatchInstance.GetComponent <Renderer>().material.SetInt("MySrcMode", (int)source); BatchInstance.GetComponent <Renderer>().material.SetInt("MyDstMode", (int)destination); #endregion //////////////////////////////// //////////////////////////////// #region Assign Textures if (LoadedWMOTextures.ContainsKey(TextureFileDataId)) { BatchInstance.GetComponent <Renderer>().material.SetTexture("_MainTex", LoadedWMOTextures[TextureFileDataId]); } else { try { Texture2Ddata tdata = data.textureData[TextureFileDataId]; Texture2D tex = new Texture2D(tdata.width, tdata.height, tdata.textureFormat, tdata.hasMipmaps); tex.LoadRawTextureData(tdata.TextureData); tex.Apply(); LoadedWMOTextures[TextureFileDataId] = tex; BatchInstance.GetComponent <Renderer>().material.SetTexture("_MainTex", tex); } catch (Exception ex) { Debug.Log("Error: Loading RawTextureData @ WMOhandler"); Debug.LogException(ex); } } #endregion //////////////////////////////// #endregion //////////////////////////////// } lods[0] = new LOD(.1f, renderers); Lodgroup.SetLODs(lods); Lodgroup.animateCrossFading = true; Lodgroup.fadeMode = LODFadeMode.SpeedTree; Lodgroup.RecalculateBounds(); } terrainHandler.LoadedWMOIds[data.fileDataId].transform.position = data.position; terrainHandler.LoadedWMOIds[data.fileDataId].transform.rotation = data.rotation; terrainHandler.LoadedWMOIds[data.fileDataId].transform.localScale = data.scale; if (data.uniqueID != -1) { if (terrainHandler.ADTBlockWMOParents[data.uniqueID] != null) { terrainHandler.LoadedWMOIds[data.fileDataId].transform.SetParent(terrainHandler.ADTBlockWMOParents[data.uniqueID].transform); } else { Destroy(terrainHandler.LoadedWMOIds[data.fileDataId]); } } terrainHandler.LoadedWMOIds[data.fileDataId].name = data.Info.wmoID.ToString(); terrainHandler.frameBusy = false; } }
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; }
void Mesh() { counting = 0; canMerge = false; int numOfseObjList = 0; totalcount = dataDic.Count; foreach (string key in dataDic.Keys) { counting++; UpdateProgress(); if (showList.Count > 0 && showList[numOfseObjList] == false) { numOfseObjList++; continue; } numOfseObjList++; if (polyMergeCountDic[key] > 65000) { continue; } NewFolder(meshContainsName, key); LOD[] lods = new LOD[dataDic[key].Count]; int lodCount = 0; int merCoung = 0; foreach (MergeData m in dataDic[key]) { //Mesh for (int i = 0; i < m._matLists.Count; i++) { subMeshList = m._subMeshLists[i]; string header = meshContainsName; GameObject mergedObject = new GameObject(header + "_" + m._objectLists[i][0].name + "_" + m._matLists[i][0].name, typeof(MeshFilter), typeof(MeshRenderer)); Mesh combinedMesh = CombineSubmeshes(subMeshList, mergedObject); if (m._tranMeshColLists.Count != 0) { int mesColCou = 0; for (int t = 0; t < m._tranMeshColLists.Count; t++) { GameObject addMesh = new GameObject(m._meshColLists[t].name + "_" + mesColCou); mesColCou++; MeshCollider mc = addMesh.AddComponent <MeshCollider> (); mc.sharedMesh = m._meshColLists[t]; addMesh.transform.position = m._tranMeshColLists[t].transform.position; addMesh.transform.rotation = m._tranMeshColLists[t].transform.rotation; addMesh.transform.localScale = m._tranMeshColLists[t].localScale; addMesh.transform.SetParent(mergedObject.transform); } } AssetDatabase.CreateAsset(combinedMesh, filePath + "/" + header + "_" + m._objectLists[i][0].name + "_" + m._matLists[i][0].name + ".asset"); mergedObject.GetComponent <MeshFilter>().mesh = combinedMesh; mergedObject.GetComponent <MeshRenderer>().sharedMaterials = m._matLists[i].ToArray(); lodList.Add(mergedObject); Renderer[] renderers = new Renderer[1]; renderers[0] = mergedObject.GetComponent <Renderer>(); lods[lodCount] = new LOD(1.0f / (lodCount + 2f), renderers); lodCount++; } } string m_header = meshContainsName; GameObject newMergedObj = new GameObject(m_header + "_" + key); foreach (GameObject n in lodList) { n.transform.SetParent(newMergedObj.transform); } if (lodGroup) { LODGroup lodObj = newMergedObj.AddComponent <LODGroup> (); lodObj.SetLODs(lods); lodObj.RecalculateBounds(); for (int n = lodObj.GetLODs().Count() - 1; n >= 0; n--) { if (lodObj.GetLODs()[n].renderers.Length == 0) { List <LOD> _lodObj = lodObj.GetLODs().ToList(); _lodObj.RemoveAt(n); lodObj.SetLODs(_lodObj.ToArray()); } } if (lodRTH.ContainsKey(key)) { lods = lodObj.GetLODs(); for (int u = 0; u < lodRTH[key].Count; u++) { lods [u].screenRelativeTransitionHeight = lodRTH [key] [u]; } lodObj.SetLODs(lods); } } PrefabUtility.CreatePrefab(filePath + "/" + m_header + "_" + key + ".prefab", (GameObject)newMergedObj, ReplacePrefabOptions.ConnectToPrefab); lodList.Clear(); } }
public void printLoDSlider(SerializedObject serializedObject, string prefix, int winId, bool showLODMode = true, GameObject gameObject = null) { bool isInspector = serializedObject.FindProperty("isInspector") != null?serializedObject.FindProperty("isInspector").boolValue : false; SerializedProperty serializedProperty = serializedObject.FindProperty(prefix); tt = "Use the button “Add LOD level” to add multiple LODs (or Level of Detail, see documentation for more information).\n\nFor each LOD(up to 5, including LOD 0), choose a Quality preset.\n\nUse the horizontal bar to set screen size percentage for each LOD.\n\nRight-click in the horizontal bar to add / remove a new LOD."; PiXYZUtils.beginGroupBox("LODs Mesh Quality", tooltip: tt); { int currentLodIndex = -1; tt = "To insert or remove a LoD, right-click on the row"; EditorGUILayout.BeginVertical(); { EditorGUILayout.Space(); bool changed = false || reset; if (changed) { reset = false; } if (showLODMode) { EditorGUILayout.BeginHorizontal(); { GUILayout.Space(20); float width = GUI.skin.label.CalcSize(new GUIContent("Quality")).x; GUILayout.Label("Mode", GUILayout.Width(width)); List <string> propertyNames = new List <string>(3); propertyNames.Add("LOD Group put on root object"); propertyNames.Add("LOD Groups put on the parent of each mesh"); List <int> intValue = new List <int>(3); intValue.Add(1); intValue.Add(2); width = (float)Math.Truncate(Screen.width * 0.6); Rect rect = EditorGUILayout.GetControlRect(); rect.width = width; GUILayout.FlexibleSpace(); int originalValue = serializedProperty.FindPropertyRelative("lodsMode").intValue; serializedProperty.FindPropertyRelative("lodsMode").intValue = EditorGUI.IntPopup(rect, originalValue, propertyNames.ToArray(), intValue.ToArray()); if (isInspector && gameObject != null && originalValue != serializedProperty.FindPropertyRelative("lodsMode").intValue) { if (originalValue == 1) { LODGroup lodGroup = gameObject.GetComponent <LODGroup>(); Dictionary <LODGroup, Dictionary <float, List <Renderer> > > finalLods = new Dictionary <LODGroup, Dictionary <float, List <Renderer> > >(); foreach (LOD lod in lodGroup.GetLODs()) { foreach (Renderer renderer in lod.renderers) { LODGroup parentLODGroup = renderer.transform.parent.GetComponent <LODGroup>(); if (parentLODGroup == null) { parentLODGroup = renderer.transform.parent.gameObject.AddComponent <LODGroup>(); } if (!finalLods.ContainsKey(parentLODGroup)) { finalLods.Add(parentLODGroup, new Dictionary <float, List <Renderer> >()); } if (!finalLods[parentLODGroup].ContainsKey(lod.screenRelativeTransitionHeight)) { finalLods[parentLODGroup].Add(lod.screenRelativeTransitionHeight, new List <Renderer>()); } finalLods[parentLODGroup][lod.screenRelativeTransitionHeight].Add(renderer); } } UnityEngine.Object.DestroyImmediate(lodGroup); foreach (var groupPair in finalLods) { List <LOD> lods = new List <LOD>(); foreach (var pair in groupPair.Value) { lods.Add(new LOD(pair.Key, pair.Value.ToArray())); } lods.Sort(delegate(LOD x, LOD y) { if (x.screenRelativeTransitionHeight < y.screenRelativeTransitionHeight) { return(1); } else if (x.screenRelativeTransitionHeight == y.screenRelativeTransitionHeight) { return(0); } else { return(-1); } }); groupPair.Key.SetLODs(lods.ToArray()); } } else { Dictionary <float, List <Renderer> > newLods = new Dictionary <float, List <Renderer> >(); foreach (LODGroup lodGroup in gameObject.GetComponentsInChildren <LODGroup>()) { foreach (LOD lod in lodGroup.GetLODs()) { if (!newLods.ContainsKey(lod.screenRelativeTransitionHeight)) { newLods.Add(lod.screenRelativeTransitionHeight, new List <Renderer>()); } newLods[lod.screenRelativeTransitionHeight].AddRange(lod.renderers); } UnityEngine.Object.DestroyImmediate(lodGroup); } LODGroup parentLODGroup = gameObject.AddComponent <LODGroup>(); List <LOD> lods = new List <LOD>(); foreach (KeyValuePair <float, List <Renderer> > pair in newLods) { lods.Add(new LOD(pair.Key, pair.Value.ToArray())); } lods.Sort(delegate(LOD x, LOD y) { if (x.screenRelativeTransitionHeight < y.screenRelativeTransitionHeight) { return(1); } else if (x.screenRelativeTransitionHeight == y.screenRelativeTransitionHeight) { return(0); } else { return(-1); } }); parentLODGroup.SetLODs(lods.ToArray()); } } } EditorGUILayout.EndHorizontal(); GUILayout.Space(10); } EditorGUILayout.BeginHorizontal(); { GUILayout.Space(20); slider.show(serializedObject, gameObject); GUILayout.Space(20); } EditorGUILayout.EndHorizontal(); GUILayout.Space(10); if (!isInspector) { EditorGUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); if (!serializedProperty.FindPropertyRelative("useLods").boolValue) { if (GUILayout.Button(new GUIContent("Activate LODs"))) { serializedProperty.FindPropertyRelative("useLods").boolValue = true; } } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); } GUILayout.Space(10); } EditorGUILayout.EndVertical(); currentLodIndex = serializedProperty.FindPropertyRelative("lodCurrentIndex").intValue; if (GUI.changed) { serializedObject.ApplyModifiedProperties(); if (EditorWindow.focusedWindow != null) { EditorWindow.focusedWindow.Repaint(); } } if (!isInspector) { GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { if (serializedProperty.FindPropertyRelative("useLods").boolValue) { printLoDSettings(currentLodIndex, serializedObject, prefix + "." + PiXYZLODSettings.serializePrefix); } serializedObject.ApplyModifiedProperties(); GUILayout.Space(10); } GUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } else { GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Propagate Materials from LOD0", "After applying a new material to one (or multiple) LOD0, use this button to propagate the material assignment to all the other LODs."))) { if (serializedProperty.FindPropertyRelative("lodsMode").intValue == 2) { foreach (var lodGroup in gameObject.GetComponentsInChildren <LODGroup>()) { for (int i = 1; i < lodGroup.lodCount; ++i) //foreach(LOD lod in lodGroup.GetLODs()) { if (lodGroup.GetLODs()[0].renderers.Length != lodGroup.GetLODs()[i].renderers.Length) { Debug.Log("The number of renderers on each LOD is not equal, can't synchronize !"); } else { for (int j = 0; j < lodGroup.GetLODs()[0].renderers.Length; ++j) { Renderer renderer = lodGroup.GetLODs()[i].renderers[j].gameObject.GetComponent <Renderer>(); renderer.sharedMaterial = lodGroup.GetLODs()[0].renderers[j].sharedMaterial; renderer.sharedMaterials = lodGroup.GetLODs()[0].renderers[j].sharedMaterials; } } } } } else { LODGroup lodGroup = gameObject.GetComponent <LODGroup>(); for (int i = 1; i < lodGroup.lodCount; ++i) //foreach(LOD lod in lodGroup.GetLODs()) { if (lodGroup.GetLODs()[0].renderers.Length != lodGroup.GetLODs()[i].renderers.Length) { Debug.Log("The number of renderers on each LOD is not equal, can't synchronize !"); } else { for (int j = 0; j < lodGroup.GetLODs()[0].renderers.Length; ++j) { Renderer renderer = lodGroup.GetLODs()[i].renderers[j].gameObject.GetComponent <Renderer>(); renderer.sharedMaterial = lodGroup.GetLODs()[0].renderers[j].sharedMaterial; renderer.sharedMaterials = lodGroup.GetLODs()[0].renderers[j].sharedMaterials; } } } } } GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); } } PiXYZUtils.endGroupBox(); }
public static void CreateFileForResult(List <VoxelCore.Result> resultList, Shader shader, float scale) { TheShader = shader; ModelScale = scale; 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.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, root, ref meshs, ref materialsMap, isRig, result.WithAvatar); 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 * ModelScale; 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, 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] + Vector3.up * 0.5f) * ModelScale; } } // 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) ); } #if UNITY_5_0 || UNITY_5_1 || UNITY_4 group.SetLODS(lods); group.RecalculateBounds(); #else group.SetLODs(lods); group.RecalculateBounds(); #endif } // 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); if (result.Extension == ".prefab") { Object prefab; if (Util.FileExists(path)) { prefab = AssetDatabase.LoadAssetAtPath <Object>(path); if (prefab as GameObject) { var group = (prefab as GameObject).GetComponent <LODGroup>(); if (group) { Object.DestroyImmediate(group, true); } } Object[] things = AssetDatabase.LoadAllAssetRepresentationsAtPath(path); foreach (Object o in things) { Object.DestroyImmediate(o, true); } } else { prefab = PrefabUtility.CreateEmptyPrefab(path); } if (prefab) { // Assets for (int i = 0; i < meshs.Count; i++) { meshs[i].name = GetIndexedName("Mesh", i, meshs.Count); AssetDatabase.AddObjectToAsset(meshs[i], path); } int currentIndex = 0; foreach (var textureMat in materialsMap) { textureMat.Key.name = GetIndexedName("Texture", currentIndex, materialsMap.Count); textureMat.Value.name = GetIndexedName("Material", currentIndex, materialsMap.Count); currentIndex++; AssetDatabase.AddObjectToAsset(textureMat.Key, path); AssetDatabase.AddObjectToAsset(textureMat.Value, path); } // 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; } } // Prefab PrefabUtility.ReplacePrefab(root.gameObject, prefab, ReplacePrefabOptions.ReplaceNameBased); } } else // Obj { string objFolderPath = Util.CombinePaths(parentPath, result.FileName); string textureFolderPath = Util.CombinePaths(objFolderPath, "Textures"); Util.CreateFolder(objFolderPath); VoxelPostprocessor.TheShader = TheShader; // 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); } } } } Object.DestroyImmediate(root.gameObject, false); } AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); Resources.UnloadUnusedAssets(); EditorApplication.delayCall += VoxelPostprocessor.ClearAsset; }
public override void OnInspectorGUI() { GUILayout.BeginHorizontal(); GUILayout.Box(WorldIcon, GUILayout.Width(WorldIcon.width), GUILayout.Height(WorldIcon.height), GUILayout.ExpandWidth(true)); //GUILayout.Label(WorldIcon, GUILayout.Width(WorldIcon.width), GUILayout.Height(WorldIcon.height),GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); EditorGUILayout.Space(); PWT.SetupTerrainAssociation(); PWT.chunkSizes = PWT.GetChunkSizes(); GUI.color = new Color(1f, 1f, 1f); GUILayout.BeginVertical(GUI.skin.box); GUILayout.Label("Terrain Visibility:"); GUILayout.BeginHorizontal(); PWT.terrainGOEnabled = GUILayout.Toggle(PWT.terrainGOEnabled, "Source Terrain", GUI.skin.button, GUILayout.Height(30)); PWT.gameObject.GetComponent <Terrain>().enabled = PWT.terrainGOEnabled; PWT.PWTGOEnabled = GUILayout.Toggle(PWT.PWTGOEnabled, "PolyWorld Terrain", GUI.skin.button, GUILayout.Height(30)); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.BeginVertical(); if (Selection.activeGameObject.transform.childCount > 0) { GUILayout.Space(10f); Transform goc = Selection.activeGameObject.transform.GetChild(0); MeshRenderer[] children = goc.gameObject.GetComponentsInChildren <MeshRenderer>(); foreach (MeshRenderer t in children) { t.enabled = PWT.PWTGOEnabled; } if (GUILayout.Button(UpdateColor, GUILayout.Height(UpdateColor.height), GUILayout.Width(UpdateColor.width), GUILayout.ExpandWidth(true))) { MeshFilter[] meshes = Selection.activeGameObject.transform.GetChild(0).GetComponentsInChildren <MeshFilter>(); List <GameObject> LOD0 = new List <GameObject>(); List <GameObject> LOD1 = new List <GameObject>(); foreach (MeshFilter m in meshes) { if (m.name.Contains("LOD0")) { LOD0.Add(m.gameObject); } else if (m.name.Contains("LOD1")) { LOD1.Add(m.gameObject); } else { LOD0.Add(m.gameObject); } } PWT.RenderVertexColors(LOD0.ToArray()); if (LOD1.Count > 0) { //set the quadsizebias up one, then put it back down to reflect the top LOD level PWT.quadsizeBiasIndex++; PWT.RenderVertexColors(LOD1.ToArray()); PWT.quadsizeBiasIndex--; } } GUILayout.Space(10f); } else { PWT.prefabPath = null; //we reset the prefab path since there aren't any polyworld terrains PWT.meshPath = null; } #region Generate Button if (GUILayout.Button(UpdateImg, GUILayout.Height(UpdateImg.height), GUILayout.Width(UpdateImg.width), GUILayout.ExpandWidth(true))) { if (RunChecks()) { if (PWT.deletePWTerrain) { if (Selection.activeGameObject.transform.childCount > 0) { for (int c = Selection.activeGameObject.transform.childCount - 1; c >= 0; c--) { GameObject.DestroyImmediate(Selection.activeGameObject.transform.GetChild(c).gameObject); } } } int priorBiasIndex = PWT.quadsizeBiasIndex; List <GameObject[]> everyLODSet = new List <GameObject[]>(); // a list of gameobject arrays. Each element represents LOD sets. everyLODSet[0] is LOD0, [1] is LOD1, etc.. We do this becasue we don't know how many LOD sets there will be. GameObject previousPWT = (GameObject)PrefabUtility.GetPrefabParent(PWT.gameObject.GetComponentInChildren <Transform>().gameObject); GameObject PWTParent = new GameObject(); //our main parent. PWTParent.name = PWT.gameObject.name + "-Faceted"; PWTParent.transform.position = PWT.gameObject.transform.position; PWTParent.transform.parent = PWT.gameObject.transform; if (PWT.GenerateLODs) { int lodCounter = 0; everyLODSet.Add(PWT.GeneratePolyWorldTerrain(PWTParent, lodCounter)); if (PWT.quadsizeBiasIndex != PWT.quadsizeBias.Length - 1) //change ths to a while loop for more lods. don't forget to change UpdateLODSizes() method and LODSizes! { lodCounter++; PWT.quadsizeBiasIndex++; everyLODSet.Add(PWT.GeneratePolyWorldTerrain(PWTParent, lodCounter)); } } else { everyLODSet.Add(PWT.GeneratePolyWorldTerrain(PWTParent, 0)); } //save the meshes to disk. associate them with the right gameobject. //WriteAllContent(PWTParent, everyLODSet); //go through all the chunks. we do [0] because each element is the same length, and we reference them directly, so it doesn't matter. if (PWT.GenerateLODs) { //for every chunk.. for (int chunkIndex = 0; chunkIndex < everyLODSet[0].Length; chunkIndex++) { //everylodset[0] is lod0, [1] is lod1, etc.. GameObject LODObject = new GameObject(); LODObject.transform.parent = PWTParent.transform; //parent it to the terrain LODObject.transform.position = everyLODSet[0][chunkIndex].transform.position; //move it to the lod0 position LODObject.name = everyLODSet[0][chunkIndex].name; LODObject.name = LODObject.name.Replace("LOD0", ""); everyLODSet[0][chunkIndex].transform.parent = LODObject.transform; LODGroup LODG = LODObject.AddComponent <LODGroup>(); LOD[] lods = new LOD[everyLODSet.Count]; //go through each LOD at the current chunkindex and grab the renderer component for (int LODIndex = 0; LODIndex < everyLODSet.Count; LODIndex++) { everyLODSet[LODIndex][chunkIndex].transform.parent = LODObject.transform; Renderer[] renderer = new Renderer[1]; //declare an array to hold the mesh renderer component of the associated lod //grab the renderer component from the LOD->Chunk renderer[0] = everyLODSet[LODIndex][chunkIndex].GetComponent <Renderer>(); //plug it into the lod array lods[LODIndex] = new LOD(PWT.LODSizes[LODIndex], renderer); // lods[LODIndex].fadeTransitionWidth = 0.5f; } // LODG.fadeMode = LODFadeMode.CrossFade; LODG.SetLODs(lods); } } PWT.quadsizeBiasIndex = priorBiasIndex; if (PWT.disableConfirmation == false) { EditorUtility.DisplayDialog("Success!", "PolyWorld Terrain has been generated and linked to the current Unity Terrain.", "OK"); } else { Debug.Log("PolyWorld Terrain generated and linked to Gameobject: " + Selection.activeGameObject.name); } if (previousPWT) { PrefabUtility.ReplacePrefab(PWTParent, previousPWT); } else { PrefabUtility.CreatePrefab("Assets" + PWT.prefabPath + "/" + PWTParent.gameObject.name + ".prefab", PWTParent); } } } #endregion GUILayout.EndVertical(); EditorGUILayout.Space(); GUILayout.BeginVertical(GUI.skin.box); PWT.quadsizeBiasIndex = EditorGUILayout.IntSlider("Quad Size Multiplier:", PWT.quadsizeBiasIndex, 0, 4); PWT.chunkIndex = EditorGUILayout.IntSlider("Chunk Size Choice:", PWT.chunkIndex, 0, PWT.chunkSizes.Length - 1); GUILayout.EndVertical(); GUILayout.BeginVertical(GUI.skin.box); EditorGUILayout.BeginHorizontal(); if (PWT.chunkIndex != PWT.chunkSizes.Length - 1) { GUILayout.Label("Chunk Size: " + PWT.chunkSizes[PWT.chunkIndex].x + "m X " + PWT.chunkSizes[PWT.chunkIndex].y + "m"); } else { GUILayout.Label("No chunk pass!"); } float numMeshes = (PWT.TWidth / PWT.chunkSizes[PWT.chunkIndex].x) * (PWT.TLength / PWT.chunkSizes[PWT.chunkIndex].y); if (numMeshes > 300) { GUI.color = new Color(1f, 1f, 0f); } else { GUI.color = new Color(1f, 1f, 1f); } GUILayout.Label("Meshes Generated: " + numMeshes); EditorGUILayout.EndHorizontal(); GUILayout.Label("Quad Size: " + PWT.quadWidth + " x " + PWT.quadLength); int numQuadsX = (int)(PWT.chunkSizes[PWT.chunkIndex].x / PWT.quadWidth); int numQuadsZ = (int)(PWT.chunkSizes[PWT.chunkIndex].y / PWT.quadLength); int triCount = (numQuadsX * numQuadsZ) * 2; int vertCount = triCount * 3; GUI.color = new Color(1f, 1f, 1f); GUILayout.Label("Triangles per Chunk: " + triCount); if (vertCount > 65536) { GUI.color = new Color(1f, 0f, 0f); } else { GUI.color = new Color(1f, 1f, 1f); } GUILayout.Label("Vertices per Chunk: " + vertCount); GUI.color = new Color(1f, 1f, 1f); GUILayout.EndVertical(); GUILayout.Space(10); GUILayout.BeginVertical(GUI.skin.box); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Material to Apply:"); PWT.PWTMat = (Material)EditorGUILayout.ObjectField(PWT.PWTMat, typeof(Material), false); EditorGUILayout.EndHorizontal(); GUI.color = new Color(1f, 1f, 1f); PWT.CV = (QT_PolyWorldTerrain.ColorVariety)EditorGUILayout.EnumPopup("Color Variety: ", PWT.CV); EditorGUILayout.BeginHorizontal(); PWT.BaseMapMip = PWT.GetTilingValue(PWT.CV); PWT.blurPasses = EditorGUILayout.IntSlider("Blur Amount:", PWT.blurPasses, 0, 8); PWT.quadColor = GUILayout.Toggle(PWT.quadColor, "Color by Quad"); EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Space(10); GUILayout.BeginVertical(GUI.skin.box); EditorGUILayout.BeginHorizontal(); if (PWT.quadsizeBiasIndex == PWT.quadsizeBias.Length - 1) { GUI.color = new Color(1f, 0f, 0f); } else { GUI.color = new Color(1f, 1f, 1f); } PWT.GenerateLODs = GUILayout.Toggle(PWT.GenerateLODs, "Generate LODs"); //PWT.Average = EditorGUILayout.Toggle("Average Vertices", PWT.Average); GUI.color = new Color(1f, 1f, 1f); if (PWT.quadsizeBiasIndex == PWT.quadsizeBias.Length - 1) { PWT.GenerateLODs = false; GUILayout.Label("No Valid LODS with Current Settings"); } EditorGUILayout.EndHorizontal(); if (PWT.GenerateLODs) { GUILayout.Label("Transition Distances:"); EditorGUILayout.BeginHorizontal(); //PWT.LODSizes[0] = Mathf.Clamp01(EditorGUILayout.FloatField("LOD1 %: ", PWT.LODSizes[0])); // PWT.LODSizes[1] = Mathf.Clamp(EditorGUILayout.FloatField("Culled %: ", PWT.LODSizes[1]),0,PWT.LODSizes[0]-.01f); GUILayout.Label("LOD 1:"); PWT.LODSizes[0] = EditorGUILayout.Slider(PWT.LODSizes[0], PWT.LODSizes[1], 1); GUILayout.Label("Cull:"); PWT.LODSizes[1] = EditorGUILayout.Slider(PWT.LODSizes[1], 0, PWT.LODSizes[0]); EditorGUILayout.EndHorizontal(); if (Selection.activeGameObject.transform.childCount > 0) { if (GUILayout.Button("Update LOD Sizes")) { PWT.UpdateLODSizes(); } } } //override this so we don't get multiple terrains in a hierarchy for when we render vertex colors PWT.deletePWTerrain = GUILayout.Toggle(PWT.deletePWTerrain, "Delete Polyworld Terrains on Update"); PWT.disableConfirmation = GUILayout.Toggle(PWT.disableConfirmation, "Disable Confirmation"); GUILayout.EndVertical(); if (GUILayout.Button("Help")) { Application.OpenURL("http://qt-ent.com/PolyWorld/scripts/"); } for (int x = 0; x < PWT.terrainData.splatPrototypes.Length; x++) { SetTextureImporterFormat(true, PWT.terrainData.splatPrototypes[x].texture); } }
private void OnGUI() { GUILayout.Label("Surreal Grass Creator", EditorStyles.boldLabel); scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false); //camera = (Camera)EditorGUILayout.ObjectField(new GUIContent("1. Camera"), camera, typeof(Camera)); targetObject = (GameObject)EditorGUILayout.ObjectField(new GUIContent("1. Target GameObject"), targetObject, typeof(GameObject)); if (GUILayout.Button("Auto-Assign Cell Division and Grass Density")) { if (targetObject == null) { ShowNotification(new GUIContent("You must select a Target Object before auto-assigning cell division and grass density.")); return; } else { Bounds objectBounds = new Bounds(); if (targetObject.GetComponent <Terrain>() != null) { objectBounds = targetObject.GetComponent <Terrain>().terrainData.bounds; } else if (targetObject.GetComponent <MeshRenderer>() != null) { objectBounds = targetObject.GetComponent <MeshRenderer>().bounds; } else { ShowNotification(new GUIContent("Please select a valid Target GameObject")); return; } float boundX = objectBounds.extents.x * 2; float boundZ = objectBounds.extents.z * 2; float cellDivSuggestion = 0; if (boundX < boundZ) { cellDivSuggestion = boundX / 10; } else { cellDivSuggestion = boundZ / 10; } //if (cellDivSuggestion < 1f) // cellDivisions = 1f; //else cellDivisions = Convert.ToInt32(Math.Ceiling(cellDivSuggestion)); float size = objectBounds.extents.x > objectBounds.extents.z ? objectBounds.extents.x * 2 / (float)cellDivisions : objectBounds.extents.z * 2 / (float)cellDivisions; if (size >= 10) { grassSamples = 60000; } else { grassSamples = Convert.ToInt32(Math.Ceiling(size / (float)10 * (float)60000)); } } } List <GUIContent> tempLayerList = new List <GUIContent>(); for (int i = 0; i <= 31; i++) { var layer = LayerMask.LayerToName(i); if (layer.Length > 0) { if (FindGameObjectsWithLayer(layer) == null) { tempLayerList.Add(new GUIContent(layer)); } } } layers = tempLayerList.ToArray(); selectedLayer = EditorGUILayout.Popup(new GUIContent("2. Empty Layer"), selectedLayer, layers); densityMap = (Texture2D)EditorGUILayout.ObjectField(new GUIContent("3. Grass Density Map"), densityMap, typeof(Texture2D)); cellDivisions = EditorGUILayout.IntSlider(new GUIContent("4. Cell Divisions"), cellDivisions, 1, 1000); grassSamples = EditorGUILayout.IntSlider(new GUIContent("5. Cell Grass Density"), grassSamples, 0, 60000); //cullDistance = EditorGUILayout.FloatField(new GUIContent("7. Cull Distance"), cullDistance); grassMaterial = (Material)EditorGUILayout.ObjectField(new GUIContent("6. Grass Material"), grassMaterial, typeof(Material)); GUILayout.Space(15.0f); GUILayout.Label("How To Use", EditorStyles.boldLabel); string descriptionString = "Surreal Grass works by creating a grid of cells over your entire target terrain or mesh, each cell then gets populated with " + "a specified number of grass blades. This editor will generate all of the cells for you and pack them into one object " + " in your scene."; GUILayout.Label(descriptionString, EditorStyles.wordWrappedLabel); GUILayout.Label("*** Disclaimer ***", EditorStyles.boldLabel); GUILayout.Label("Surreal Grass will create a new layer in your scene and temporarily move the Target Object to that layer. After the tools runs, it will move your Target Object back to its original layer.", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 1: You can run this tool multiple times to have grass spawn on different objects, just select a new Target GameObject each time you run the tool. (this setting cannot be changed after creating Grass objects)", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 2: You must create and assign an empty layer to the Surreal Grass Creator to do it's thing on. This layer can be deleted after the tool runs or it can be reused for running the tool multiple times as long as it stays empty.", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 3: This is the density map that will be applied to your target object to determine where grass is rendered. BLACK = rendered, WHITE = not rendered (this setting cannot be changed after creating Grass objects)", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 4: This figure determines the size of each cell. e.g. A value of \"10\" will calculate 10 divisions in the X direction and 10 divisions in the Z direction resulting in 100 total cells. A good grass density is about 60,000 blades per 10m square. So it's good to make sure that your cell divisions figure results in a cell size of around 10m. If your mesh/terrain is smaller than 10m square, then just use a division of \"1\". The higher the number of divisions, the longer this tool takes to run. (this setting cannot be changed after creating Grass objects)", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 5: Surreal Grass allows up to 60,000 blades of grass per cell. (this setting cannot be changed after creating Grass objects)", EditorStyles.wordWrappedLabel); GUILayout.Space(15.0f); GUILayout.Label("Step 6: Multiple grass materials can be created using the SurrealGrassShader, select the grass material you want to use for this Target object. The selected material DOES NOT replace the material on the object itself. If none is selected, the creator will use the \"SurrealDefaultGrassMat\" material", EditorStyles.wordWrappedLabel); GUILayout.EndScrollView(); if (GUILayout.Button("Generate Grass Objects")) { if (targetObject == null) { ShowNotification(new GUIContent("You must select a Target Object before generating grass objects.")); return; } else { Bounds objectBounds = new Bounds(); int targetObjectType = 0; if (targetObject.GetComponent <Terrain>() != null) { objectBounds = targetObject.GetComponent <Terrain>().terrainData.bounds; targetObjectType = 1; } else if (targetObject.GetComponent <MeshRenderer>() != null) { objectBounds = targetObject.GetComponent <MeshRenderer>().bounds; targetObjectType = 2; } else { ShowNotification(new GUIContent("Please select a valid Target GameObject")); return; } float size = objectBounds.extents.x > objectBounds.extents.z ? objectBounds.extents.x * 2 / cellDivisions : objectBounds.extents.z * 2 / cellDivisions; float destYPosition = (objectBounds.extents.y * 2) + 100f; float srcXPosition = targetObject.transform.position.x - (targetObjectType == 2 ? objectBounds.extents.x : 0f); float srcZPosition = targetObject.transform.position.z - (targetObjectType == 2 ? objectBounds.extents.z : 0f); float destXorigin = srcXPosition; float destZorigin = srcZPosition; float destXPosition = srcXPosition; float destZPosition = srcZPosition; LayerMask layerMask = new LayerMask(); layerMask.value = LayerMask.NameToLayer(layers[selectedLayer].text); originalLayer = targetObject.layer; targetObject.layer = layerMask.value; GameObject parentEmpty = new GameObject(targetObject.name + "_SGRenderer"); parentEmpty.transform.position = new Vector3(srcXPosition, targetObject.transform.position.y, srcZPosition); for (int x = 0; x < cellDivisions; x++) { destZPosition = destZorigin; destXPosition = destXorigin + (x * size); for (int z = 0; z < cellDivisions; z++) { destZPosition = destZorigin + (z * size); GameObject lod = new GameObject(targetObject.name + "_SGRendererLOD_" + x.ToString() + "_" + z.ToString()); GameObject empty = new GameObject(targetObject.name + "_SGRenderer_" + x.ToString() + "_" + z.ToString()); MeshFilter filter = empty.AddComponent <MeshFilter>(); MeshRenderer renderer = empty.AddComponent <MeshRenderer>(); //filter.name = targetObject.name + "_SGMeshFilter"; Mesh mesh = new Mesh(); empty.layer = layerMask.value; empty.transform.position = new Vector3(srcXPosition, targetObject.transform.position.y, srcZPosition); List <Vector3> positions = new List <Vector3>(); List <int> indicies = new List <int>(); List <Vector3> normals = new List <Vector3>(); int hitCount = 0; for (int i = 0; i < grassSamples; i++) { Vector3 origin = new Vector3(destXPosition, destYPosition, destZPosition); origin.x += size * UnityEngine.Random.Range(0.0f, 1f); origin.z += size * UnityEngine.Random.Range(0.0f, 1f); Ray ray = new Ray(origin, Vector3.down); RaycastHit hit; if (Physics.Raycast(ray, out hit, 1000f, 1 << layerMask.value)) { bool record = true; if (densityMap != null) { record = false; Vector2 uvCoord = hit.textureCoord; Color color = densityMap.GetPixel(Convert.ToInt32(uvCoord.x * densityMap.width), Convert.ToInt32(uvCoord.y * densityMap.height)); if (color.grayscale < 0.5f) { record = true; } } if (record) { origin.x -= empty.transform.position.x; origin.z -= empty.transform.position.z; positions.Add(hit.point); indicies.Add(hitCount); normals.Add(hit.normal); hitCount += 1; } } } if (hitCount > 1) { mesh.SetVertices(positions); mesh.SetIndices(indicies.ToArray(), MeshTopology.Points, 0); mesh.SetNormals(normals); filter.mesh = mesh; filter.transform.position = new Vector3(0, 0, 0); if (grassMaterial != null) { renderer.material = grassMaterial; } parentEmpty.layer = layerMask.value; empty.layer = layerMask.value; lod.transform.SetParent(parentEmpty.transform, true); empty.transform.SetParent(lod.transform, true); lod.AddComponent <LODGroup>(); LODGroup lodGroup = lod.GetComponent <LODGroup>(); LOD[] lods = new LOD[1]; Renderer[] rendArray = new Renderer[1]; rendArray[0] = empty.GetComponent <Renderer>(); lods[0] = new LOD(0.14f, rendArray); //lods[1] = new LOD(0.27f, new Renderer[0]); lodGroup.SetLODs(lods); } else { DestroyImmediate(empty); } } } targetObject.layer = originalLayer; } } }
public static GameObject LoadOBJFile(string fn) { Debug.Log("Loading map...."); Debug.Log(fn); MaterialLoader.LoadAlphaMaterial(); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fn); if (fileNameWithoutExtension.Contains("alpha")) { alphaIsEnabledOld = true; } else { alphaIsEnabledOld = false; } bool flag2 = false; List <Vector3> list = new List <Vector3>(); List <Vector3> list2 = new List <Vector3>(); List <Vector2> list3 = new List <Vector2>(); List <Vector3> list4 = new List <Vector3>(); List <Vector3> list5 = new List <Vector3>(); List <Vector2> list6 = new List <Vector2>(); List <string> list7 = new List <string>(); List <string> list8 = new List <string>(); Dictionary <string, int> dictionary = new Dictionary <string, int>(); List <OBJFace> list9 = new List <OBJFace>(); string text = ""; string text2 = "default"; Material[] array = null; FileInfo fileInfo = new FileInfo(fn); string[] text3 = File.ReadAllLines(fn); for (int e = 0; e < text3.Length; e++) { if (text3[e].Length > 0 && text3[e][0] != '#') { string text4 = text3[e].Trim().Replace(" ", " "); string[] array2 = text4.Split(new char[] { ' ' }); string text5 = text4.Remove(0, text4.IndexOf(' ') + 1); switch (array2[0]) { case "o": text2 = text5; if (!list8.Contains(text2)) { list8.Add(text2); } break; case "mtllib": string text6 = Search.OBJGetFilePath(text5, fileInfo.Directory.FullName + Path.DirectorySeparatorChar.ToString(), fileNameWithoutExtension); if (text6 != null) { array = MaterialLoader.LoadMTLFile(text6, alphaIsEnabledOld); } break; case "usemtl": text = text5; if (!list7.Contains(text)) { list7.Add(text); } if (splitByMaterial && !list8.Contains(text)) { list8.Add(text); } break; case "v": list.Add(ParseVectorFromCMPS(array2)); break; case "vn": list2.Add(ParseVectorFromCMPS(array2)); break; case "vt": list3.Add(ParseVectorFromCMPS(array2)); break; case "f": int[] array3 = new int[array2.Length - 1]; for (int i = 1; i < array2.Length; i++) { string text7 = array2[i]; int num = -1; int num2 = -1; int num3; if (text7.Contains("//")) { string[] array8 = text7.Split(new char[] { '/' }); num3 = int.Parse(array8[0]) - 1; num = int.Parse(array8[2]) - 1; } else if (text7.Count(new Func <char, bool>(OBJLoader.Func1)) == 2) { string[] array9 = text7.Split(new char[] { '/' }); num3 = int.Parse(array9[0]) - 1; num2 = int.Parse(array9[1]) - 1; num = int.Parse(array9[2]) - 1; } else if (!text7.Contains("/")) { num3 = int.Parse(text7) - 1; } else { string[] array10 = text7.Split(new char[] { '/' }); num3 = int.Parse(array10[0]) - 1; num2 = int.Parse(array10[1]) - 1; } string key = string.Concat(new object[] { num3, "|", num, "|", num2 }); if (dictionary.ContainsKey(key)) { array3[i - 1] = dictionary[key]; } else { array3[i - 1] = dictionary.Count; dictionary[key] = dictionary.Count; list4.Add(list[num3]); if (num < 0 || num > list2.Count - 1) { list5.Add(Vector3.zero); } else { flag2 = true; list5.Add(list2[num]); } if (num2 < 0 || num2 > list3.Count - 1) { list6.Add(Vector2.zero); } else { list6.Add(list3[num2]); } } } if (array3.Length < 5 && array3.Length >= 3) { List <OBJFace> list10 = list9; OBJFace objface3 = new OBJFace { materialName = text, indexes = new int[] { array3[0], array3[1], array3[2] }, meshName = (splitByMaterial ? text : text2) }; OBJFace item = objface3; list10.Add(item); if (array3.Length > 3) { List <OBJFace> list11 = list9; objface3 = new OBJFace { materialName = text, meshName = (splitByMaterial ? text : text2), indexes = new int[] { array3[2], array3[3], array3[0] } }; item = objface3; list11.Add(item); } } break; } } } if (list8.Count == 0) { list8.Add("default"); } GameObject gameObject = new GameObject("ModdedMap"); using (List <string> .Enumerator enumerator = list8.GetEnumerator()) { while (enumerator.MoveNext()) { string obj = enumerator.Current; GameObject gameObject2 = new GameObject(obj); gameObject2.transform.parent = gameObject.transform; gameObject2.transform.localScale = new Vector3(-1f, 1f, 1f); Mesh mesh = new Mesh(); mesh.name = obj; List <Vector3> list12 = new List <Vector3>(); List <Vector3> list13 = new List <Vector3>(); List <Vector2> list14 = new List <Vector2>(); List <int[]> list15 = new List <int[]>(); Dictionary <int, int> dictionary2 = new Dictionary <int, int>(); OBJLoader.meshMaterialNames = new List <string>(); OBJFace[] source = list9.Where(x => x.meshName == obj).ToArray <OBJFace>(); using (List <string> .Enumerator enumerator2 = list7.GetEnumerator()) { while (enumerator2.MoveNext()) { mn = enumerator2.Current; OBJFace[] array4 = source.Where(x => x.materialName == mn).ToArray <OBJFace>(); if (array4.Length != 0) { int[] array5 = new int[0]; foreach (OBJFace objface2 in array4) { int num4 = array5.Length; Array.Resize <int>(ref array5, num4 + objface2.indexes.Length); Array.Copy(objface2.indexes, 0, array5, num4, objface2.indexes.Length); } meshMaterialNames.Add(mn); if (mesh.subMeshCount != meshMaterialNames.Count) { mesh.subMeshCount = meshMaterialNames.Count; } for (int j = 0; j < array5.Length; j++) { int num5 = array5[j]; if (dictionary2.ContainsKey(num5)) { array5[j] = dictionary2[num5]; } else { list12.Add(list4[num5]); list13.Add(list5[num5]); list14.Add(list6[num5]); dictionary2[num5] = list12.Count - 1; array5[j] = dictionary2[num5]; } } list15.Add(array5); } } } mesh.SetVertices(list12); mesh.SetNormals(list13); mesh.SetUVs(0, list14); for (int k = 0; k < list15.Count; k++) { mesh.SetIndices(list15[k], MeshTopology.Triangles, k); } if (!flag2) { mesh.RecalculateNormals(); } mesh.RecalculateBounds(); Material[] array6 = new Material[meshMaterialNames.Count]; counter = 0; while (counter < meshMaterialNames.Count) { if (array == null) { Debug.Log("array null"); array6[counter] = new Material(Shader.Find("HDRP/Lit")); } else { Material[] array12 = array; Predicate <Material> match; if ((match = haha3) == null) { match = haha3 = new Predicate <Material>(LoadOBJFile3); } Material material = Array.Find(array12, match); Debug.Log(material); if (material == null) { Debug.Log("material null"); array6[counter] = new Material(Shader.Find("HDRP/Lit")); } else { array6[counter] = material; } } array6[counter].name = meshMaterialNames[counter]; int i2 = counter; counter = i2 + 1; } meshFilter = gameObject2.AddComponent <MeshFilter>(); meshRenderer = gameObject2.AddComponent <MeshRenderer>(); meshRenderer.receiveShadows = true; meshFilter.mesh = mesh; meshRenderer.materials = array6; if (MaterialLoader.alphaIsEnabled || alphaIsEnabledOld) { Renderer[] newRenderer = new Renderer[1]; newRenderer[0] = meshRenderer; LODGroup lods = gameObject2.AddComponent <LODGroup>(); LOD[] lod = new LOD[1]; lod[0].renderers = newRenderer; lod[0].screenRelativeTransitionHeight = 0.8f; lods.SetLODs(lod); lods.RecalculateBounds(); } if (!alphaIsEnabledOld) { meshCollider = gameObject2.AddComponent <MeshCollider>(); meshCollider.convex = false; meshCollider.sharedMesh = mesh; CarX.Material carXMaterial = gameObject2.AddComponent <CarX.Material>(); string objectParams = gameObject2.name.Split('_')[0].ToLower(); switch (objectParams) { case "road": Debug.Log("road set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Asphalt, 1, 0.01f, 0f, 0f, 100f, 0f, 0f, 100f); gameObject2.isStatic = true; break; case "kerb": Debug.Log("kerb set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Asphalt, 1, 0.015f, -0.007f, 0f, 12f, -0.007f, 0f, 12f); gameObject2.isStatic = true; break; case "sand": Debug.Log("sand set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Sand, 1, 0.13f, 0.06f, 0.05f, 25f, 0.06f, 0.05f, 25f); gameObject2.isStatic = true; break; case "snow": Debug.Log("snow set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Snow, 2, 0.1f, -0.01f, -0.01f, 30f, -0.01f, -0.01f, 30f); gameObject2.isStatic = true; break; case "grass": Debug.Log("grass set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Grass, 1, 0f, 0.05f, 0.04f, 25f, 0.05f, 0.04f, 25f); gameObject2.isStatic = true; break; case "gravel": Debug.Log("gravel set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Sand, 2, 0.1f, -0.01f, -0.01f, 30f, -0.01f, -0.01f, 30f); gameObject2.isStatic = true; break; case "icyroad": Debug.Log("icyroad set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Asphalt, 0.73f, 0.025f, 0f, 0f, 30f, 0f, 0f, 30f); gameObject2.isStatic = true; break; case "dirt": Debug.Log("dirt set"); gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Earth, 1, 0.025f, -0.007f, 0f, 12f, -0.007f, 0f, 12f); gameObject2.isStatic = true; break; case "nocol": Debug.Log("nocol set"); meshCollider.enabled = false; gameObject2.isStatic = true; break; case "rb": Debug.Log("rb set"); gameObject2.transform.SetParent(null); meshCollider.convex = true; Rigidbody rb = gameObject2.AddComponent <Rigidbody>(); rbGos.Add(gameObject2); gameObject2.isStatic = false; break; default: gameObject2.AddComponent <CARXSurface>(); carXMaterial.SetParameters(CarX.SurfaceType.Asphalt, 1, 0.01f, 0f, 0f, 100f, 0f, 0f, 100f); gameObject2.isStatic = true; Debug.Log("Surface not set for this object"); break; } } gameObject2.layer = 11; } } return(gameObject); }