private void Update() { if (requests.Count > 0) { MeshRequest request = requests.OrderBy(x => Vector3.SqrMagnitude(x.chunk.centerPos - Observer.transform.position)).First(); requests.Remove(request); lock (requests) { ThreadStart thread = delegate { request.chunk.March(request.callback); }; thread.Invoke(); } } }
/// <summary> /// Returns the next logical mesh to generate. /// </summary> /// <returns></returns> public static MeshRequest[] getNextRequests() { int size = Math.Min(10, getRequestCount()); MeshRequest[] ret = new MeshRequest[size]; lock (requestArray) { for (int i = 0; i < ret.Length; i++) { ret[i] = getNextRequest(); } } return(ret); }
/// <summary> /// Adds a request to generate a mesh /// </summary> /// <param name="_node">The node the mesh is for</param> public static void requestMesh(Node _node) { MeshRequest req = new MeshRequest { node = _node, pos = _node.position, LOD = _node.LOD, isDone = false, hasDensities = (_node.densityData != null) }; if (!req.hasDensities) { lock (requestArray[req.LOD + 1]) requestArray[req.LOD + 1].Enqueue(req); } else { lock (requestArray[0]) requestArray[0].Enqueue(req); } }
public static void update() { if (setMeshQueue.Count > 0) { MeshRequest req = setMeshQueue.Dequeue(); req.node.setMesh(req.meshData); } for (int i = 0; i < generatorThreads.Length; i++) { MeshRequest req; while ((req = generatorThreads[i].getFinishedMesh()) != null) { chunksFinished++; if (req.node.disposed == false) { req.node.densityData = req.densities; if (req.meshData.triangleArray.Length > 0) { setMeshQueue.Enqueue(req); } else { req.node.setMesh(req.meshData); } } } } #region Save/Load threads Node node; while ((node = fileThread.getFinishedLoadRequest()) != null) { node.regenerateChunk(); nodesLoaded++; } #endregion }
/// <summary> /// Adds a request to generate a mesh /// </summary> /// <param name="_node">The node the mesh is for</param> public static void requestMesh(Node _node) { MeshRequest req = new MeshRequest { node = _node, pos = _node.position, LOD = _node.LOD, isDone = false, hasDensities = (_node.densityData != null) }; if (!req.hasDensities) lock (requestArray[req.LOD + 1]) requestArray[req.LOD + 1].Enqueue(req); else lock (requestArray[0]) requestArray[0].Enqueue(req); }
/// <summary> /// Returns the next logical mesh to generate. /// </summary> /// <returns></returns> public static MeshRequest[] getNextRequests() { int size = Math.Min(10, getRequestCount()); MeshRequest[] ret = new MeshRequest[size]; lock (requestArray) { for (int i = 0; i < ret.Length; i++) { ret[i] = getNextRequest(); } } return ret; }
/// <summary> /// Generates the mesh data /// </summary> public static void GenerateMeshData(MeshRequest request) { MeshData meshData = new MeshData(); request.meshData = meshData; //Check if the node requesting a generation has been disposed if (request == null || request.node.disposed) { meshData.triangleArray = new Vector3[0]; meshData.indexArray = new int[0][]; meshData.uvArray = new Vector2[0]; meshData.normalArray = new Vector3[0]; request.isDone = true; return; } DensityData densityArray = request.densities; Vector3[, ,] densityNormals = new Vector3[17, 17, 17]; List<Triangle> triangleList = new List<Triangle>(); List<int> subMeshIDList = new List<int>(); int[] subMeshTriCount = new int[QuixelEngine.materials.Length]; Node node = request.node; request.meshData = meshData; //Unoptimized generation densityNormals = new Vector3[18, 18, 18]; if (!request.hasDensities) { for (int x = -1; x < 18; x++) { for (int y = -1; y < 18; y++) { for (int z = -1; z < 18; z++) { VoxelData data = calculateDensity(node, new Vector3I(x, y, z)); densityArray.set(x, y, z, data.density); densityArray.setMaterial(x, y, z, data.material); } } } } for (int x = 0; x < 17; x++) { for (int y = 0; y < 17; y++) { for (int z = 0; z < 17; z++) { densityNormals[x, y, z] = calculateDensityNormal(new Vector3I(x, y, z), densityArray, node.LOD); } } } for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { generateTriangles(node, new Vector3I(x, y, z), triangleList, subMeshIDList, subMeshTriCount, densityArray, densityNormals); } } } int ppos = 0; int li = 0; try { meshData.triangleArray = new Vector3[triangleList.Count * 3]; meshData.indexArray = new int[QuixelEngine.materials.Length][]; for (int i = 0; i < QuixelEngine.materials.Length; i++) meshData.indexArray[i] = new int[(subMeshTriCount[i] * 3) * 3]; meshData.uvArray = new Vector2[meshData.triangleArray.Length]; meshData.normalArray = new Vector3[meshData.triangleArray.Length]; int count = 0; int[] indCount = new int[QuixelEngine.materials.Length]; for (int i = 0; i < triangleList.Count; i++) { ppos = i; Triangle triangle = triangleList[i]; meshData.triangleArray[count + 2] = triangle.pointOne; meshData.triangleArray[count + 1] = triangle.pointTwo; meshData.triangleArray[count + 0] = triangle.pointThree; meshData.normalArray[count + 2] = triangle.nOne; meshData.normalArray[count + 1] = triangle.nTwo; meshData.normalArray[count + 0] = triangle.nThree; int ind = subMeshIDList[i]; li = subMeshIDList[i]; meshData.indexArray[ind][indCount[ind] + 0] = count + 0; meshData.indexArray[ind][indCount[ind] + 1] = count + 1; meshData.indexArray[ind][indCount[ind] + 2] = count + 2; meshData.uvArray[count + 0] = new Vector2(meshData.triangleArray[count + 0].x, meshData.triangleArray[count + 0].z); meshData.uvArray[count + 1] = new Vector2(meshData.triangleArray[count + 1].x, meshData.triangleArray[count + 1].z); meshData.uvArray[count + 2] = new Vector2(meshData.triangleArray[count + 2].x, meshData.triangleArray[count + 2].z); count += 3; indCount[subMeshIDList[i]] += 3; } } catch (Exception e) { StreamWriter sw = new StreamWriter("Error Log.txt"); sw.WriteLine(e.Message + "\r\n" + e.StackTrace); for (int i = 0; i < QuixelEngine.materials.Length; i++) sw.WriteLine(i + ": " + subMeshTriCount[i]); sw.WriteLine(ppos); sw.WriteLine(li); sw.Close(); } request.isDone = true; }
/// <summary> /// Generates the mesh data /// </summary> public static void GenerateMeshData(MeshRequest request) { MeshData meshData = new MeshData(); request.meshData = meshData; //Check if the node requesting a generation has been disposed if (request == null || request.node.disposed) { meshData.triangleArray = new Vector3[0]; meshData.indexArray = new int[0][]; meshData.uvArray = new Vector2[0]; meshData.normalArray = new Vector3[0]; request.isDone = true; return; } DensityData densityArray = request.densities; Vector3[, ,] densityNormals = new Vector3[17, 17, 17]; List <Triangle> triangleList = new List <Triangle>(); List <int> subMeshIDList = new List <int>(); int[] subMeshTriCount = new int[QuixelEngine.materials.Length]; Node node = request.node; request.meshData = meshData; //Unoptimized generation densityNormals = new Vector3[18, 18, 18]; if (!request.hasDensities) { for (int x = -1; x < 18; x++) { for (int y = -1; y < 18; y++) { for (int z = -1; z < 18; z++) { VoxelData data = calculateDensity(node, new Vector3I(x, y, z)); densityArray.set(x, y, z, data.density); densityArray.setMaterial(x, y, z, data.material); } } } } for (int x = 0; x < 17; x++) { for (int y = 0; y < 17; y++) { for (int z = 0; z < 17; z++) { densityNormals[x, y, z] = calculateDensityNormal(new Vector3I(x, y, z), densityArray, node.LOD); } } } for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { generateTriangles(node, new Vector3I(x, y, z), triangleList, subMeshIDList, subMeshTriCount, densityArray, densityNormals); } } } int ppos = 0; int li = 0; try { meshData.triangleArray = new Vector3[triangleList.Count * 3]; meshData.indexArray = new int[QuixelEngine.materials.Length][]; for (int i = 0; i < QuixelEngine.materials.Length; i++) { meshData.indexArray[i] = new int[(subMeshTriCount[i] * 3) * 3]; } meshData.uvArray = new Vector2[meshData.triangleArray.Length]; meshData.normalArray = new Vector3[meshData.triangleArray.Length]; int count = 0; int[] indCount = new int[QuixelEngine.materials.Length]; for (int i = 0; i < triangleList.Count; i++) { ppos = i; Triangle triangle = triangleList[i]; meshData.triangleArray[count + 2] = triangle.pointOne; meshData.triangleArray[count + 1] = triangle.pointTwo; meshData.triangleArray[count + 0] = triangle.pointThree; meshData.normalArray[count + 2] = triangle.nOne; meshData.normalArray[count + 1] = triangle.nTwo; meshData.normalArray[count + 0] = triangle.nThree; int ind = subMeshIDList[i]; li = subMeshIDList[i]; meshData.indexArray[ind][indCount[ind] + 0] = count + 0; meshData.indexArray[ind][indCount[ind] + 1] = count + 1; meshData.indexArray[ind][indCount[ind] + 2] = count + 2; meshData.uvArray[count + 0] = new Vector2(meshData.triangleArray[count + 0].x, meshData.triangleArray[count + 0].z); meshData.uvArray[count + 1] = new Vector2(meshData.triangleArray[count + 1].x, meshData.triangleArray[count + 1].z); meshData.uvArray[count + 2] = new Vector2(meshData.triangleArray[count + 2].x, meshData.triangleArray[count + 2].z); count += 3; indCount[subMeshIDList[i]] += 3; } } catch (Exception e) { StreamWriter sw = new StreamWriter("Error Log.txt"); sw.WriteLine(e.Message + "\r\n" + e.StackTrace); for (int i = 0; i < QuixelEngine.materials.Length; i++) { sw.WriteLine(i + ": " + subMeshTriCount[i]); } sw.WriteLine(ppos); sw.WriteLine(li); sw.Close(); } request.isDone = true; }