void DeleteChunk(Vector3Int chunkToDelete) { SDMeshChunk chunk = null; if (chunks.TryGetValue(chunkToDelete, out chunk)) { Destroy(chunk.meshFilter.sharedMesh); Destroy(chunk.gameObject); chunks.Remove(chunkToDelete); } }
void UpdateChunk(Vector3Int chunkToUpdate) { SDMeshChunk chunk = null; if (chunks.TryGetValue(chunkToUpdate, out chunk)) { chunk.meshVersion = meshVersion; List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <int> indices = new List <int>(); List <Color32> colors = new List <Color32>(); int offset = 0; foreach (SDMeshBlock block in chunk.blocks.Values) { vertices.AddRange(block.vertices); normals.AddRange(block.normals); foreach (Vector3Int triangle in block.triangles) { indices.Add(triangle.x + offset); indices.Add(triangle.y + offset); indices.Add(triangle.z + offset); } offset += block.vertices.Count; Color32 vertexColor = Color.HSVToRGB((block.meshVersion % 256) * 0.00392157f, 1f, 1f); colors.AddRange(System.Linq.Enumerable.Repeat(vertexColor, block.vertices.Count)); } Mesh workMesh = chunk.meshFilter.sharedMesh; workMesh.Clear(); if (vertices.Count > 0 && indices.Count > 0) { workMesh.vertices = vertices.ToArray(); workMesh.normals = normals.ToArray(); workMesh.triangles = indices.ToArray(); workMesh.colors32 = colors.ToArray(); if (enableMeshCollider && chunk.meshCollider) { chunk.meshCollider.sharedMesh = workMesh; } } else { DeleteChunk(chunkToUpdate); } } }
SDMeshBlock GetOrCreateBlock(SDMeshChunk chunk, Vector3Int blockCoords) { SDMeshBlock block = null; // Create new block if it's not part of the dict if (!chunk.blocks.TryGetValue(blockCoords, out block)) { block = new SDMeshBlock { coordinates = blockCoords, vertices = new List <Vector3>(), normals = new List <Vector3>(), triangles = new List <Vector3Int>(), version = -1, meshVersion = -1 }; chunk.blocks.Add(blockCoords, block); } return(block); }
SDMeshChunk GetOrCreateChunk(Vector3Int chunkCoords) { SDMeshChunk chunk = null; // Create new chunk if it's not part of the dict if (!chunks.TryGetValue(chunkCoords, out chunk)) { string chunkName = "Mesh Chunk " + chunkCoords.x + "," + chunkCoords.y + "," + chunkCoords.z; GameObject chunkObject = new GameObject(chunkName); chunkObject.transform.SetParent(transform); chunkObject.layer = MeshLayer; MeshFilter meshFilter = chunkObject.AddComponent <MeshFilter>(); meshFilter.sharedMesh = new Mesh(); MeshRenderer meshRenderer = chunkObject.AddComponent <MeshRenderer>(); meshRenderer.material = meshVisible ? meshMaterial : depthMaskMaterial; MeshCollider meshCollider = null; if (enableMeshCollider) { meshCollider = chunkObject.AddComponent <MeshCollider>(); meshCollider.sharedMesh = meshFilter.sharedMesh; } chunk = new SDMeshChunk { coordinates = chunkCoords, blocks = new Dictionary <Vector3Int, SDMeshBlock>(), gameObject = chunkObject, meshFilter = meshFilter, meshRenderer = meshRenderer, meshCollider = meshCollider, meshVersion = meshVersion }; chunks.Add(chunkCoords, chunk); } return(chunk); }
void UpdateMesh(int newVersion, int blockBufferSize, int vertexBufferSize, int faceBufferSize) { meshVersion = newVersion; int[] blockArray = new int[blockBufferSize]; float[] vertexArray = new float[vertexBufferSize]; int[] faceArray = new int[faceBufferSize]; unsafe { fixed(int *blockBufferPtr = &blockArray[0], faceBufferPtr = &faceArray[0]) { fixed(float *vertexBufferPtr = &vertexArray[0]) { fullBlocks = SDPlugin.SixDegreesSDK_GetMeshBlocks(blockBufferPtr, vertexBufferPtr, faceBufferPtr, blockBufferSize, vertexBufferSize, faceBufferSize); } } } bool gotAllBlocks = (fullBlocks == blockBufferSize / 6); if (fullBlocks < 0) { Debug.Log("Error calling SixDegreesSDK_GetMeshBlocks(), will not update the mesh."); return; } else if (fullBlocks == 0) { Debug.Log("SixDegreesSDK_GetMeshBlocks() gave us an empty mesh, will not update."); return; } else if (!gotAllBlocks) { Debug.Log("SixDegreesSDK_GetMeshBlocks() returned " + fullBlocks + " full blocks, expected " + (blockBufferSize / 5)); } int firstVertex = 0; int firstTriangle = 0; HashSet <Vector3Int> chunksToUpdate = new HashSet <Vector3Int>(); HashSet <Vector3Int> meshBlocks = new HashSet <Vector3Int>(); // Update all the full blocks returned by the API int fullBlockSize = fullBlocks * 6; for (int b = 0; b + 5 < fullBlockSize; b += 6) { Vector3Int blockCoords = new Vector3Int(blockArray[b], blockArray[b + 1], blockArray[b + 2]); Vector3Int chunkCoords = GetChunkCoords(blockCoords); int vertexCount = blockArray[b + 3]; int triangleCount = blockArray[b + 4]; int blockVersion = blockArray[b + 5]; meshBlocks.Add(blockCoords); if (!IsChunkTooFar(chunkCoords)) { SDMeshChunk chunk = GetOrCreateChunk(chunkCoords); SDMeshBlock block = GetOrCreateBlock(chunk, blockCoords); // Update block if it is outdated if (block.version < blockVersion) { chunksToUpdate.Add(chunkCoords); block.version = blockVersion; block.meshVersion = meshVersion; block.vertices.Clear(); block.normals.Clear(); block.triangles.Clear(); // copy vertices int fullVertices = 0; int lastBlockVertex = Mathf.Min(vertexBufferSize, (firstVertex + vertexCount) * 6); for (int va = firstVertex * 6; va + 5 < lastBlockVertex; va += 6) { block.vertices.Add(new Vector3(vertexArray[va], vertexArray[va + 1], vertexArray[va + 2])); block.normals.Add(new Vector3(vertexArray[va + 3], vertexArray[va + 4], vertexArray[va + 5])); fullVertices++; } if (fullVertices != vertexCount) { Debug.Log("Got only " + fullVertices + " vertices out of " + vertexCount); } // copy faces int fullTriangles = 0; int lastBlockTriangle = Mathf.Min(faceBufferSize, (firstTriangle + triangleCount) * 3); for (int fa = firstTriangle * 3; fa + 2 < lastBlockTriangle; fa += 3) { block.triangles.Add(new Vector3Int(faceArray[fa] - firstVertex, faceArray[fa + 1] - firstVertex, faceArray[fa + 2] - firstVertex)); fullTriangles++; } if (fullTriangles != triangleCount) { Debug.Log("Got only " + fullTriangles + " triangles out of " + triangleCount); } } } firstVertex += vertexCount; firstTriangle += triangleCount; } // Clean up missing blocks only if we received all the expected full blocks if (gotAllBlocks) { foreach (SDMeshChunk chunk in chunks.Values) { HashSet <Vector3Int> blocksToRemove = new HashSet <Vector3Int>(chunk.blocks.Keys); blocksToRemove.ExceptWith(meshBlocks); foreach (Vector3Int block in blocksToRemove) { chunk.blocks.Remove(block); } if (blocksToRemove.Count > 0) { chunksToUpdate.Add(chunk.coordinates); } } } // Update chunks with updated blocks UpdateChunks(chunksToUpdate); // Clean up far chunks if (destroyFarChunks) { List <Vector3Int> allChunks = new List <Vector3Int>(chunks.Keys); List <Vector3Int> chunksToDelete = allChunks.FindAll((Vector3Int chunkCoords) => IsChunkTooFar(chunkCoords)); DeleteChunks(chunksToDelete); } }