629 lines
18 KiB
C#
629 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace Artngame.SKYMASTER.PlanetCreator
|
|
{
|
|
public class PlanetCreator : MonoBehaviour
|
|
{
|
|
public Transform Sun;
|
|
|
|
public int ChunkSegments = 32;
|
|
|
|
public float SphereRadius = 10f;
|
|
|
|
public float ChunkSize = 128f;
|
|
|
|
public Material mat;
|
|
|
|
public float TerrainFreq = 0.006f;
|
|
|
|
public float TerrainGain = 0.5f;
|
|
|
|
public float Terrainlacunarity = 2f;
|
|
|
|
public float TerrainScale = 20f;
|
|
|
|
public float TerrainBumpScale = 20f;
|
|
|
|
public Camera MainCamera;
|
|
|
|
private List<PlanetChunkProperties> rootChunks;
|
|
|
|
public int MaxLodLevel = 7;
|
|
|
|
public int LodColliderStart = 5;
|
|
|
|
public float MaxError = 1f;
|
|
|
|
public float MaxSplitsPerSecond = 20f;
|
|
|
|
private Mesh BasicPlane;
|
|
|
|
private Stack<PlanetChunkObject> MeshPool;
|
|
|
|
private Queue<PlanetChunkProperties> SplitPool;
|
|
|
|
public int PoolStartPopulation;
|
|
|
|
public ComputeBuffer VertexComputeBuffer;
|
|
|
|
public ComputeBuffer NormalComputeBuffer;
|
|
|
|
public ComputeBuffer PlanetMapCreatorBuffer;
|
|
|
|
public ComputeShader VertexComputeShader;
|
|
|
|
public ComputeShader PlanetMapGeneratorShader;
|
|
|
|
private ImprovedPerlinNoise m_perlin;
|
|
|
|
private readonly List<Vector2> uvsTmp = new List<Vector2>();
|
|
|
|
private readonly List<Vector3> vertexTmp = new List<Vector3>();
|
|
|
|
private readonly List<Vector3> normalTmp = new List<Vector3>();
|
|
|
|
private float lastSplitTime;
|
|
|
|
private static readonly int Frequency = Shader.PropertyToID("_Frequency");
|
|
|
|
private static readonly int Lacunarity = Shader.PropertyToID("_Lacunarity");
|
|
|
|
private static readonly int Gain = Shader.PropertyToID("_Gain");
|
|
|
|
private static readonly int PlanetRadius = Shader.PropertyToID("_PlanetRadius");
|
|
|
|
private static readonly int PermTable2D = Shader.PropertyToID("_PermTable2D");
|
|
|
|
private static readonly int Gradient3D = Shader.PropertyToID("_Gradient3D");
|
|
|
|
public float K { get; set; }
|
|
|
|
public int MeshPoolSize => MeshPool.Count;
|
|
|
|
public int SplitPoolSize => SplitPool.Count;
|
|
|
|
public void Start()
|
|
{
|
|
Precompute();
|
|
MeshPool = new Stack<PlanetChunkObject>();
|
|
SplitPool = new Queue<PlanetChunkProperties>();
|
|
BasicPlane = GeneratePremadePlane(ChunkSegments);
|
|
rootChunks = new List<PlanetChunkProperties>();
|
|
CreateRoot(Vector3.left, 0f);
|
|
CreateRoot(Vector3.left, 90f);
|
|
CreateRoot(Vector3.left, 180f);
|
|
CreateRoot(Vector3.left, 270f);
|
|
CreateRoot(Vector3.forward, 90f);
|
|
CreateRoot(Vector3.forward, 270f);
|
|
for (int i = 0; i < PoolStartPopulation; i++)
|
|
{
|
|
AddToChunkPool(CreateBasicChunkObject());
|
|
}
|
|
}
|
|
|
|
private void CreateTemperatureMap()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
Texture2D texture2D = new Texture2D(1024, 1024, TextureFormat.RGBA32, mipChain: false);
|
|
Vector3[] array = new Vector3[1048576];
|
|
Color32[] array2 = new Color32[1048576];
|
|
int num = 0;
|
|
for (int j = 0; j < 1024; j++)
|
|
{
|
|
for (int k = 0; k < 1024; k++)
|
|
{
|
|
array[num++] = new Vector3(j, k, 0f);
|
|
}
|
|
}
|
|
PlanetMapCreatorBuffer.SetData(array);
|
|
PlanetMapGeneratorShader.Dispatch(0, 1048576, 1, 1);
|
|
PlanetMapCreatorBuffer.GetData(array);
|
|
for (int l = 0; l < 1048576; l++)
|
|
{
|
|
array2[l] = new Color32((byte)(array[l].x * 255f), 0, 0, byte.MaxValue);
|
|
}
|
|
texture2D.SetPixels32(array2);
|
|
using FileStream output = new FileStream("D:/Test/" + i + ".png", FileMode.OpenOrCreate);
|
|
new BinaryWriter(output).Write(texture2D.EncodeToPNG());
|
|
}
|
|
}
|
|
|
|
public void Precompute()
|
|
{
|
|
K = (float)Screen.width / (2f * Mathf.Tan(MathF.PI * 13f / 72f));
|
|
m_perlin = new ImprovedPerlinNoise(0);
|
|
m_perlin.LoadResourcesFor3DNoise();
|
|
Texture2D permutationTable2D = m_perlin.GetPermutationTable2D();
|
|
Texture2D gradient3D = m_perlin.GetGradient3D();
|
|
VertexComputeShader.SetTexture(0, "_PermTable2D", permutationTable2D);
|
|
VertexComputeShader.SetTexture(0, "_Gradient3D", gradient3D);
|
|
mat.SetTexture(PermTable2D, permutationTable2D);
|
|
mat.SetTexture(Gradient3D, gradient3D);
|
|
VertexComputeBuffer = new ComputeBuffer((ChunkSegments + 2) * (ChunkSegments + 2), 12);
|
|
NormalComputeBuffer = new ComputeBuffer((ChunkSegments + 2) * (ChunkSegments + 2), 12);
|
|
PlanetMapCreatorBuffer = new ComputeBuffer(1048576, 32);
|
|
VertexComputeShader.SetBuffer(0, "vertexBuffer", VertexComputeBuffer);
|
|
VertexComputeShader.SetBuffer(0, "normalBuffer", NormalComputeBuffer);
|
|
PlanetMapGeneratorShader.SetBuffer(0, "Output", PlanetMapCreatorBuffer);
|
|
PlanetMapGeneratorShader.SetTexture(0, "_PermTable2D", permutationTable2D);
|
|
PlanetMapGeneratorShader.SetTexture(0, "_Gradient3D", gradient3D);
|
|
UpdateNoise();
|
|
}
|
|
|
|
public void CreateRoot(Vector3 rotationDir, float angle)
|
|
{
|
|
PlanetChunkProperties planetChunkProperties = CreateChunkProperties(null, Quaternion.AngleAxis(angle, rotationDir), 1f, 0, Vector2.zero);
|
|
GetFreeChunkObject(planetChunkProperties);
|
|
rootChunks.Add(planetChunkProperties);
|
|
}
|
|
|
|
public void CreateChunk(PlanetChunkProperties parent, Vector2 min, int index)
|
|
{
|
|
parent.Chunks[index] = CreateChunkProperties(parent, parent.Rotation, parent.Size / 2f, parent.LODLevel + 1, min);
|
|
parent.Chunks[index].ChunkObject = GetFreeChunkObject(parent.Chunks[index]);
|
|
parent.Chunks[index].Bounds = parent.Chunks[index].ChunkObject.GetComponent<MeshRenderer>().bounds;
|
|
}
|
|
|
|
private PlanetChunkObject CreateBasicChunkObject()
|
|
{
|
|
PlanetChunkObject component = new GameObject("Chunk", typeof(MeshFilter), typeof(MeshCollider), typeof(MeshRenderer), typeof(PlanetChunkObject)).GetComponent<PlanetChunkObject>();
|
|
component.Filter = component.GetComponent<MeshFilter>();
|
|
component.Collider = component.GetComponent<MeshCollider>();
|
|
component.Renderer = component.GetComponent<Renderer>();
|
|
component.Renderer.sharedMaterial = mat;
|
|
return component;
|
|
}
|
|
|
|
public PlanetChunkObject UpdateChunkObject(PlanetChunkProperties chunkProperties, PlanetChunkObject chunk)
|
|
{
|
|
chunk.transform.localPosition = Vector3.zero;
|
|
chunk.Properties = chunkProperties;
|
|
chunkProperties.ChunkObject = chunk;
|
|
UpdateChunkMesh(chunk);
|
|
return chunk;
|
|
}
|
|
|
|
public PlanetChunkProperties GetNearestChunkProperties(Vector3 point)
|
|
{
|
|
if (rootChunks == null)
|
|
{
|
|
return null;
|
|
}
|
|
float num = float.PositiveInfinity;
|
|
PlanetChunkProperties parent = null;
|
|
foreach (PlanetChunkProperties rootChunk in rootChunks)
|
|
{
|
|
float sqrMagnitude = (rootChunk.Bounds.center - point).sqrMagnitude;
|
|
if (sqrMagnitude < num)
|
|
{
|
|
num = sqrMagnitude;
|
|
parent = rootChunk;
|
|
}
|
|
}
|
|
return GetNearestChunkProperties(parent, point);
|
|
}
|
|
|
|
private PlanetChunkProperties GetNearestChunkProperties(PlanetChunkProperties parent, Vector3 point)
|
|
{
|
|
if (parent.Chunks == null)
|
|
{
|
|
return parent;
|
|
}
|
|
float num = float.PositiveInfinity;
|
|
PlanetChunkProperties parent2 = null;
|
|
PlanetChunkProperties[] chunks = parent.Chunks;
|
|
foreach (PlanetChunkProperties planetChunkProperties in chunks)
|
|
{
|
|
float sqrMagnitude = (planetChunkProperties.Bounds.center - point).sqrMagnitude;
|
|
if (sqrMagnitude < num)
|
|
{
|
|
parent2 = planetChunkProperties;
|
|
num = sqrMagnitude;
|
|
}
|
|
}
|
|
return GetNearestChunkProperties(parent2, point);
|
|
}
|
|
|
|
public PlanetChunkObject GetChunkObjectFromPool()
|
|
{
|
|
if (MeshPool.Count > 0)
|
|
{
|
|
return MeshPool.Pop();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public PlanetChunkObject GetFreeChunkObject(PlanetChunkProperties chunkProperties)
|
|
{
|
|
PlanetChunkObject planetChunkObject = GetChunkObjectFromPool();
|
|
if (planetChunkObject == null)
|
|
{
|
|
planetChunkObject = CreateBasicChunkObject();
|
|
}
|
|
UpdateChunkObject(chunkProperties, planetChunkObject);
|
|
return planetChunkObject;
|
|
}
|
|
|
|
public void UpdateChunkMesh(PlanetChunkObject chunk)
|
|
{
|
|
if (chunk.Filter.sharedMesh == null)
|
|
{
|
|
chunk.Filter.sharedMesh = CopyMesh(BasicPlane);
|
|
}
|
|
CaluclateVertex(chunk);
|
|
}
|
|
|
|
private void UpdateNoise()
|
|
{
|
|
VertexComputeShader.SetFloat(Frequency, TerrainFreq);
|
|
VertexComputeShader.SetFloat(Lacunarity, Terrainlacunarity);
|
|
VertexComputeShader.SetFloat(Gain, TerrainGain);
|
|
mat.SetFloat(Frequency, TerrainFreq);
|
|
mat.SetFloat(Lacunarity, Terrainlacunarity);
|
|
mat.SetFloat(Gain, TerrainGain);
|
|
mat.SetFloat(PlanetRadius, SphereRadius);
|
|
}
|
|
|
|
public void AddToChunkPool(PlanetChunkObject chunk)
|
|
{
|
|
MeshPool.Push(chunk);
|
|
}
|
|
|
|
public PlanetChunkProperties CreateChunkProperties(PlanetChunkProperties parent, Quaternion rotation, float Size, int LodLevel, Vector2 min)
|
|
{
|
|
PlanetChunkProperties planetChunkProperties = new PlanetChunkProperties();
|
|
planetChunkProperties.Rotation = rotation;
|
|
planetChunkProperties.Parent = parent;
|
|
planetChunkProperties.LODLevel = LodLevel;
|
|
planetChunkProperties.Size = Size;
|
|
planetChunkProperties.min = min;
|
|
planetChunkProperties.Center = (planetChunkProperties.Rotation * new Vector3(planetChunkProperties.Middle.x - 0.5f, 1f, planetChunkProperties.Middle.y - 0.5f)).normalized * SphereRadius;
|
|
planetChunkProperties.maxGeoError = Mathf.Pow(2f, MaxLodLevel - planetChunkProperties.LODLevel);
|
|
return planetChunkProperties;
|
|
}
|
|
|
|
public void CaluclateVertex(PlanetChunkObject chunk)
|
|
{
|
|
int num = ChunkSegments + 2;
|
|
int num2 = ChunkSegments + 2;
|
|
int num3 = num * num2;
|
|
vertexTmp.Clear();
|
|
normalTmp.Clear();
|
|
uvsTmp.Clear();
|
|
float num4 = chunk.Properties.Size / (float)ChunkSegments;
|
|
for (float num5 = 0f; num5 < (float)num2; num5 += 1f)
|
|
{
|
|
for (float num6 = 0f; num6 < (float)num; num6 += 1f)
|
|
{
|
|
float x = chunk.Properties.BottomLeft.x + num6 * num4 - 0.5f;
|
|
float y = chunk.Properties.BottomLeft.y + num5 * num4 - 0.5f;
|
|
vertexTmp.Add(GeVertex(chunk.Properties.Rotation, SphereRadius, x, y));
|
|
uvsTmp.Add(chunk.Properties.BottomLeft + new Vector2(num6 * num4, num5 * num4));
|
|
}
|
|
}
|
|
VertexComputeBuffer.SetData(vertexTmp);
|
|
NormalComputeBuffer.SetData(normalTmp);
|
|
VertexComputeShader.SetFloat("Scale", num4);
|
|
VertexComputeShader.SetFloat("TerrainScale", TerrainScale);
|
|
VertexComputeShader.SetFloat("TerrainBumpScale", TerrainBumpScale);
|
|
VertexComputeShader.Dispatch(0, num3 / 16, 1, 1);
|
|
AsyncGPUReadback.Request(VertexComputeBuffer, chunk.ApplyVertexData);
|
|
AsyncGPUReadback.Request(NormalComputeBuffer, chunk.ApplyNormalData);
|
|
chunk.MarkCalculatingVertexData();
|
|
chunk.name = "Recycled Mesh";
|
|
chunk.Filter.sharedMesh.SetUVs(0, uvsTmp);
|
|
chunk.SetVisible(visible: true);
|
|
if (chunk.Properties != null)
|
|
{
|
|
if (chunk.Properties.LODLevel >= LodColliderStart)
|
|
{
|
|
chunk.Collider.sharedMesh = null;
|
|
chunk.Collider.sharedMesh = chunk.Filter.sharedMesh;
|
|
chunk.Collider.enabled = true;
|
|
}
|
|
else
|
|
{
|
|
chunk.Collider.enabled = false;
|
|
}
|
|
chunk.Properties.Active = true;
|
|
}
|
|
}
|
|
|
|
public Vector3 GeVertex(Quaternion rotation, float SphereRadius, float X, float Y)
|
|
{
|
|
Vector3 vector = rotation * new Vector3(X, 0.5f, Y);
|
|
return ToSphere(vector) * SphereRadius;
|
|
}
|
|
|
|
public static void calculateMeshTangents(Mesh mesh)
|
|
{
|
|
int[] triangles = mesh.triangles;
|
|
Vector3[] vertices = mesh.vertices;
|
|
Vector2[] uv = mesh.uv;
|
|
Vector3[] normals = mesh.normals;
|
|
int num = triangles.Length;
|
|
int num2 = vertices.Length;
|
|
Vector3[] array = new Vector3[num2];
|
|
Vector3[] array2 = new Vector3[num2];
|
|
Vector4[] array3 = new Vector4[num2];
|
|
for (long num3 = 0L; num3 < num; num3 += 3)
|
|
{
|
|
long num4 = triangles[num3];
|
|
long num5 = triangles[num3 + 1];
|
|
long num6 = triangles[num3 + 2];
|
|
Vector3 vector = vertices[num4];
|
|
Vector3 vector2 = vertices[num5];
|
|
Vector3 vector3 = vertices[num6];
|
|
Vector2 vector4 = uv[num4];
|
|
Vector2 vector5 = uv[num5];
|
|
Vector2 vector6 = uv[num6];
|
|
float num7 = vector2.x - vector.x;
|
|
float num8 = vector3.x - vector.x;
|
|
float num9 = vector2.y - vector.y;
|
|
float num10 = vector3.y - vector.y;
|
|
float num11 = vector2.z - vector.z;
|
|
float num12 = vector3.z - vector.z;
|
|
float num13 = vector5.x - vector4.x;
|
|
float num14 = vector6.x - vector4.x;
|
|
float num15 = vector5.y - vector4.y;
|
|
float num16 = vector6.y - vector4.y;
|
|
float num17 = 1f / (num13 * num16 - num14 * num15);
|
|
Vector3 vector7 = new Vector3((num16 * num7 - num15 * num8) * num17, (num16 * num9 - num15 * num10) * num17, (num16 * num11 - num15 * num12) * num17);
|
|
Vector3 vector8 = new Vector3((num13 * num8 - num14 * num7) * num17, (num13 * num10 - num14 * num9) * num17, (num13 * num12 - num14 * num11) * num17);
|
|
array[num4] += vector7;
|
|
array[num5] += vector7;
|
|
array[num6] += vector7;
|
|
array2[num4] += vector8;
|
|
array2[num5] += vector8;
|
|
array2[num6] += vector8;
|
|
}
|
|
for (long num18 = 0L; num18 < num2; num18++)
|
|
{
|
|
Vector3 normal = normals[num18];
|
|
Vector3 tangent = array[num18];
|
|
Vector3.OrthoNormalize(ref normal, ref tangent);
|
|
array3[num18].x = tangent.x;
|
|
array3[num18].y = tangent.y;
|
|
array3[num18].z = tangent.z;
|
|
array3[num18].w = ((Vector3.Dot(Vector3.Cross(normal, tangent), array2[num18]) < 0f) ? (-1f) : 1f);
|
|
}
|
|
mesh.tangents = array3;
|
|
}
|
|
|
|
public static Mesh CopyMesh(Mesh mesh)
|
|
{
|
|
return UnityEngine.Object.Instantiate(mesh);
|
|
}
|
|
|
|
public Mesh GeneratePremadePlane(int Segments)
|
|
{
|
|
Mesh mesh = new Mesh();
|
|
int num = Segments + 2;
|
|
int num2 = Segments * Segments * 6;
|
|
int num3 = num * num;
|
|
int num4 = 0;
|
|
float num5 = 1f / (float)Segments;
|
|
float num6 = 1f / (float)Segments;
|
|
float num7 = 1f / (float)Segments;
|
|
float num8 = 1f / (float)Segments;
|
|
int[] array = new int[num2];
|
|
Vector2[] array2 = new Vector2[num3];
|
|
Vector3[] array3 = new Vector3[num3];
|
|
for (float num9 = 0f; num9 < (float)num; num9 += 1f)
|
|
{
|
|
for (float num10 = 0f; num10 < (float)num; num10 += 1f)
|
|
{
|
|
float x = num10 * num7 - 0.5f;
|
|
float z = num9 * num8 - 0.5f;
|
|
array2[num4] = new Vector2(num10 * num5, num9 * num6);
|
|
array3[num4++] = new Vector3(x, 1f, z);
|
|
}
|
|
}
|
|
num4 = 0;
|
|
for (int i = 0; i < Segments; i++)
|
|
{
|
|
for (int j = 0; j < Segments; j++)
|
|
{
|
|
array[num4] = i * num + j;
|
|
array[num4 + 1] = (i + 1) * num + j;
|
|
array[num4 + 2] = i * num + j + 1;
|
|
array[num4 + 3] = (i + 1) * num + j;
|
|
array[num4 + 4] = (i + 1) * num + j + 1;
|
|
array[num4 + 5] = i * num + j + 1;
|
|
num4 += 6;
|
|
}
|
|
}
|
|
mesh.vertices = array3;
|
|
mesh.triangles = array;
|
|
mesh.uv = array2;
|
|
mesh.RecalculateNormals();
|
|
mesh.RecalculateBounds();
|
|
calculateMeshTangents(mesh);
|
|
calculateMeshTangents(mesh);
|
|
return mesh;
|
|
}
|
|
|
|
public static Bounds CopyBounds(Bounds bounds)
|
|
{
|
|
return new Bounds
|
|
{
|
|
min = bounds.min,
|
|
max = bounds.max,
|
|
size = bounds.size,
|
|
center = bounds.center
|
|
};
|
|
}
|
|
|
|
private Vector3 ToSphere(Vector3 vector)
|
|
{
|
|
return vector.normalized;
|
|
}
|
|
|
|
private Vector3 SphericalPos(Vector3 pos, float radius)
|
|
{
|
|
return pos.normalized * radius;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
ManageChunks();
|
|
UpdateNoise();
|
|
if (SplitPool.Count > 0 && lastSplitTime - Time.time <= 0f)
|
|
{
|
|
PlanetChunkProperties chunk = SplitPool.Dequeue();
|
|
Split(chunk);
|
|
lastSplitTime = Time.time + 1f / MaxSplitsPerSecond;
|
|
}
|
|
}
|
|
|
|
public bool NeedsSplit(PlanetChunkProperties chunk)
|
|
{
|
|
return chunk.maxGeoError / Mathf.Sqrt(chunk.ChunkObject.Renderer.bounds.SqrDistance(MainCamera.transform.position)) * K > MaxError;
|
|
}
|
|
|
|
public void AddToSplitPool(PlanetChunkProperties chunk)
|
|
{
|
|
if (!SplitPool.Contains(chunk))
|
|
{
|
|
SplitPool.Enqueue(chunk);
|
|
}
|
|
}
|
|
|
|
private void ManageChunks()
|
|
{
|
|
foreach (PlanetChunkProperties rootChunk in rootChunks)
|
|
{
|
|
ManageRecursive(rootChunk);
|
|
}
|
|
}
|
|
|
|
public void ManageRecursive(PlanetChunkProperties chunk)
|
|
{
|
|
if (NeedsSplit(chunk) && chunk.LODLevel < MaxLodLevel)
|
|
{
|
|
if (chunk.isSplit)
|
|
{
|
|
bool flag = false;
|
|
PlanetChunkProperties[] children = chunk.Children;
|
|
foreach (PlanetChunkProperties planetChunkProperties in children)
|
|
{
|
|
flag |= planetChunkProperties.ChunkObject.IsCalculating;
|
|
ManageRecursive(planetChunkProperties);
|
|
}
|
|
if (!flag)
|
|
{
|
|
HideChunk(chunk);
|
|
}
|
|
chunk.isSpliting = false;
|
|
}
|
|
else
|
|
{
|
|
AddToSplitPool(chunk);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Merge(chunk);
|
|
}
|
|
}
|
|
|
|
public void Split(PlanetChunkProperties chunk)
|
|
{
|
|
if (!(chunk.ChunkObject != null) || !NeedsSplit(chunk))
|
|
{
|
|
return;
|
|
}
|
|
if (chunk.Children == null)
|
|
{
|
|
chunk.Children = new PlanetChunkProperties[4];
|
|
CreateChunk(chunk, chunk.min, 0);
|
|
CreateChunk(chunk, chunk.MiddleLeft, 1);
|
|
CreateChunk(chunk, chunk.BottomMiddle, 2);
|
|
CreateChunk(chunk, chunk.Middle, 3);
|
|
}
|
|
else
|
|
{
|
|
PlanetChunkProperties[] children = chunk.Children;
|
|
foreach (PlanetChunkProperties chunk2 in children)
|
|
{
|
|
EnableChunk(chunk2);
|
|
}
|
|
}
|
|
chunk.isMerged = false;
|
|
}
|
|
|
|
public void Merge(PlanetChunkProperties chunk)
|
|
{
|
|
if (chunk.isMerged)
|
|
{
|
|
return;
|
|
}
|
|
if (chunk.Children != null)
|
|
{
|
|
PlanetChunkProperties[] children = chunk.Children;
|
|
foreach (PlanetChunkProperties child in children)
|
|
{
|
|
MergeChildren(chunk, child);
|
|
}
|
|
}
|
|
EnableChunk(chunk);
|
|
chunk.isMerged = true;
|
|
}
|
|
|
|
private void MergeChildren(PlanetChunkProperties parent, PlanetChunkProperties child)
|
|
{
|
|
if (!child.isMerged && child.Children != null)
|
|
{
|
|
PlanetChunkProperties[] children = child.Children;
|
|
foreach (PlanetChunkProperties child2 in children)
|
|
{
|
|
MergeChildren(parent, child2);
|
|
}
|
|
}
|
|
DisableChunk(child);
|
|
parent.isMerged = true;
|
|
}
|
|
|
|
public void EnableChunk(PlanetChunkProperties chunk)
|
|
{
|
|
if (chunk.ChunkObject == null)
|
|
{
|
|
chunk.ChunkObject = GetFreeChunkObject(chunk);
|
|
}
|
|
chunk.ChunkObject.SetVisible(visible: true);
|
|
}
|
|
|
|
public void HideChunk(PlanetChunkProperties chunk)
|
|
{
|
|
if (chunk.ChunkObject != null && chunk.ChunkObject.IsVisible)
|
|
{
|
|
chunk.ChunkObject.SetVisible(visible: false);
|
|
}
|
|
}
|
|
|
|
public void DisableChunk(PlanetChunkProperties chunk)
|
|
{
|
|
if (chunk.ChunkObject.Collider != null)
|
|
{
|
|
chunk.ChunkObject.Collider.enabled = false;
|
|
}
|
|
HideChunk(chunk);
|
|
AddToChunkPool(chunk.ChunkObject);
|
|
chunk.ChunkObject = null;
|
|
chunk.Active = false;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
VertexComputeBuffer.Dispose();
|
|
NormalComputeBuffer.Dispose();
|
|
PlanetMapCreatorBuffer.Dispose();
|
|
}
|
|
}
|
|
}
|