Esempio n. 1
0
        void DeleteChunk(Vector3Int chunkToDelete)
        {
            SDMeshChunk chunk = null;

            if (chunks.TryGetValue(chunkToDelete, out chunk))
            {
                Destroy(chunk.meshFilter.sharedMesh);
                Destroy(chunk.gameObject);
                chunks.Remove(chunkToDelete);
            }
        }
Esempio n. 2
0
        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);
                }
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
            }
        }