static MarchingCubesDispatcher instance; // just used to make sure only one of these at once void Awake() { if (!SystemInfo.supportsComputeShaders) { Debug.LogError("THIS IS BAD"); DestroyImmediate(gameObject); return; } if (instance == null) { instance = this; } else { DestroyImmediate(this); return; } queue = new FastPriorityQueue <ChunkRequest>(10000); kernelMC = MarchingCubesCS.FindKernel("MarchingCubes"); //kernelTripleCount = MarchingCubesCS.FindKernel("TripleCount"); MarchingCubesCS.SetInt("_gridSize", resolution); MarchingCubesCS.SetFloat("_isoLevel", 0.0f); // halfway point for noise in range [-1, 1] workers = new MarchingCubesWorker[numWorkers]; for (int i = 0; i < workers.Length; ++i) { workers[i] = new MarchingCubesWorker(resolution, kernelMC, MarchingCubesCS, noiseMat); } }
// for GPU cubes. just throw out all ur meshes and request new ones // nice for when you change material params public void ResetMeshes() { SetSplitting(false); // dont do this actually since changing parameters will cause the terrain to change // so spots that were empty might not be anymore... even doing this tho will cause the number of // trees to rise as old ones that were split fully become empty but remain max split // should maybe just rebuild whole tree everytime... // this is just purely for debugging tho so doesnt really matter if (emptyMesh) { //return; } if (obj.mf.mesh != null) { Object.Destroy(obj.mf.mesh); } // double check that the tree didnt die is only thing (inner nodes should still get their meshes regened) MarchingCubesDispatcher.Enqueue(worldPos, voxelSize, AssignMesh, NotDead, GetSqrDistToCamFromCenter()); // do this since still splitting emptys in this mode if (hasChildren) { for (int i = 0; i < 8; ++i) { children[i].ResetMeshes(); } } }
void Update() { if (Input.GetKey(KeyCode.R)) { transform.Rotate(rotation * Time.deltaTime); } if (Input.GetKeyDown(KeyCode.P)) { MarchingCubesDispatcher.ClearRequests(); root.ResetMeshes(); } currentMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); // cache player position this frame because like a billion things reference // this and the cost of transform.getposition adds up player = playerTransform.position; root.Update(); invalidCheckTimer -= Time.deltaTime; if (invalidCheckTimer < 0.0f) { if (!root.IsTreeValid()) { Debug.LogError("INVALID TREE DETECTED"); } invalidCheckTimer = 2.0f; int num = root.GetCount(false); countText.text = "Trees: " + num; //Debug.Log(root.GetNumGameObjects(true)); } }
// Use this for initialization void Start() { // will later need to set this in chunk material property blocks i think //mat.SetVector("_PlanetCenter", transform.position); root = new Octree(this, null, Vector3.zero, 0, 0); //root.BuildGameObject(root.GenerateMesh(true)); root.SetupChunk(); MarchingCubesDispatcher.Enqueue(root.worldPos, root.voxelSize, root.AssignMesh, root.GetSqrDistToCamFromCenter()); //root.SplitCompute(); // calculating split levels by hand now // too hard to get right witha formula to look good both on surface and // from high up in space (may need to change strat, like dynamic split more chunks based on total num tris) Debug.Assert(splitLevels.Length >= Octree.MAX_DEPTH + 1); //splitLevels = new float[Octree.MAX_DEPTH + 1]; //int len = splitLevels.Length; //splitLevels[len - 1] = maxDepthDist; //for (int i = len - 2; i >= 0; --i) { // splitLevels[i] = splitLevels[i + 1] * 1.74f; // //splitLevels[i] = splitLevels[i + 1] * 2.0f; //} // old way of calculating squaresplit levels //for (int i = 0; i < squareSplitLevels.Length; i++) { // float level = Mathf.Pow(2f, Octree.MAX_DEPTH - i) * 100f; //64.0f; // squareSplitLevels[i] = level * level; //} rotation = Random.onUnitSphere; // * speed? playerTransform = GameObject.Find("Player").transform; }
public void SplitCompute() { SetSplitting(true); if (childMeshes == null) { childMeshes = new MeshData[8]; } childMeshCount = 0; int childDepth = depth + 1; float childVoxelSize = GetVoxelSize(childDepth); float priority = GetSplitPriority(); for (int i = 0; i < 8; ++i) { Vector3 childWorldPos = GetChildCenter(i) - Vector3.one * (SIZE / 2f) * childVoxelSize; MarchingCubesDispatcher.Enqueue(childWorldPos, childVoxelSize, GetChildMesh, LastSplitCheck, priority, i); } }