/// <summary> /// Checks if mesh generation on other thread or on the GPU is finished. If so, it is applied to the mesh. /// </summary> public void Update() { if (cookie != null && cookie.IsCompleted) { MeshData result = method.EndInvoke(cookie); ApplyToMesh(result); UpdateDistances(); cookie = null; method = null; } if (isComputingOnGPU && gpuReadbackReq.done) { isComputingOnGPU = false; if (gpuReadbackReq.hasError) { computeBuffer.Dispose(); computeBuffer = null; configurationOld = bool4.True; GetNeighbors(); } else { var a = gpuReadbackReq.GetData <Vector3>().ToArray(); MeshData md = new MeshData(a, planet.quadMesh.normals, planet.quadMesh.uv); //print(md.vertices.Length + ", [0]: " + md.vertices[0].ToString("F4") + ", [1089]: " + md.vertices[1089].ToString("F4")); method = SpherifyAndDisplace; cookie = method.BeginInvoke(md, null, null); computeBuffer.Dispose(); computeBuffer = null; } } //Foliage Stuff: if (planet.generateDetails && (planet.generateFoliageInEveryBiome || planet.foliageBiomes.Contains(uniformBiome))) //Generating details if enabled and right biome. { if (level >= planet.grassLevel && foliageRenderer == null && renderedQuad && collider && distance < planet.dtDisSqr && planet.detailObjectsGenerating < planet.detailObjectsGeneratingSimultaneously) { var down = planet.Vector3Down(renderedQuad.transform.position); Ray ray = new Ray(collider.bounds.center - (down * 500), down); RaycastHit hit; if (collider.Raycast(ray, out hit, 5000f)) //Only start foliage generation if the collider is working, it needs a few frames to initialize { foliageRenderer = renderedQuad.AddComponent <FoliageRenderer>(); foliageRenderer.planet = planet; foliageRenderer.quad = this; planet.detailObjectsGenerating++; } } if (foliageRenderer != null && distance > planet.dtDisSqr) { MonoBehaviour.Destroy(foliageRenderer); foliageRenderer = null; } } }
public bool4(bool4 bools) { this.x = bools.x; this.y = bools.y; this.z = bools.z; this.w = bools.w; }
/// <summary> /// Resets all variables. Used for pooling. /// </summary> public void Reset() { uniformBiome = 0; parent = null; children = null; neighbors = null; configuration = bool4.False; hasSplit = false; isSplitting = false; initialized = false; isComputingOnGPU = false; computeBuffer = null; configurationOld = bool4.True; collider = null; neighborIds = null; meshOffset = Vector3.zero; foliageRenderer = null; distance = Mathf.Infinity; coroutine = null; level = 1; msd = 0f; gpuReadbackReq = new AsyncGPUReadbackRequest(); }
/// <summary> /// Finds this Quad's neighbors, then checks if edge fans are needed. If so, they are applied. /// </summary> public void GetNeighbors() { if (neighborIds == null) //Finding the IDs of all neigbors. This is only done once. { neighborIds = new string[4]; for (int i = 0; i < 4; i++) { neighborIds[i] = QuadNeighbor.GetNeighbor(index, i.ToString()); } } neighbors = new Quad[4]; for (int i = 0; i < neighbors.Length; i++) //Trying to find neighbors by id. If not there, neighbor has a lower subdivision level, last char of id is removed. { int j = 0; while (neighbors[i] == null && j < 4) { neighbors[i] = planet.FindQuad(neighborIds[i].Substring(0, neighborIds[i].Length - j)); j++; } /*neighbors[i] = null; * neighbors[i] = planet.FindQuad(neighborIds[i]); * * if (neighbors[i] == null) * neighbors[i] = planet.FindQuad(neighborIds[i].Substring(0, neighborIds[i].Length - 1));*/ } configuration = bool4.False; for (int i = 0; i < neighbors.Length; i++) //Creating configuration based on neighbor levels. { if (neighbors[i] != null) { if (neighbors[i].level == level - 1) { configuration[i] = true; } else { configuration[i] = false; } } else { configuration[i] = false; } } if (configuration != configurationOld) //Loading plane mesh and starting generation on another thread or GPU. { configurationOld = new bool4(configuration); if (!initialized) { MeshData md = new MeshData(ConstantTriArrays.extendedPlane, planet.quadMesh.normals, planet.quadMesh.uv); if (planet.mode == Mode.ComputeShader) { int kernelIndex = planet.computeShader.FindKernel("ComputePositions"); computeBuffer = new ComputeBuffer(1225, 12); computeBuffer.SetData(ConstantTriArrays.extendedPlane); planet.computeShader.SetFloat("scale", scale); planet.computeShader.SetFloats("trPosition", new float[] { trPosition.x, trPosition.y, trPosition.z }); planet.computeShader.SetFloat("radius", planet.radius); planet.computeShader.SetFloats("rotation", new float[] { rotation.x, rotation.y, rotation.z, rotation.w }); planet.computeShader.SetFloat("noiseDiv", 1f / planet.heightScale); planet.computeShader.SetBuffer(kernelIndex, "dataBuffer", computeBuffer); planet.computeShader.Dispatch(kernelIndex, 5, 1, 1); gpuReadbackReq = AsyncGPUReadback.Request(computeBuffer); isComputingOnGPU = true; } else { method = SpherifyAndDisplace; cookie = method.BeginInvoke(md, null, null); } } else { if (mesh.vertices.Length > 0) { mesh.triangles = Utils.GetTriangles(configuration.ToString()); } if (renderedQuad) { renderedQuad.GetComponent <MeshFilter>().mesh = mesh; } } } }