Ejemplo n.º 1
0
        public IEnumerator CreateImpl()
        {
            try
            {
                using (m_queue = new JobQueue(8))
                {
                    Stopwatch sw = new Stopwatch();

                    AssetDatabase.Refresh();
                    AssetDatabase.SaveAssets();

                    sw.Reset();
                    sw.Start();

                    EditorUtility.DisplayProgressBar("Bake HLOD", "Initialize Bake", 0.0f);


                    TerrainData data = m_hlod.TerrainData;

                    m_size = data.size;

                    m_heightmap = new Heightmap(data.heightmapResolution, data.heightmapResolution, data.size,
                                                data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution));

                    string materialPath = AssetDatabase.GUIDToAssetPath(m_hlod.MaterialGUID);
                    m_terrainMaterial = AssetDatabase.LoadAssetAtPath <Material>(materialPath);
                    if (m_terrainMaterial == null)
                    {
                        m_terrainMaterial = new Material(Shader.Find("Standard"));
                    }

                    m_terrainMaterialInstanceId = m_terrainMaterial.GetInstanceID();
                    m_terrainMaterialName       = m_terrainMaterial.name;

                    using (m_alphamaps = new DisposableList <WorkingTexture>())
                        using (m_layers = new DisposableList <Layer>())
                        {
                            for (int i = 0; i < data.alphamapTextures.Length; ++i)
                            {
                                m_alphamaps.Add(new WorkingTexture(Allocator.Persistent, data.alphamapTextures[i]));
                            }

                            for (int i = 0; i < data.terrainLayers.Length; ++i)
                            {
                                m_layers.Add(new Layer(data.terrainLayers[i]));
                            }


                            QuadTreeSpaceSplitter splitter =
                                new QuadTreeSpaceSplitter(0.0f);

                            SpaceNode rootNode = splitter.CreateSpaceTree(m_hlod.GetBounds(), m_hlod.ChunkSize * 2.0f,
                                                                          m_hlod.transform.position, null, progress => { });

                            EditorUtility.DisplayProgressBar("Bake HLOD", "Create mesh", 0.0f);

                            using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(data, rootNode))
                            {
                                yield return(m_queue.WaitFinish());

                                //Write material & textures

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    int curIndex = i;
                                    m_queue.EnqueueJob(() =>
                                    {
                                        ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(m_hlod.SimplifierType,
                                                                                                       new object[] { m_hlod.SimplifierOptions });
                                        simplifier.SimplifyImmidiate(buildInfos[curIndex]);
                                    });
                                }

                                EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.0f);
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Simplify: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();
                                EditorUtility.DisplayProgressBar("Bake HLOD", "Make border", 0.0f);

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    HLODBuildInfo info = buildInfos[i];
                                    m_queue.EnqueueJob(() =>
                                    {
                                        for (int oi = 0; oi < info.WorkingObjects.Count; ++oi)
                                        {
                                            WorkingObject o       = info.WorkingObjects[oi];
                                            int borderVertexCount = m_hlod.BorderVertexCount * Mathf.RoundToInt(Mathf.Pow(2.0f, (float)info.Distances[oi]));
                                            using (WorkingMesh m = MakeBorder(o.Mesh, info.Heightmap, borderVertexCount))
                                            {
                                                ReampUV(m, info.Heightmap);
                                                o.SetMesh(MakeFillHoleMesh(m));
                                            }
                                        }
                                    });
                                }
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Make Border: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();


                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    SpaceNode     node = buildInfos[i].Target;
                                    HLODBuildInfo info = buildInfos[i];
                                    if (node.HasChild() == false)
                                    {
                                        SpaceNode parent = node.ParentNode;
                                        node.ParentNode = null;

                                        GameObject go = new GameObject(buildInfos[i].Name);

                                        for (int wi = 0; wi < info.WorkingObjects.Count; ++wi)
                                        {
                                            WorkingObject wo       = info.WorkingObjects[wi];
                                            GameObject    targetGO = null;
                                            if (wi == 0)
                                            {
                                                targetGO = go;
                                            }
                                            else
                                            {
                                                targetGO = new GameObject(wi.ToString());
                                                targetGO.transform.SetParent(go.transform, false);
                                            }

                                            List <Material> materials = new List <Material>();
                                            for (int mi = 0; mi < wo.Materials.Count; ++mi)
                                            {
                                                WorkingMaterial wm = wo.Materials[mi];
                                                if (wm.NeedWrite() == false)
                                                {
                                                    materials.Add(wm.ToMaterial());
                                                    continue;
                                                }

                                                Material mat          = new Material(wm.ToMaterial());
                                                string[] textureNames = wm.GetTextureNames();
                                                for (int ti = 0; ti < textureNames.Length; ++ti)
                                                {
                                                    WorkingTexture wt  = wm.GetTexture(textureNames[ti]);
                                                    Texture2D      tex = wt.ToTexture();
                                                    tex.wrapMode = wt.WrapMode;
                                                    mat.name     = targetGO.name + "_Mat";
                                                    mat.SetTexture(textureNames[ti], tex);
                                                }
                                                mat.EnableKeyword("_NORMALMAP");
                                                materials.Add(mat);
                                            }

                                            targetGO.AddComponent <MeshFilter>().sharedMesh        = wo.Mesh.ToMesh();
                                            targetGO.AddComponent <MeshRenderer>().sharedMaterials = materials.ToArray();
                                        }

                                        go.transform.SetParent(m_hlod.transform, false);
                                        m_hlod.AddGeneratedResource(go);

                                        parent.Objects.Add(go);
                                        buildInfos.RemoveAt(i);
                                        i -= 1;
                                    }
                                }

                                //controller
                                IStreamingBuilder builder =
                                    (IStreamingBuilder)Activator.CreateInstance(m_hlod.StreamingType,
                                                                                new object[] { m_hlod, m_hlod.StreamingOptions });

                                builder.Build(rootNode, buildInfos, m_hlod.gameObject, m_hlod.CullDistance, m_hlod.LODDistance, true, false,
                                              progress =>
                                {
                                    EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.",
                                                                     0.75f + progress * 0.25f);
                                });

                                Debug.Log("[TerrainHLOD] Build: " + sw.Elapsed.ToString("g"));
                            }
                        }

                    EditorUtility.SetDirty(m_hlod.gameObject);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                GC.Collect();
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            EditorGUI.BeginChangeCheck();

            TerrainHLOD hlod = target as TerrainHLOD;

            if (hlod == null)
            {
                EditorGUILayout.LabelField("TerrainHLOD is null.");
                return;
            }
            isShowCommon = EditorGUILayout.BeginFoldoutHeaderGroup(isShowCommon, "Common");
            if (isShowCommon == true)
            {
                EditorGUILayout.PropertyField(m_TerrainDataProperty, Styles.SourceText);
                EditorGUILayout.PropertyField(m_DestoryTerrainProperty, Styles.DestoryTerrainText);
                EditorGUILayout.PropertyField(m_ChunkSizeProperty);

                m_ChunkSizeProperty.floatValue = HLODUtils.GetChunkSizePropertyValue(m_ChunkSizeProperty.floatValue);

                var bounds = hlod.GetBounds();
                int depth  = m_splitter.CalculateTreeDepth(bounds, m_ChunkSizeProperty.floatValue);
                EditorGUILayout.LabelField($"The HLOD tree will be created with {depth} levels.");
                if (depth > 5)
                {
                    EditorGUILayout.LabelField($"Node Level Count greater than 5 may cause a frozen Editor.", Styles.RedTextColor);
                    EditorGUILayout.LabelField($"Use a value less than 5.", Styles.RedTextColor);
                }


                EditorGUILayout.PropertyField(m_BorderVertexCountProperty);
                m_LODSlider.Draw();
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            isShowSimplifier = EditorGUILayout.BeginFoldoutHeaderGroup(isShowSimplifier, "Simplifier");
            if (isShowSimplifier == true)
            {
                if (m_SimplifierTypes.Length > 0)
                {
                    int simplifierIndex = Math.Max(Array.IndexOf(m_SimplifierTypes, hlod.SimplifierType), 0);
                    simplifierIndex     = EditorGUILayout.Popup("Simplifier", simplifierIndex, m_SimplifierNames);
                    hlod.SimplifierType = m_SimplifierTypes[simplifierIndex];

                    var info = m_SimplifierTypes[simplifierIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod.SimplifierOptions });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Can not find Simplifiers.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            isShowMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(isShowMaterial, "Material");
            if (isShowMaterial == true)
            {
                Material mat     = null;
                string   matGUID = hlod.MaterialGUID;
                if (string.IsNullOrEmpty(matGUID) == false)
                {
                    string path = AssetDatabase.GUIDToAssetPath(matGUID);
                    mat = AssetDatabase.LoadAssetAtPath <Material>(path);
                }

                mat = EditorGUILayout.ObjectField("Material", mat, typeof(Material), false) as Material;
                if (mat != null)
                {
                    string path = AssetDatabase.GetAssetPath(mat);
                    hlod.MaterialGUID = AssetDatabase.AssetPathToGUID(path);
                }

                matGUID = hlod.MaterialLowGUID;
                if (string.IsNullOrEmpty(matGUID) == false)
                {
                    string path = AssetDatabase.GUIDToAssetPath(matGUID);
                    mat = AssetDatabase.LoadAssetAtPath <Material>(path);
                }

                mat = EditorGUILayout.ObjectField("MaterialLow", mat, typeof(Material), false) as Material;
                if (mat != null)
                {
                    string path = AssetDatabase.GetAssetPath(mat);
                    hlod.MaterialLowGUID = AssetDatabase.AssetPathToGUID(path);
                }

                hlod.TextureSize = EditorGUILayout.IntPopup("Size", hlod.TextureSize, Styles.TextureSizeStrings,
                                                            Styles.TextureSizes);
                //Output Property name
                //EditorGUILayout.
                if (mat == null)
                {
                    mat = new Material(Shader.Find("Standard"));
                }

                string[] outputTexturePropertyNames = mat.GetTexturePropertyNames();
                int      index = 0;
                isShowTexturePropertices = EditorGUILayout.Foldout(isShowTexturePropertices, "Texture propertices");

                if (isShowTexturePropertices == true)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.Toggle(true, GUILayout.Width(20));
                    index = Array.IndexOf(outputTexturePropertyNames, hlod.AlbedoPropertyName);
                    index = EditorGUILayout.Popup("Albedo", index, outputTexturePropertyNames);
                    index = (index < 0) ? 0 : index;
                    hlod.AlbedoPropertyName = outputTexturePropertyNames[index];
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    hlod.UseNormal          = EditorGUILayout.Toggle(hlod.UseNormal, GUILayout.Width(20));
                    index                   = Array.IndexOf(outputTexturePropertyNames, hlod.NormalPropertyName);
                    index                   = EditorGUILayout.Popup("Normal", index, outputTexturePropertyNames);
                    index                   = (index < 0) ? 0 : index;
                    hlod.NormalPropertyName = outputTexturePropertyNames[index];
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    hlod.UseMask          = EditorGUILayout.Toggle(hlod.UseMask, GUILayout.Width(20));
                    index                 = Array.IndexOf(outputTexturePropertyNames, hlod.MaskPropertyName);
                    index                 = EditorGUILayout.Popup("Mask", index, outputTexturePropertyNames);
                    index                 = (index < 0) ? 0 : index;
                    hlod.MaskPropertyName = outputTexturePropertyNames[index];
                    EditorGUILayout.EndHorizontal();
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            isShowStreaming = EditorGUILayout.BeginFoldoutHeaderGroup(isShowStreaming, "Streaming");
            if (isShowStreaming == true)
            {
                if (m_StreamingTypes.Length > 0)
                {
                    int streamingIndex = Math.Max(Array.IndexOf(m_StreamingTypes, hlod.StreamingType), 0);
                    streamingIndex     = EditorGUILayout.Popup("Streaming", streamingIndex, m_StreamingNames);
                    hlod.StreamingType = m_StreamingTypes[streamingIndex];

                    var info = m_StreamingTypes[streamingIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod.StreamingOptions });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Can not find StreamingSetters.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            GUIContent generateButton = Styles.GenerateButtonEnable;
            GUIContent destroyButton  = Styles.DestroyButtonNotExists;

            if (hlod.GetComponent <HLODControllerBase>() != null)
            {
                generateButton = Styles.GenerateButtonExists;
                destroyButton  = Styles.DestroyButtonEnable;
            }



            EditorGUILayout.Space();

            GUI.enabled = generateButton == Styles.GenerateButtonEnable;
            if (GUILayout.Button(generateButton))
            {
                CoroutineRunner.RunCoroutine(TerrainHLODCreator.Create(hlod));
            }

            GUI.enabled = destroyButton == Styles.DestroyButtonEnable;
            if (GUILayout.Button(destroyButton))
            {
                CoroutineRunner.RunCoroutine(TerrainHLODCreator.Destroy(hlod));
            }

            GUI.enabled = true;

            serializedObject.ApplyModifiedProperties();
        }