├── Scripts ├── ColorHeight.cs ├── PlanetData.cs ├── PopulateData.cs ├── GenerationData.cs ├── Planet.cs └── Polygon.cs ├── README.md ├── PopulateData.cs └── LICENSE /Scripts/ColorHeight.cs: -------------------------------------------------------------------------------- 1 | /** 2 | ColorHeight.cs 3 | Purpose: Contains ColorHeight class and 4 | the class required to have a custom layout on the inspector. 5 | Require: No other files required. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/2018 9 | */ 10 | 11 | using UnityEngine; 12 | using UnityEditor; 13 | using System; 14 | 15 | [Serializable] 16 | public class ColorHeight 17 | { 18 | [Tooltip("Minimun height to set the color.")] 19 | public int layer; 20 | [Tooltip("Color of the mesh.")] 21 | public Color color; 22 | } 23 | 24 | [CustomPropertyDrawer(typeof(ColorHeight), true)] 25 | public class ColorHeightDrawer : PropertyDrawer 26 | { 27 | /// 28 | /// Custom GUI view of the ColorHeight class. 29 | /// 30 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 31 | { 32 | label = EditorGUI.BeginProperty(position, label, property); 33 | Rect contentPosition = EditorGUI.PrefixLabel(position, label); 34 | contentPosition.width *= 0.75f; 35 | EditorGUI.indentLevel = 0; 36 | contentPosition.width /= 2f; 37 | EditorGUIUtility.labelWidth = 45f; 38 | EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("layer"), new GUIContent("Layer")); 39 | contentPosition.x += contentPosition.width + 10; 40 | EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("color"), new GUIContent("Color")); 41 | EditorGUI.EndProperty(); 42 | } 43 | } -------------------------------------------------------------------------------- /Scripts/PlanetData.cs: -------------------------------------------------------------------------------- 1 | /** 2 | PlanetData.cs 3 | Purpose: Scriptable object that have all the data needed 4 | to crate a planet. 5 | Require: GenerationData.cs, ColorHeight.cs, PopulateData.cs. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/2018 9 | */ 10 | 11 | using UnityEngine; 12 | 13 | namespace Generation 14 | { 15 | [CreateAssetMenu()] 16 | public class PlanetData : ScriptableObject 17 | { 18 | [Tooltip("Name for the Empty Object that will hold the terrains.")] 19 | public string newName; 20 | [Tooltip("Seed for the planet.")] 21 | public int seed; 22 | [Tooltip("If true it will ignore the seed and generate a new random one.")] 23 | public bool generateRandomSeed; 24 | [Tooltip("Types of terrain generation.")] 25 | public Style terrainStyle; 26 | [Tooltip("Material for the terrain(to be able to apply the color per layer the material need to be vertex friendly).")] 27 | public Material material; 28 | [Tooltip("Material for the sea.")] 29 | public Material seaMaterial; 30 | [Space(5)] 31 | [Tooltip("Position of the center of the planet.")] 32 | public Vector3 position; 33 | [Tooltip("Radius of the planet.")] 34 | public float radius; 35 | [Tooltip("Level of the sea.")] 36 | public float seaLevel; 37 | [Tooltip("Amount of times the icosphere is divided.")] 38 | public int subdivisions; 39 | [Tooltip("Amount of times each icosphere division is divided.")] 40 | public int chunckSubdivisions; 41 | [Space(5)] 42 | [Tooltip("Noise to modify the terrain shape.")] 43 | public GenerationData[] generationData; 44 | [Tooltip("Colors for the terrain.")] 45 | public ColorHeight[] ColorPerLayer; 46 | [Tooltip("Data to populate the terrain.")] 47 | public PopulateData[] population; 48 | } 49 | /// 50 | /// Types of terrains. 51 | /// 52 | public enum Style { LowPoly, Terrace }; 53 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![status](https://img.shields.io/badge/status-discontinued-red) 2 | 3 | # New feature added: 4 | Now the planet have water and can be populate: 5 | ![](https://i.gyazo.com/0e9afa84b7d5c65a1bc8ffcbf31b4211.png) 6 | 7 | # Procedural-planet-generation (Unity Project) 8 | Generate planets proceduraly. 9 | [(Generate)](https://thehunterjp.itch.io/planetary-generation-prototype) 10 | # Low Poly style: 11 | 12 | 13 | # Terrace style: 14 | 15 | ![](https://i.gyazo.com/e15d76e0091e84ada206e3a14787739b.gif) 16 | 17 | 18 | # How to use? 19 | #### We only need to **import 5 files**: 20 | 'Planet.cs' , 'PlanetData.cs' , 'Polygon.cs' , 'ColorHeight.cs' , 'GenerationData.cs'. 21 | 22 | #### GenerationData: 23 | This scriptable object stores the information that will then be used to get the height of the map vertices (it uses perlin noise). 24 | 25 | ![](https://i.gyazo.com/18a6e7d72de6d9383ae1c72503ba8d45.png) 26 | 27 | #### PlanetData: 28 | This scriptable object stores the information that will then be used to create a planet. 29 | 30 | ![](https://i.gyazo.com/fc828f1192b56b41dce73e9fcf1df70c.png) 31 | 32 | #### Generate the planets: 33 | To add a planet to the list of planets that will be created, use the functtion: 34 | > Planet.AddPlanetToQueu(); 35 | 36 | To start the thread that will calculate the data for the mesh sphere generation and modification of the landscape (will only be executed after StartDataQueu has ended): 37 | > Planet.StartDataQueu(); 38 | 39 | Instantiate the planet into the scene: 40 | >Planet.InstantiateIntoWorld(); 41 | 42 | Wait until the planet data have been compute. Then load the chunks in range to the position. 43 | >Planet.HideAndShow(Vector3 position); 44 | 45 | Both InstantiateIntoWorld and HideAndShow can be used at the same time. In that case 46 | InstantiateIntoWorld will generate the planet until it's fully generated and the will hide all the 47 | terrain that is not in range of the position. 48 | 49 | The end result should look like this: 50 | ![](https://i.gyazo.com/f6c185f8c376b7a620202f5381a32ffe.png) 51 | -------------------------------------------------------------------------------- /PopulateData.cs: -------------------------------------------------------------------------------- 1 | /** 2 | PopulateData.cs 3 | Purpose: Scriptable object that have all the data needed 4 | to crate a planet. 5 | Require: GenerationData.cs, ColorHeight.cs, PopulateData.cs. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/2018 9 | */ 10 | 11 | using UnityEngine; 12 | 13 | namespace Generation 14 | { 15 | [CreateAssetMenu] 16 | public class PopulateData : ScriptableObject 17 | { 18 | // To generate all random numbers. 19 | private System.Random rng; 20 | 21 | [Tooltip("List of models.")] 22 | public GameObject[] models; 23 | [Tooltip("Noise.")] 24 | public GenerationData noise; 25 | [Tooltip("Minimum height to get the height.")] 26 | public int minHeight; 27 | [Tooltip("Maximum height to get the height.")] 28 | public int maxHeight; 29 | [Tooltip("Numbers of divisions.")] 30 | public int divisions; 31 | [Range(0,1)] 32 | [Tooltip("Probability to generatethe model.")] 33 | public float probability; 34 | 35 | // Offset for the noise. 36 | private Vector3 offset; 37 | 38 | /// 39 | /// Set the seed random number generator and the offset. 40 | /// 41 | /// Seed of the planet. 42 | /// List of population that want to add the seed. 43 | static public void SetSeed(int seed, PopulateData[] population) 44 | { 45 | foreach (var item in population) 46 | { 47 | item.rng = new System.Random(123); 48 | Vector3 offset = new Vector3(item.rng.Next(-10000, 10000), item.rng.Next(-10000, 10000), item.rng.Next(-10000, 10000)); 49 | } 50 | } 51 | /// 52 | /// Check if it can be instantiate. 53 | /// 54 | /// Position to check. 55 | /// Return true if it can be instantiate. 56 | public bool InstantiateAtPosition(Vector3 position) 57 | { 58 | // Get the height at the position. 59 | float height = noise.CalculateNoise(position + offset); 60 | // Check if in range. 61 | if(height > minHeight && height < maxHeight) 62 | return true; 63 | return false; 64 | } 65 | /// 66 | /// Get a random model from the list. 67 | /// 68 | /// Return a model. 69 | public GameObject GetRandomModel() 70 | { 71 | // Get random model. 72 | return models[rng.Next(0, models.Length)]; 73 | } 74 | /// 75 | /// Get the height at that position. 76 | /// 77 | /// Position to check. 78 | /// Return the height. 79 | public float GetHeightAtPosition(Vector3 position) 80 | { 81 | // Get noise at position. 82 | return noise.CalculateNoise(position + offset); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Scripts/PopulateData.cs: -------------------------------------------------------------------------------- 1 | /** 2 | PopulateData.cs 3 | Purpose: Scriptable object that have all the data needed 4 | to crate a planet. 5 | Require: GenerationData.cs, ColorHeight.cs, PopulateData.cs. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/2018 9 | */ 10 | 11 | using UnityEngine; 12 | 13 | namespace Generation 14 | { 15 | [CreateAssetMenu] 16 | public class PopulateData : ScriptableObject 17 | { 18 | // To generate all random numbers. 19 | private System.Random rng; 20 | 21 | [Tooltip("List of models.")] 22 | public GameObject[] models; 23 | [Tooltip("Noise.")] 24 | public GenerationData noise; 25 | [Tooltip("Minimum height to get the height.")] 26 | public int minHeight; 27 | [Tooltip("Maximum height to get the height.")] 28 | public int maxHeight; 29 | [Tooltip("Numbers of divisions.")] 30 | public int divisions; 31 | [Range(0,1)] 32 | [Tooltip("Probability to generatethe model.")] 33 | public float probability; 34 | 35 | // Offset for the noise. 36 | private Vector3 offset; 37 | 38 | /// 39 | /// Set the seed random number generator and the offset. 40 | /// 41 | /// Seed of the planet. 42 | /// List of population that want to add the seed. 43 | static public void SetSeed(int seed, PopulateData[] population) 44 | { 45 | foreach (var item in population) 46 | { 47 | item.rng = new System.Random(123); 48 | Vector3 offset = new Vector3(item.rng.Next(-10000, 10000), item.rng.Next(-10000, 10000), item.rng.Next(-10000, 10000)); 49 | } 50 | } 51 | /// 52 | /// Check if it can be instantiate. 53 | /// 54 | /// Position to check. 55 | /// Return true if it can be instantiate. 56 | public bool InstantiateAtPosition(Vector3 position) 57 | { 58 | // Get the height at the position. 59 | float height = noise.CalculateNoise(position + offset); 60 | // Check if in range. 61 | if(height > minHeight && height < maxHeight) 62 | return true; 63 | return false; 64 | } 65 | /// 66 | /// Get a random model from the list. 67 | /// 68 | /// Return a model. 69 | public GameObject GetRandomModel() 70 | { 71 | // Get random model. 72 | return models[rng.Next(0, models.Length)]; 73 | } 74 | /// 75 | /// Get the height at that position. 76 | /// 77 | /// Position to check. 78 | /// Return the height. 79 | public float GetHeightAtPosition(Vector3 position) 80 | { 81 | // Get noise at position. 82 | return noise.CalculateNoise(position + offset); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Scripts/GenerationData.cs: -------------------------------------------------------------------------------- 1 | /** 2 | GenerationData.cs 3 | Purpose: Scriptable object that stores the 4 | data and some functions for the terrain generation. 5 | Require: No other files required. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/2018 9 | */ 10 | 11 | using UnityEngine; 12 | 13 | namespace Generation 14 | { 15 | [CreateAssetMenu()] 16 | public class GenerationData : ScriptableObject 17 | { 18 | [Range(1, 10)] 19 | [Tooltip("Amounts of calls.")] 20 | public int octaves = 8; 21 | [Range(0.1f, 1.0f)] 22 | [Tooltip("Amplitud variation through octaves.")] 23 | public float persistance = 0.5f; 24 | [Range(1.0f, 2f)] 25 | [Tooltip("Frequency variation through octaves.")] 26 | public float lacunarity = 2f; 27 | [Range(0.1f, 500)] 28 | [Tooltip("General frequency division.")] 29 | public float scale = 1; 30 | [Range(0f,1f)] 31 | [Tooltip("Minimum perlin value that return a value.")] 32 | public float minimum_height = 0.5f; 33 | [Range(1f,500f)] 34 | [Tooltip("Height that will be multiply to the 0 to 1 value.")] 35 | public int height_multiplier = 1; 36 | [Tooltip("True to invert the values sign.")] 37 | public bool invert = false; 38 | 39 | /// 40 | /// Genrate 3D perlin noise value. 41 | /// 42 | /// x axis. 43 | /// y axis. 44 | /// z axis. 45 | /// Return a float between 0 and 1. 46 | static private float PerlinNoise3D(float x, float y, float z) 47 | { 48 | 49 | float ab = Mathf.PerlinNoise(x, y); 50 | float bc = Mathf.PerlinNoise(y, z); 51 | float ac = Mathf.PerlinNoise(x, z); 52 | 53 | float ba = Mathf.PerlinNoise(y, x); 54 | float cb = Mathf.PerlinNoise(z, y); 55 | float ca = Mathf.PerlinNoise(z, x); 56 | 57 | float abc = ab + bc + ac + ba + cb + ca; 58 | return abc / 6f; 59 | } 60 | 61 | /// 62 | /// Calculate the noise at a specific position. 63 | /// 64 | /// Position. 65 | /// Returns the height at that position. 66 | public float CalculateNoise(Vector3 position) 67 | { 68 | float x = position.x; 69 | float y = position.y; 70 | float z = position.z; 71 | 72 | float output = 0; 73 | float frequency = 1; 74 | float amplitude = 1; 75 | 76 | for (int i = 0; i < octaves; i++) 77 | { 78 | output += PerlinNoise3D(x * frequency / scale, y * frequency / scale, z * frequency / scale) * amplitude; 79 | amplitude *= persistance; 80 | frequency *= lacunarity; 81 | } 82 | // Make output to stay between 0 and 1. 83 | output /= octaves; 84 | 85 | // if output is less than minimum_height then set to 0. 86 | output = output > minimum_height ? Mathf.InverseLerp(0, 1f - minimum_height, output - minimum_height) : 0; 87 | output *= height_multiplier; 88 | if (invert) 89 | output *= -1; 90 | return output; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Scripts/Planet.cs: -------------------------------------------------------------------------------- 1 | /** 2 | Planet.cs 3 | Purpose: Generate Planets into the scene. 4 | Require: Polygon.cs, GenerationData.cs, 5 | ColorHeight.cs, PopulationData.cs. 6 | 7 | @author Mikel Jauregui 8 | @version 1.1.0 14/07/18 9 | */ 10 | 11 | using System.Collections.Generic; 12 | using UnityEngine; 13 | using System.Threading; 14 | 15 | namespace Generation 16 | { 17 | public class Planet : MonoBehaviour 18 | { 19 | // List where we store all the planets. 20 | static private List planetList = new List(); 21 | // Queue where we add the polygons that need to be instantiate. 22 | static private Queue polygonsToInstantiate = new Queue(); 23 | // List of polygons instantiated. 24 | static List distanceList = new List(); 25 | // True if the thread that generate 26 | // the data for the planet has started. 27 | static private bool isThreadBeenStarted = false; 28 | // True if the thread that generate the 29 | // data for the planet has ended. 30 | static private bool isThreadDone = false; 31 | // True if the game want to quit. 32 | static private bool gameQuiting = false; 33 | // The terrain has been instantiate. 34 | static private bool terrainInstantiated = false; 35 | 36 | // Stores a reference to its own 37 | // to pass it to the polygons. 38 | private Planet planet; 39 | // Terrain style for the planet. 40 | private Style terrainStyle; 41 | // Array of noises that will 42 | // then be used to generate the terrain. 43 | private GenerationData[] generationData; 44 | // Array of colors that will then be used 45 | // to color the terrain. 46 | private ColorHeight[] colorHeight; 47 | // Array of offsets that will be apply 48 | // to the terrain generation noise. 49 | private Vector3[] offset; 50 | // Array that stores the data to 51 | // generate the population for the planet. 52 | private PopulateData[] population; 53 | // Material for the terrain. 54 | private Material material; 55 | // Material for the sea. 56 | private Material seaMaterial; 57 | // List of polygons that compose the planet. 58 | private List polygons; 59 | // List of vertices of the icosphere. 60 | private List vertices; 61 | // Center of the planet. 62 | private Vector3 position; 63 | // Planet radius. 64 | private float radius; 65 | // Sea Level. 66 | private float seaLevel; 67 | // Planet seed. 68 | private int seed; 69 | // Icosphere subdivisions. 70 | private int subdivisions; 71 | // Chunck subdivisions. 72 | private int chunckSubdivisions; 73 | 74 | /// 75 | /// Thread that generate all the data. 76 | /// 77 | static private void DataThreadLoop() 78 | { 79 | //Prevent list modification during 80 | // thread loop. 81 | lock (planetList) 82 | { 83 | foreach (var planet in planetList) 84 | { 85 | if (gameQuiting) 86 | return; 87 | // Create icosahedron. 88 | planet.InitAsIcosahedron(); 89 | // Subdivide it. 90 | planet.Subdivide(); 91 | // Create noise offset. 92 | planet.CalculateOffset(); 93 | 94 | // Generate mesh data. 95 | foreach (var poly in planet.polygons) 96 | { 97 | if (gameQuiting) 98 | return; 99 | 100 | poly.GenerateMesh(); 101 | } 102 | } 103 | } 104 | isThreadDone = true; 105 | } 106 | /// 107 | /// Check is a polygon is in range of the viewer. 108 | /// 109 | /// 110 | /// 111 | /// 112 | static private bool PolyInRange(Polygon poly, Vector3 position) 113 | { 114 | // Normalize to check on the circle unit. 115 | position = position.normalized; 116 | 117 | // Get the planet data. 118 | Planet p = poly.GetPlanet(); 119 | int[] i = poly.GetVertices().ToArray(); 120 | Vector3[] v = new Vector3[3] { p.vertices[i[0]], p.vertices[i[1]], p.vertices[i[2]] }; 121 | float d0, d1, d2; 122 | d0 = Vector3.Distance(position, v[0].normalized); 123 | d1 = Vector3.Distance(position, v[1].normalized); 124 | d2 = Vector3.Distance(position, v[2].normalized); 125 | // True if in range. 126 | return d0 < Main.G_viewDistance || d1 < Main.G_viewDistance || d2 < Main.G_viewDistance; 127 | } 128 | /// 129 | /// Add a polygon to the Instantiate queue. 130 | /// 131 | /// The polygon that need to be added. 132 | static public void AddPolygonToQueue(Polygon poly) 133 | { 134 | lock (polygonsToInstantiate) 135 | { 136 | // Add to end of the queue. 137 | polygonsToInstantiate.Enqueue(poly); 138 | } 139 | } 140 | /// 141 | /// Check if the main thread want to quit. 142 | /// 143 | /// True if the game is quitting. 144 | static public bool ThreadNeedToQuit() 145 | { 146 | return gameQuiting; 147 | } 148 | /// 149 | /// Add a planet to the queue of the ones that need to be generated. 150 | /// 151 | /// Name of the Empty object that will hold the terrain objects 152 | /// Center of the planet. 153 | /// Seed for the planet. 154 | /// True if the seed need to be change by a random new one. 155 | /// Style of the terrain. 156 | /// Level of the sea. 157 | /// Noise to generate the terrain. 158 | /// Color to add to the layers. 159 | /// Data to populate the planet. 160 | /// Material for the terrain. 161 | /// Material for the sea. 162 | /// Radius of the planet. 163 | /// Icosphere subdivisions. 164 | /// Chunck subdivisions. 165 | static public void AddPlanetToQueue(string name, Vector3 position, int seed, bool randomSeed, Style terrainStyle, float seaLevel, GenerationData[] generationData, ColorHeight[] colorHeight, PopulateData[] population, Material material, Material seaMaterial, float radius, int subdivisions, int chunckSubdivisions) 166 | { 167 | // Instantiate a gameobject that hold planet. 168 | GameObject obj = new GameObject(); 169 | obj.name = name; 170 | obj.transform.position = position; 171 | Planet planet = obj.AddComponent(); 172 | planet.planet = planet; 173 | int new_seed = randomSeed == true ? UnityEngine.Random.Range(0, int.MaxValue) : seed; 174 | planet.InstantiatePlanetVariables(new_seed, terrainStyle, seaLevel, generationData, colorHeight, population, material, seaMaterial, radius, subdivisions, chunckSubdivisions); 175 | planet.position = position; 176 | 177 | // Add the planet to the list of planets. 178 | planetList.Add(planet); 179 | } 180 | /// 181 | /// Start the Data computations. 182 | /// 183 | static public void StartDataQueue() 184 | { 185 | // Prevent to overload of threads. Only 186 | // one will be running at a time. 187 | if (isThreadBeenStarted) 188 | return; 189 | 190 | // Start the thread. 191 | Thread thread = new Thread(DataThreadLoop); 192 | thread.Start(); 193 | isThreadBeenStarted = true; 194 | } 195 | /// 196 | /// Generate the terrain while added to the queue. 197 | /// 198 | static public void InstantiateIntoWorld() 199 | { 200 | terrainInstantiated = true; 201 | // Instantiate the polygons into the scene while been added to the queue. 202 | while (polygonsToInstantiate.Count != 0) 203 | { 204 | Polygon poly = polygonsToInstantiate.Dequeue(); 205 | poly.Instantiate(); 206 | // Add it to the list for later modification. 207 | distanceList.Add(poly); 208 | } 209 | } 210 | /// 211 | /// Hide or show the polygons objects 212 | /// if they are in range of the viewer. 213 | /// 214 | /// Position tto check if the polygon is in range. 215 | static public void HideAndShow(Vector3 viewer) 216 | { 217 | // Wait to the secondary thread to end for avoid errors. 218 | if (!isThreadDone) 219 | return; 220 | 221 | // if distanceList is empty fill it. 222 | if(!terrainInstantiated) 223 | while (polygonsToInstantiate.Count != 0) 224 | distanceList.Add(polygonsToInstantiate.Dequeue()); 225 | 226 | foreach (var item in distanceList) 227 | { 228 | // if polygon is in range to the viewer instantiate. 229 | if(PolyInRange(item, viewer)) 230 | item.Show(); 231 | // else hide it. 232 | else 233 | item.Hide(); 234 | } 235 | } 236 | /// 237 | /// Set the vairables to the values. 238 | /// 239 | /// Seed for the planet. 240 | /// True if the seed need to be change by a random new one. 241 | /// Style of the terrain. 242 | /// Level of the sea. 243 | /// Noise to generate the terrain. 244 | /// Color to add to the layers. 245 | /// Data to populate the planet. 246 | /// Material for the terrain. 247 | /// Material for the sea. 248 | /// Radius of the planet. 249 | /// Icosphere subdivisions. 250 | /// Chunck subdivisions. 251 | private void InstantiatePlanetVariables(int seed, Style terrainStyle, float seaLevel, GenerationData[] generationData, ColorHeight[] colorHeight, PopulateData[] population, Material material, Material seaMaterial, float radius, int subdivisions, int chunckSubdivisions) 252 | { 253 | this.seed = seed; 254 | this.terrainStyle = terrainStyle; 255 | this.radius = radius; 256 | this.generationData = generationData; 257 | this.colorHeight = colorHeight; 258 | this.population = population; 259 | PopulateData.SetSeed(seed, population); 260 | this.subdivisions = subdivisions; 261 | this.seaLevel = seaLevel; 262 | this.material = material; 263 | this.seaMaterial = seaMaterial; 264 | this.chunckSubdivisions = chunckSubdivisions; 265 | } 266 | /// 267 | /// Generate the basic Icosphere structure. 268 | /// 269 | private void InitAsIcosahedron() 270 | { 271 | polygons = new List(); 272 | vertices = new List(); 273 | 274 | // An icosahedron has 12 vertices, and 275 | // since it's completely symmetrical the 276 | // formula for calculating them is kind of 277 | // symmetrical too: 278 | 279 | float t = (1.0f + Mathf.Sqrt(5.0f)) / 2.0f; 280 | 281 | vertices.Add(position + new Vector3(-1, t, 0).normalized * this.radius); 282 | vertices.Add(position + new Vector3(1, t, 0).normalized * this.radius); 283 | vertices.Add(position + new Vector3(-1, -t, 0).normalized * this.radius); 284 | vertices.Add(position + new Vector3(1, -t, 0).normalized * this.radius); 285 | vertices.Add(position + new Vector3(0, -1, t).normalized * this.radius); 286 | vertices.Add(position + new Vector3(0, 1, t).normalized * this.radius); 287 | vertices.Add(position + new Vector3(0, -1, -t).normalized * this.radius); 288 | vertices.Add(position + new Vector3(0, 1, -t).normalized * this.radius); 289 | vertices.Add(position + new Vector3(t, 0, -1).normalized * this.radius); 290 | vertices.Add(position + new Vector3(t, 0, 1).normalized * this.radius); 291 | vertices.Add(position + new Vector3(-t, 0, -1).normalized * this.radius); 292 | vertices.Add(position + new Vector3(-t, 0, 1).normalized * this.radius); 293 | 294 | // And here's the formula for the 20 sides, 295 | // referencing the 12 vertices we just created. 296 | polygons.Add(new Polygon(0, 11, 5, ref planet)); 297 | polygons.Add(new Polygon(0, 5, 1, ref planet)); 298 | polygons.Add(new Polygon(0, 1, 7, ref planet)); 299 | polygons.Add(new Polygon(0, 7, 10, ref planet)); 300 | polygons.Add(new Polygon(0, 10, 11, ref planet)); 301 | polygons.Add(new Polygon(1, 5, 9, ref planet)); 302 | polygons.Add(new Polygon(5, 11, 4, ref planet)); 303 | polygons.Add(new Polygon(11, 10, 2, ref planet)); 304 | polygons.Add(new Polygon(10, 7, 6, ref planet)); 305 | polygons.Add(new Polygon(7, 1, 8, ref planet)); 306 | polygons.Add(new Polygon(3, 9, 4, ref planet)); 307 | polygons.Add(new Polygon(3, 4, 2, ref planet)); 308 | polygons.Add(new Polygon(3, 2, 6, ref planet)); 309 | polygons.Add(new Polygon(3, 6, 8, ref planet)); 310 | polygons.Add(new Polygon(3, 8, 9, ref planet)); 311 | polygons.Add(new Polygon(4, 9, 5, ref planet)); 312 | polygons.Add(new Polygon(2, 4, 11, ref planet)); 313 | polygons.Add(new Polygon(6, 2, 10, ref planet)); 314 | polygons.Add(new Polygon(8, 6, 7, ref planet)); 315 | polygons.Add(new Polygon(9, 8, 1, ref planet)); 316 | } 317 | /// 318 | /// Subdivide the Icosphere by 'subdivisions' times. 319 | /// 320 | private void Subdivide() 321 | { 322 | var mid_point_cache = new Dictionary(); 323 | 324 | for (int i = 0; i < subdivisions; i++) 325 | { 326 | var new_polys = new List(); 327 | foreach (var poly in polygons) 328 | { 329 | List t_vertices = poly.GetVertices(); 330 | int a = t_vertices[0]; 331 | int b = t_vertices[1]; 332 | int c = t_vertices[2]; 333 | // Use GetMidPointIndex to either create a 334 | // new vertex between two old vertices, or 335 | // find the one that was already created. 336 | int ab = GetMidPointIndex(mid_point_cache, a, b); 337 | int bc = GetMidPointIndex(mid_point_cache, b, c); 338 | int ca = GetMidPointIndex(mid_point_cache, c, a); 339 | // Create the four new polygons using our original 340 | // three vertices, and the three new midpoints. 341 | new_polys.Add(new Polygon(a, ab, ca, ref planet)); 342 | new_polys.Add(new Polygon(b, bc, ab, ref planet)); 343 | new_polys.Add(new Polygon(c, ca, bc, ref planet)); 344 | new_polys.Add(new Polygon(ab, bc, ca, ref planet)); 345 | } 346 | // Replace all our old polygons with the new set of 347 | // subdivided ones. 348 | polygons = new_polys; 349 | } 350 | } 351 | /// 352 | /// Get the Middle point. 353 | /// 354 | private int GetMidPointIndex(Dictionary cache, int indexA, int indexB) 355 | { 356 | // We create a key out of the two original indices 357 | // by storing the smaller index in the upper two bytes 358 | // of an integer, and the larger index in the lower two 359 | // bytes. By sorting them according to whichever is smaller 360 | // we ensure that this function returns the same result 361 | // whether you call 362 | // GetMidPointIndex(cache, 5, 9) 363 | // or... 364 | // GetMidPointIndex(cache, 9, 5) 365 | int smaller_index = Mathf.Min(indexA, indexB); 366 | int greater_index = Mathf.Max(indexA, indexB); 367 | int key = (smaller_index << 16) + greater_index; 368 | // If a midpoint is already defined, just return it. 369 | int ret; 370 | if (cache.TryGetValue(key, out ret)) 371 | return ret; 372 | // If we're here, it's because a midpoint for these two 373 | // vertices hasn't been created yet. Let's do that now! 374 | Vector3 p1 = vertices[indexA]; 375 | Vector3 p2 = vertices[indexB]; 376 | Vector3 middle = (Vector3.Lerp(p1, p2, 0.5f) - position).normalized * radius + position; 377 | 378 | ret = vertices.Count; 379 | vertices.Add(middle); 380 | 381 | cache.Add(key, ret); 382 | return ret; 383 | } 384 | /// 385 | /// Calculate the offset for the noise using the seed. 386 | /// 387 | private void CalculateOffset() 388 | { 389 | // Generate a random number generator to 390 | // always have the same random for the same seed. 391 | System.Random rng = new System.Random(seed); 392 | 393 | offset = new Vector3[generationData.Length]; 394 | 395 | // Calculate the offset of the generation noise. 396 | for (int i = 0; i < offset.Length; i++) 397 | { 398 | offset[i].x = rng.Next(-10000, 10000); 399 | offset[i].y = rng.Next(-10000, 10000); 400 | offset[i].z = rng.Next(-10000, 10000); 401 | } 402 | } 403 | /// 404 | /// If the game try to quit. 405 | /// 406 | private void OnApplicationQuit() 407 | { 408 | // If the background thread is still running. 409 | // quit will make it stop. 410 | gameQuiting = true; 411 | } 412 | 413 | /// 414 | /// Get the style. 415 | /// 416 | /// Return the style. 417 | public Style GetStyle() 418 | { 419 | return terrainStyle; 420 | } 421 | /// 422 | /// Get the polygons list. 423 | /// 424 | /// Return the polygon list. 425 | public List GetPolygons() 426 | { 427 | return polygons; 428 | } 429 | /// 430 | /// Get the Color height array. 431 | /// 432 | /// Return the colorHeight array. 433 | public ColorHeight[] GetColorHeight() 434 | { 435 | return colorHeight; 436 | } 437 | /// 438 | /// Get the vertex list. 439 | /// 440 | /// Return the vertex list. 441 | public List GetVertices() 442 | { 443 | return vertices; 444 | } 445 | /// 446 | /// Get the sea level. 447 | /// 448 | /// Return the sea level. 449 | public float GetSeaLevel() 450 | { 451 | return seaLevel; 452 | } 453 | /// 454 | /// Get the populationData array. 455 | /// 456 | /// Return the populationData array. 457 | public PopulateData[] GetPopulation() 458 | { 459 | return population; 460 | } 461 | /// 462 | /// Get the planet center. 463 | /// 464 | /// Return the planet center. 465 | public Vector3 GetPosition() 466 | { 467 | return position; 468 | } 469 | /// 470 | /// Get material. 471 | /// 472 | /// Return the terrain material. 473 | public Material GetMaterial() 474 | { 475 | return material; 476 | } 477 | /// 478 | /// Get the sea material. 479 | /// 480 | /// Return the material for the sea. 481 | public Material GetSeaMaterial() 482 | { 483 | return seaMaterial; 484 | } 485 | /// 486 | /// Get seed. 487 | /// 488 | /// Return the seed. 489 | public int GetSeed() 490 | { 491 | return seed; 492 | } 493 | /// 494 | /// Get the chunck subdivisions. 495 | /// 496 | /// Return the chunck subdivision number. 497 | public int GetChunkSubdivisions() 498 | { 499 | return chunckSubdivisions; 500 | } 501 | /// 502 | /// Calculate the height at a specific position. 503 | /// 504 | /// Position where we want tto get the height. 505 | /// Return the height. 506 | public float CalculateHeightAtPosition(Vector3 position) 507 | { 508 | float height = 0; 509 | 510 | for (int i = 0; i < generationData.Length; i++) 511 | height += generationData[i].CalculateNoise(position + offset[i]); 512 | 513 | return height; 514 | } 515 | } 516 | } 517 | -------------------------------------------------------------------------------- /Scripts/Polygon.cs: -------------------------------------------------------------------------------- 1 | /** 2 | Polygon.cs 3 | Purpose: Generate Polygons into the scene. 4 | Require: Planet.cs. 5 | 6 | @author Mikel Jauregui 7 | @version 1.1.0 14/07/2018 8 | */ 9 | 10 | using System.Collections.Generic; 11 | using UnityEngine; 12 | 13 | namespace Generation 14 | { 15 | public class Polygon 16 | { 17 | // Random number generator. 18 | static private System.Random rng = new System.Random(0); 19 | 20 | // Planet data. 21 | private Planet planet; 22 | // Object that hold the terrain. 23 | private GameObject face; 24 | // Object that hold the sea. 25 | private GameObject seaFace; 26 | // Data for generate the mesh. 27 | private MeshData meshData; 28 | // Data for generate the sea mesh. 29 | private MeshData seaMeshData; 30 | // Index of the vertices of the chunk. 31 | private List vertices; 32 | // Positions of the populations that need to be instantiated. 33 | private List[] pop; 34 | // Terrain has been instantiated. 35 | private bool instantiate = false; 36 | // Face is active. 37 | private bool showing = false; 38 | 39 | /// 40 | /// Get the middle points and add them to the list. 41 | /// 42 | /// List where we add the points. 43 | /// Point a. 44 | /// Point b. 45 | /// Amount of subdivisions. 46 | static private void ListMiddlePoints(List list, Vector3 a, Vector3 b, int sub) 47 | { 48 | Vector3 new_vector = new Vector3(); 49 | 50 | new_vector.x = (b.x - a.x) / sub; 51 | new_vector.y = (b.y - a.y) / sub; 52 | new_vector.z = (b.z - a.z) / sub; 53 | 54 | for (int i = 1; i < sub; i++) 55 | list.Add(a + new_vector * i); 56 | } 57 | /// 58 | /// Organize the three vectors by distance to 59 | /// 60 | private void Organize(ref Vector3 a, ref Vector3 b, ref Vector3 c) 61 | { 62 | Vector3 v1, v2, v3; 63 | float h1, h2, h3; 64 | 65 | // Get distance from center of the planet. 66 | h1 = Vector3.Magnitude(a); 67 | h2 = Vector3.Magnitude(b); 68 | h3 = Vector3.Magnitude(c); 69 | 70 | // Sort. 71 | if (h1 > h2) 72 | { 73 | if (h1 > h3) 74 | { 75 | v1 = a; 76 | if (h2 > h3) 77 | { 78 | v2 = b; 79 | v3 = c; 80 | } 81 | else 82 | { 83 | v2 = c; 84 | v3 = b; 85 | } 86 | } 87 | else 88 | { 89 | v1 = c; 90 | v2 = a; 91 | v3 = b; 92 | } 93 | } 94 | else 95 | { 96 | if (h2 > h3) 97 | { 98 | v1 = b; 99 | if (h1 > h3) 100 | { 101 | v2 = a; 102 | v3 = c; 103 | } 104 | else 105 | { 106 | v2 = c; 107 | v3 = a; 108 | } 109 | } 110 | else 111 | { 112 | v1 = c; 113 | v2 = b; 114 | v3 = a; 115 | } 116 | } 117 | // Set the result. 118 | a = v1; 119 | b = v2; 120 | c = v3; 121 | } 122 | /// 123 | /// From a triangle generate a stair. 124 | /// 125 | /// Triangle to use. 126 | /// Return the mesh of the stair. 127 | private MeshData TriangleToStair(Vector3[] triangle) 128 | { 129 | Vector3 middle = planet.GetPosition(); 130 | MeshData mesh_data = new MeshData(); 131 | Vector3 v1, v2, v3; 132 | 133 | v1 = triangle[0]; 134 | v2 = triangle[1]; 135 | v3 = triangle[2]; 136 | Organize(ref v1, ref v2, ref v3); 137 | 138 | float h1, h2, h3; 139 | h1 = Vector3.Magnitude(v1); 140 | h2 = Vector3.Magnitude(v2); 141 | h3 = Vector3.Magnitude(v3); 142 | 143 | int h_min, h_max; 144 | h_min = Mathf.FloorToInt(Mathf.Min(h1, h2, h3)); 145 | h_max = Mathf.FloorToInt(Mathf.Max(h1, h2, h3)); 146 | int iv = 0; 147 | for (int h = h_min; h <= h_max; h++) 148 | { 149 | int points_above = 0; 150 | if (h3 == h2 && h3 == h1) 151 | points_above = 3; 152 | else if (h3 > h) 153 | points_above = 3; 154 | else if (h2 > h) 155 | points_above = 2; 156 | else 157 | points_above = 1; 158 | 159 | // Current Plane. 160 | Vector3 v1_c, v2_c, v3_c; 161 | v1_c = v1.normalized * h; 162 | v2_c = v2.normalized * h; 163 | v3_c = v3.normalized * h; 164 | 165 | // Previous Plane. 166 | Vector3 v1_p, v2_p, v3_p; 167 | v1_p = v1.normalized * (h - 1); 168 | v2_p = v2.normalized * (h - 1); 169 | v3_p = v3.normalized * (h - 1); 170 | 171 | Vector3 normal = Vector3.Cross(v1_p - v2_p, v3_p - v2_p).normalized; 172 | float d = -Vector3.Dot(normal, v1_p); 173 | float sign1 = d; 174 | float distance = Mathf.Abs(normal.x * v1_c.x + normal.y * v1_c.y + normal.z * v1_c.z + d); 175 | 176 | Color color = Color.white; 177 | ColorHeight[] colorHeight = planet.GetColorHeight(); 178 | foreach (var item in colorHeight) 179 | { 180 | if (h > item.layer) 181 | { 182 | color = item.color; 183 | break; 184 | } 185 | } 186 | 187 | if (points_above == 3) 188 | { 189 | // Floor. 190 | mesh_data.vertices.Add(v1_c + middle); 191 | mesh_data.vertices.Add(v2_c + middle); 192 | mesh_data.vertices.Add(v3_c + middle); 193 | 194 | mesh_data.colors.Add(color); 195 | mesh_data.colors.Add(color); 196 | mesh_data.colors.Add(color); 197 | 198 | if (sign1 < 0) 199 | { 200 | // Floor. 201 | mesh_data.triangles.Add(iv); 202 | mesh_data.triangles.Add(iv + 2); 203 | mesh_data.triangles.Add(iv + 1); 204 | } 205 | else 206 | { 207 | mesh_data.triangles.Add(iv); 208 | mesh_data.triangles.Add(iv + 1); 209 | mesh_data.triangles.Add(iv + 2); 210 | } 211 | iv += 3; 212 | } 213 | else if (points_above == 2) 214 | { 215 | float t1 = (h1 - h) / (h1 - h3); 216 | Vector3 v1_v3_c = Vector3.Lerp(v1, v3, t1); 217 | Vector3 v1_v3_p = v1_v3_c + Vector3.Cross(v1_c - v2_c, v3_c - v2_c).normalized * distance * Mathf.Sign(sign1); 218 | 219 | float t2 = (h2 - h) / (h2 - h3); 220 | Vector3 v2_v3_c = Vector3.Lerp(v2, v3, t2); 221 | Vector3 v2_v3_p = v2_v3_c + Vector3.Cross(v1_c - v2_c, v3_c - v2_c).normalized * distance * Mathf.Sign(sign1); 222 | 223 | if (sign1 < 0) 224 | { 225 | // Floor. 226 | mesh_data.vertices.Add(v1_v3_c + middle); 227 | mesh_data.vertices.Add(v2_v3_c + middle); 228 | mesh_data.vertices.Add(v1_c + middle); 229 | mesh_data.vertices.Add(v2_c + middle); 230 | 231 | mesh_data.colors.Add(color); 232 | mesh_data.colors.Add(color); 233 | mesh_data.colors.Add(color); 234 | mesh_data.colors.Add(color); 235 | 236 | mesh_data.triangles.Add(iv); 237 | mesh_data.triangles.Add(iv + 1); 238 | mesh_data.triangles.Add(iv + 2); 239 | 240 | mesh_data.triangles.Add(iv + 1); 241 | mesh_data.triangles.Add(iv + 3); 242 | mesh_data.triangles.Add(iv + 2); 243 | iv += 4; 244 | 245 | // Wall. 246 | mesh_data.vertices.Add(v1_v3_c + middle); 247 | mesh_data.vertices.Add(v1_v3_p + middle); 248 | mesh_data.vertices.Add(v2_v3_c + middle); 249 | mesh_data.vertices.Add(v2_v3_p + middle); 250 | 251 | mesh_data.colors.Add(color); 252 | mesh_data.colors.Add(color); 253 | mesh_data.colors.Add(color); 254 | mesh_data.colors.Add(color); 255 | 256 | mesh_data.triangles.Add(iv); 257 | mesh_data.triangles.Add(iv + 1); 258 | mesh_data.triangles.Add(iv + 2); 259 | 260 | mesh_data.triangles.Add(iv + 1); 261 | mesh_data.triangles.Add(iv + 3); 262 | mesh_data.triangles.Add(iv + 2); 263 | iv += 4; 264 | } 265 | else 266 | { 267 | // Floor. 268 | mesh_data.vertices.Add(v1_v3_c + middle); 269 | mesh_data.vertices.Add(v2_v3_c + middle); 270 | mesh_data.vertices.Add(v1_c + middle); 271 | mesh_data.vertices.Add(v2_c + middle); 272 | 273 | mesh_data.colors.Add(color); 274 | mesh_data.colors.Add(color); 275 | mesh_data.colors.Add(color); 276 | mesh_data.colors.Add(color); 277 | 278 | mesh_data.triangles.Add(iv); 279 | mesh_data.triangles.Add(iv + 2); 280 | mesh_data.triangles.Add(iv + 1); 281 | 282 | mesh_data.triangles.Add(iv + 1); 283 | mesh_data.triangles.Add(iv + 2); 284 | mesh_data.triangles.Add(iv + 3); 285 | iv += 4; 286 | 287 | // Wall. 288 | mesh_data.vertices.Add(v1_v3_c + middle); 289 | mesh_data.vertices.Add(v1_v3_p + middle); 290 | mesh_data.vertices.Add(v2_v3_c + middle); 291 | mesh_data.vertices.Add(v2_v3_p + middle); 292 | 293 | mesh_data.colors.Add(color); 294 | mesh_data.colors.Add(color); 295 | mesh_data.colors.Add(color); 296 | mesh_data.colors.Add(color); 297 | 298 | mesh_data.triangles.Add(iv); 299 | mesh_data.triangles.Add(iv + 2); 300 | mesh_data.triangles.Add(iv + 1); 301 | 302 | mesh_data.triangles.Add(iv + 1); 303 | mesh_data.triangles.Add(iv + 2); 304 | mesh_data.triangles.Add(iv + 3); 305 | iv += 4; 306 | } 307 | } 308 | else if (points_above == 1) 309 | { 310 | float t1 = (h1 - h) / (h1 - h3); 311 | Vector3 v1_v3_c = Vector3.Lerp(v1, v3, t1); 312 | Vector3 v1_v3_p = v1_v3_c + Vector3.Cross(v1_c - v2_c, v3_c - v2_c).normalized * distance * Mathf.Sign(sign1); 313 | 314 | float t2 = (h1 - h) / (h1 - h2); 315 | Vector3 v2_v3_c = Vector3.Lerp(v1, v2, t2); 316 | Vector3 v2_v3_p = v2_v3_c + Vector3.Cross(v1_c - v2_c, v3_c - v2_c).normalized * distance * Mathf.Sign(sign1); 317 | 318 | if (sign1 < 0) 319 | { 320 | // Floor. 321 | mesh_data.vertices.Add(v1_v3_c + middle); 322 | mesh_data.vertices.Add(v2_v3_c + middle); 323 | mesh_data.vertices.Add(v1_c + middle); 324 | 325 | mesh_data.colors.Add(color); 326 | mesh_data.colors.Add(color); 327 | mesh_data.colors.Add(color); 328 | 329 | mesh_data.triangles.Add(iv); 330 | mesh_data.triangles.Add(iv + 1); 331 | mesh_data.triangles.Add(iv + 2); 332 | 333 | iv += 3; 334 | 335 | // Wall. 336 | mesh_data.vertices.Add(v1_v3_c + middle); 337 | mesh_data.vertices.Add(v1_v3_p + middle); 338 | mesh_data.vertices.Add(v2_v3_c + middle); 339 | mesh_data.vertices.Add(v2_v3_p + middle); 340 | 341 | mesh_data.colors.Add(color); 342 | mesh_data.colors.Add(color); 343 | mesh_data.colors.Add(color); 344 | mesh_data.colors.Add(color); 345 | 346 | mesh_data.triangles.Add(iv); 347 | mesh_data.triangles.Add(iv + 1); 348 | mesh_data.triangles.Add(iv + 2); 349 | 350 | mesh_data.triangles.Add(iv + 1); 351 | mesh_data.triangles.Add(iv + 3); 352 | mesh_data.triangles.Add(iv + 2); 353 | iv += 4; 354 | } 355 | else 356 | { 357 | // Floor. 358 | mesh_data.vertices.Add(v1_v3_c + middle); 359 | mesh_data.vertices.Add(v2_v3_c + middle); 360 | mesh_data.vertices.Add(v1_c + middle); 361 | 362 | mesh_data.colors.Add(color); 363 | mesh_data.colors.Add(color); 364 | mesh_data.colors.Add(color); 365 | 366 | mesh_data.triangles.Add(iv); 367 | mesh_data.triangles.Add(iv + 2); 368 | mesh_data.triangles.Add(iv + 1); 369 | 370 | iv += 3; 371 | 372 | // Wall. 373 | mesh_data.vertices.Add(v1_v3_c + middle); 374 | mesh_data.vertices.Add(v1_v3_p + middle); 375 | mesh_data.vertices.Add(v2_v3_c + middle); 376 | mesh_data.vertices.Add(v2_v3_p + middle); 377 | 378 | mesh_data.colors.Add(color); 379 | mesh_data.colors.Add(color); 380 | mesh_data.colors.Add(color); 381 | mesh_data.colors.Add(color); 382 | 383 | mesh_data.triangles.Add(iv); 384 | mesh_data.triangles.Add(iv + 2); 385 | mesh_data.triangles.Add(iv + 1); 386 | 387 | mesh_data.triangles.Add(iv + 1); 388 | mesh_data.triangles.Add(iv + 2); 389 | mesh_data.triangles.Add(iv + 3); 390 | iv += 4; 391 | } 392 | } 393 | } 394 | MeshData data = new MeshData(); 395 | data.vertices = new List(triangle); 396 | int[] i = new int[3] { 0, 1, 2 }; 397 | data.triangles = new List(i); 398 | 399 | return mesh_data; 400 | } 401 | /// 402 | /// Subdivide a triangle. 403 | /// 404 | /// Index of the vertices of the triangle. 405 | /// Return aa list with the points of the triangle divided. 406 | private List> Subdivide(List m_Vertices) 407 | { 408 | List> vertices = new List>(); 409 | List p_Vertices = planet.GetVertices(); 410 | List left = new List(); 411 | List right = new List(); 412 | vertices = new List>(); 413 | 414 | Vector3 a = p_Vertices[m_Vertices[0]] - planet.GetPosition(); 415 | Vector3 b = p_Vertices[m_Vertices[1]] - planet.GetPosition(); 416 | Vector3 c = p_Vertices[m_Vertices[2]] - planet.GetPosition(); 417 | 418 | // Amount of sections we need to create. 419 | int size = (int)Mathf.Pow(2, planet.GetChunkSubdivisions()); 420 | 421 | // Create the sections of the left side of the triangle. 422 | left.Add(a); 423 | ListMiddlePoints(left, a, c, size); 424 | left.Add(c); 425 | 426 | // Create the sections of the right side of the triangle. 427 | right.Add(b); 428 | ListMiddlePoints(right, b, c, size); 429 | right.Add(c); 430 | 431 | // Calculate each slice points. 432 | for (int i = 0; i < size; i++) 433 | { 434 | vertices.Add(new List()); 435 | vertices[i].Add(left[i]); 436 | ListMiddlePoints(vertices[i], left[i], right[i], size - i); 437 | vertices[i].Add(right[i]); 438 | } 439 | 440 | // Add the last slice. 441 | vertices.Add(new List()); 442 | vertices[vertices.Count - 1].Add(c); 443 | 444 | return vertices; 445 | } 446 | /// 447 | /// If a value is in range of two others. 448 | /// 449 | /// Minimum. 450 | /// Maximum. 451 | /// Value to check. 452 | /// True if the value is in range. 453 | private bool InRange(float min, float max, float value) 454 | { 455 | return min < value && max > value; 456 | } 457 | /// 458 | /// Calculate the height at a point. 459 | /// 460 | /// Position. 461 | /// Return the height. 462 | private float getHeight(Vector3 p) 463 | { 464 | return planet.CalculateHeightAtPosition(p); 465 | } 466 | 467 | /// 468 | /// Constructor 469 | /// 470 | /// Index of a vertex. 471 | /// Index of a vertex. 472 | /// Index of a vertex. 473 | /// Parent planet. 474 | public Polygon(int a, int b, int c, ref Planet planet) 475 | { 476 | vertices = new List() { a, b, c }; 477 | this.planet = planet; 478 | } 479 | /// 480 | /// Generate the data for the meshes and the population locations. 481 | /// 482 | public void GenerateMesh() 483 | { 484 | List t_vertices = new List(); 485 | List t_triangles = new List(); 486 | List t_colors = new List(); 487 | 488 | // If the chunck don't need to be divided. 489 | if(planet.GetChunkSubdivisions() == 0) 490 | { 491 | // Only asssign the original triangle. 492 | List v = planet.GetVertices(); 493 | t_vertices = new List() { v[vertices[0]], v[vertices[1]], v[vertices[2]] }; 494 | t_triangles = new List() { 0,1,2 }; 495 | meshData = new MeshData(t_vertices, t_triangles, t_colors); 496 | Planet.AddPolygonToQueue(this); 497 | return; 498 | } 499 | 500 | List> sub_vertices = Subdivide(vertices); 501 | List meshes = new List(); 502 | int size = (int)Mathf.Pow(2, planet.GetChunkSubdivisions()); 503 | int iv = 0; 504 | PopulateData[] population = planet.GetPopulation(); 505 | pop = new List[population.Length]; 506 | for (int i = 0; i < pop.Length; i++) 507 | pop[i] = new List(); 508 | 509 | // Create the mesh data. 510 | for (int x = 0; x < size; x++) 511 | { 512 | for (int y = 0; y < size - x; y++) 513 | { 514 | if (Planet.ThreadNeedToQuit()) 515 | return; 516 | 517 | Vector3 v1, v2, v3, v4 = Vector3.zero; 518 | 519 | v1 = sub_vertices[x][y]; 520 | v2 = sub_vertices[x][y + 1]; 521 | v3 = sub_vertices[x + 1][y]; 522 | 523 | // Variables for the height of each vertex of the triangle. 524 | float h1 = 0.0f, h2 = 0.0f, h3 = 0.0f, h4 = 0.0f; 525 | 526 | h1 = getHeight(v1); 527 | h2 = getHeight(v2); 528 | h3 = getHeight(v3); 529 | 530 | v1 = v1 + (v1).normalized * h1; 531 | v2 = v2 + (v2).normalized * h2; 532 | v3 = v3 + (v3).normalized * h3; 533 | 534 | if(planet.GetStyle() == Style.LowPoly) 535 | { 536 | t_vertices.Add(v1 + planet.GetPosition()); 537 | t_vertices.Add(v2 + planet.GetPosition()); 538 | t_vertices.Add(v3 + planet.GetPosition()); 539 | 540 | t_triangles.Add(iv + 0); 541 | t_triangles.Add(iv + 1); 542 | t_triangles.Add(iv + 2); 543 | 544 | if (h1 > 19 && h2 > 19 && h3 > 19) 545 | { 546 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 547 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 548 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 549 | } 550 | else if (h1 > 16 && h2 > 16 && h3 > 16) 551 | { 552 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 553 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 554 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 555 | } 556 | else if (h1 > 14 && h2 > 14 && h3 > 14) 557 | { 558 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 559 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 560 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 561 | } 562 | else 563 | { 564 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 565 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 566 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 567 | } 568 | 569 | iv += 3; 570 | } 571 | else 572 | { 573 | Vector3[] triangle = new Vector3[3] { v1, v2, v3 }; 574 | MeshData mesh_data = TriangleToStair(triangle); 575 | 576 | foreach (var item in mesh_data.vertices) 577 | { 578 | t_vertices.Add(item); 579 | } 580 | foreach (var item in mesh_data.triangles) 581 | { 582 | t_triangles.Add(iv + item); 583 | } 584 | foreach (var item in mesh_data.colors) 585 | { 586 | t_colors.Add(item); 587 | } 588 | 589 | iv += mesh_data.vertices.Count; 590 | } 591 | 592 | if (x != 0) 593 | { 594 | v4 = sub_vertices[x - 1][y + 1]; 595 | 596 | h4 = getHeight(v4); 597 | 598 | v4 = v4 + v4.normalized * h4; 599 | 600 | if(planet.GetStyle() == Style.LowPoly) 601 | { 602 | t_vertices.Add(v1 + planet.GetPosition()); 603 | t_vertices.Add(v2 + planet.GetPosition()); 604 | t_vertices.Add(v4 + planet.GetPosition()); 605 | 606 | t_triangles.Add(iv + 0); 607 | t_triangles.Add(iv + 2); 608 | t_triangles.Add(iv + 1); 609 | 610 | if (h1 > 19 && h2 > 19 && h4 > 19) 611 | { 612 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 613 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 614 | t_colors.Add(new Color(0.6415094f, 0.5063629f, 0.1845852f, 1)); 615 | } 616 | else if (h1 > 16 && h2 > 16 && h4 > 16) 617 | { 618 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 619 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 620 | t_colors.Add(new Color(0.4470589f, 0.6392157f, 0.145098f, 1)); 621 | } 622 | else if (h1 > 14 && h2 > 14 && h4 > 14) 623 | { 624 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 625 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 626 | t_colors.Add(new Color(0.6196079f, 0.6431373f, 0.1568628f, 1)); 627 | } 628 | else 629 | { 630 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 631 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 632 | t_colors.Add(new Color(0.9450981f, 0.8392158f, 0.4980392f, 1)); 633 | } 634 | 635 | iv += 3; 636 | } 637 | else 638 | { 639 | Vector3[] triangle2 = new Vector3[3] { v1, v2, v4 }; 640 | 641 | MeshData mesh_data2 = TriangleToStair(triangle2); 642 | 643 | foreach (var item in mesh_data2.vertices) 644 | { 645 | t_vertices.Add(item); 646 | } 647 | foreach (var item in mesh_data2.triangles) 648 | { 649 | t_triangles.Add(iv + item); 650 | } 651 | foreach (var item in mesh_data2.colors) 652 | { 653 | t_colors.Add(item); 654 | } 655 | iv += mesh_data2.vertices.Count; 656 | } 657 | } 658 | 659 | if (Vector3.Magnitude(v1) < planet.GetSeaLevel() 660 | || Vector3.Magnitude(v2) < planet.GetSeaLevel() 661 | || Vector3.Magnitude(v3) < planet.GetSeaLevel()) 662 | 663 | { 664 | // Only asssign the original triangle. 665 | List v = planet.GetVertices(); 666 | List sea_t_vertices = new List() {(v[vertices[0]] - planet.GetPosition()).normalized * planet.GetSeaLevel() + planet.GetPosition(), 667 | (v[vertices[1]] - planet.GetPosition()).normalized * planet.GetSeaLevel() + planet.GetPosition(), 668 | (v[vertices[2]] - planet.GetPosition()).normalized * planet.GetSeaLevel() + planet.GetPosition()}; 669 | List sea_t_triangles = new List() { 0, 1, 2 }; 670 | List sea_t_colors = new List(); 671 | seaMeshData = new MeshData(sea_t_vertices, sea_t_triangles, sea_t_colors); 672 | } 673 | 674 | Vector3 a = v1; 675 | Vector3 b = v2; 676 | Vector3 c = v3; 677 | Vector3 d = v4; 678 | 679 | for (int i = 0; i < pop.Length; i++) 680 | { 681 | float rand1 = (float)rng.NextDouble(); 682 | float rand2 = (float)rng.NextDouble(); 683 | Vector3 ac = Vector3.Lerp(a, c, rand1); 684 | Vector3 bc = Vector3.Lerp(b, c, rand1); 685 | 686 | Vector3 point = Vector3.Lerp(ac, bc, rand2); 687 | float height = Vector3.Magnitude(point); 688 | if (Style.Terrace == planet.GetStyle()) 689 | { 690 | height = Mathf.Floor(height); 691 | point = point.normalized * height; 692 | } 693 | if (height >= population[i].minHeight && height <= population[i].maxHeight 694 | && population[i].GetHeightAtPosition(point) > 0 695 | && population[i].probability > (float)rng.NextDouble()) 696 | { 697 | pop[i].Add(point + planet.GetPosition()); 698 | } 699 | 700 | if (x != 0) 701 | { 702 | rand1 = (float)rng.NextDouble(); 703 | rand2 = (float)rng.NextDouble(); 704 | Vector3 ab = Vector3.Lerp(a, b, rand1); 705 | Vector3 db = Vector3.Lerp(d, b, rand1); 706 | 707 | point = Vector3.Lerp(ab, db, rand2); 708 | height = Vector3.Distance(planet.GetPosition(), point); 709 | if (Style.Terrace == planet.GetStyle()) 710 | { 711 | height = Mathf.Floor(height); 712 | point = point.normalized * height; 713 | } 714 | if (height >= population[i].minHeight && height <= population[i].maxHeight 715 | && population[i].GetHeightAtPosition(point) > 0 716 | && population[i].probability > (float)rng.NextDouble()) 717 | { 718 | pop[i].Add(point + planet.GetPosition()); 719 | } 720 | } 721 | } 722 | } 723 | } 724 | // Assign the mesh data. 725 | meshData = new MeshData(t_vertices, t_triangles, t_colors); 726 | Planet.AddPolygonToQueue(this); 727 | } 728 | /// 729 | /// Instantiate terrain and populate it. 730 | /// 731 | public void Instantiate() 732 | { 733 | if (instantiate) 734 | return; 735 | // Instantiate the gameobject. 736 | face = new GameObject(); 737 | face.name = "Terrain Chunck"; 738 | face.transform.parent = planet.transform; 739 | MeshFilter mesh_filter = face.AddComponent(); 740 | MeshCollider collider = face.AddComponent(); 741 | MeshRenderer renderer = face.AddComponent(); 742 | renderer.material = planet.GetMaterial(); 743 | 744 | // Apply the mesh to the object. 745 | Mesh mesh = new Mesh(); 746 | mesh.vertices = meshData.vertices.ToArray(); 747 | mesh.triangles = meshData.triangles.ToArray(); 748 | mesh.colors = meshData.colors.ToArray(); 749 | mesh.RecalculateBounds(); 750 | mesh.RecalculateNormals(); 751 | mesh.RecalculateTangents(); 752 | mesh_filter.mesh = mesh; 753 | collider.sharedMesh = mesh; 754 | 755 | if(seaMeshData != null) 756 | { 757 | // Instantiate the gameobject. 758 | seaFace = new GameObject(); 759 | seaFace.name = "Sea"; 760 | seaFace.transform.parent = face.transform; 761 | MeshFilter sea_mesh_filter = seaFace.AddComponent(); 762 | MeshCollider sea_collider = seaFace.AddComponent(); 763 | MeshRenderer sea_renderer = seaFace.AddComponent(); 764 | sea_renderer.material = planet.GetSeaMaterial(); 765 | 766 | // Apply the mesh to the object. 767 | Mesh sea_mesh = new Mesh(); 768 | sea_mesh.vertices = seaMeshData.vertices.ToArray(); 769 | sea_mesh.triangles = seaMeshData.triangles.ToArray(); 770 | sea_mesh.colors = seaMeshData.colors.ToArray(); 771 | sea_mesh.RecalculateBounds(); 772 | sea_mesh.RecalculateNormals(); 773 | sea_mesh.RecalculateTangents(); 774 | sea_mesh_filter.mesh = sea_mesh; 775 | sea_collider.sharedMesh = sea_mesh; 776 | } 777 | 778 | PopulateData[] population = planet.GetPopulation(); 779 | for (int i = 0; i < pop.Length; i++) 780 | { 781 | foreach (var pos in pop[i]) 782 | { 783 | GameObject cube = GameObject.Instantiate(population[i].GetRandomModel()); 784 | cube.transform.parent = face.transform; 785 | Quaternion rotation = Quaternion.FromToRotation(Vector3.up, (pos - planet.GetPosition()).normalized); 786 | cube.transform.SetPositionAndRotation(pos, rotation); 787 | } 788 | } 789 | instantiate = true; 790 | showing = true; 791 | } 792 | /// 793 | /// Show the terrain on the scene. 794 | /// 795 | public void Show() 796 | { 797 | Instantiate(); 798 | face.SetActive(true); 799 | } 800 | /// 801 | /// Hide the terrain on the scene. 802 | /// 803 | public void Hide() 804 | { 805 | if (!instantiate) 806 | return; 807 | 808 | face.SetActive(false); 809 | showing = false; 810 | } 811 | public List GetVertices() 812 | { 813 | return vertices; 814 | } 815 | public Planet GetPlanet() 816 | { 817 | return planet; 818 | } 819 | public bool GetShowing() 820 | { 821 | return showing; 822 | } 823 | } 824 | public class MeshData 825 | { 826 | public List vertices; 827 | public List triangles; 828 | public List colors; 829 | 830 | public MeshData() 831 | { 832 | this.vertices = new List(); 833 | this.triangles = new List(); 834 | this.colors = new List(); 835 | } 836 | public MeshData(List vertices, List triangles, List colors) 837 | { 838 | this.vertices = vertices; 839 | this.triangles = triangles; 840 | this.colors = colors; 841 | } 842 | } 843 | } --------------------------------------------------------------------------------