Beispiel #1
0
        public override _16x256x16VoxChunk GenerateVoxChunk(int uniqueID)
        {
            int[] position = _16x256x16VoxChunk.DefaultDecoderFromUniqueID2StPosition(uniqueID);
            offset = new Vector2(position[0], position[1]);
            GenNodes();

            byte[]             data  = new byte[_16x256x16VoxChunk.Count];
            _16x256x16VoxChunk chunk = new _16x256x16VoxChunk(uniqueID, data);

            for (int x = 0; x < _16x256x16VoxChunk.Width; x++)
            {
                for (int z = 0; z < _16x256x16VoxChunk.Length; z++)
                {
                    TNode node   = nodes[x, z];
                    int   height = (int)node.elevation;
                    byte  type   = (byte)(node.ttype);

                    for (int y = 0; y < height; y++)
                    {
                        chunk.SetVoxel(x, y, z, type);
                    }
                }
            }

            return(chunk);
        }
Beispiel #2
0
        // Mesh chunk
        private GameObject CreateMeshObj(_16x256x16VoxChunk chunk, MeshingMaterial meshingMaterial, MeshingMaterial coliderMeshingMaterial)
        {
            Mesh mesh        = meshingMaterial.ToMesh();
            Mesh coliderMesh = coliderMeshingMaterial.ToMesh();

            return(CreateMeshObj(chunk, mesh, coliderMesh));
        }
Beispiel #3
0
        // 获得射线交点所在Voxel的世界坐标信息
        public Vector3 SetSelectedVoxel(RaycastHit hit)
        {
            if (hit.point.x < 0 || hit.point.y < 0 || hit.point.z < 0)
            {
                return(new Vector3(0, 0, 0));
            }

            float acc = 0.00001f;

            int[] delta = new int[] { 0, 0, 0 };
            int[] start = new int[] { 0, 0, 0 };
            int[] local = new int[] { 0, 0, 0 };

            if ((hit.point.x % 1) < acc)
            {
                delta[0] = 1;
            }
            else if ((hit.point.y % 1) < acc)
            {
                delta[1] = 1;
            }
            else if ((hit.point.z % 1) < acc)
            {
                delta[2] = 1;
            }

            start[0] = (int)hit.point.x;
            start[1] = (int)hit.point.y;
            start[2] = (int)hit.point.z;

            int uniqueID = GetUniqueIDByVoxelWorldPosition(start[0], start[2]);
            var chunk    = GetChunkByUniqueID(uniqueID);

            if (chunk == null)
            {
                selectChunk         = null;
                selectVoxelPosition = new Vector3(0, 0, 0);
                return(selectVoxelPosition);
            }

            local[0] = start[0] % _16x256x16VoxChunk.Width;
            local[1] = start[1] % _16x256x16VoxChunk.Height;
            local[2] = start[2] % _16x256x16VoxChunk.Length;

            byte voxType = chunk.GetVoxel(local[0], local[1], local[2]);

            if (voxType != _16x256x16VoxChunk.EmptyType)
            {
                selectChunk         = chunk;
                selectVoxelPosition = new Vector3(start[0], start[1], start[2]);
            }
            else
            {
                selectChunk         = GetChunkByUniqueID(GetUniqueIDByVoxelWorldPosition(start[0] - delta[0], start[2] - delta[2]));
                selectVoxelPosition = new Vector3(start[0] - delta[0], start[1] - delta[1], start[2] - delta[2]);
            }

            return(selectVoxelPosition);
        }
        public void SetChunk(_16x256x16VoxChunk chunk)
        {
            if (!ExistWT())
            {
                OpenWT();
            }

            wt.WriteChunk(chunk);
        }
        public void SetChunk(int index, _16x256x16VoxChunk chunk)
        {
            if (index < 0 || index >= MaxChunkSize)
            {
                return;
            }

            chunkData[index] = chunk;
        }
Beispiel #6
0
 // 查找在Terrain中是否存在该chunk
 private bool HasTheChunk(_16x256x16VoxChunk chunk)
 {
     foreach (var lchunk in chunksInLastArea)
     {
         if (lchunk == chunk)
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #7
0
        // 更新指定Chunk
        private void UpdateChunk(_16x256x16VoxChunk chunk)
        {
            if (!HasTheChunk(chunk))
            {
                return;
            }

            MeshingMaterial meshMat        = VoxTerrainMeshingTool.GreedyMeshing(chunk);
            MeshingMaterial coliderMeshMat = VoxTerrainMeshingTool.GreedyMeshing_ColiderMesh(chunk);
            Mesh            mesh           = meshMat.ToMesh();
            Mesh            coliderMesh    = coliderMeshMat.ToMesh();

            var oldMeshObj = GetMeshObj(chunk.UniqueID);

            DestroyImmediate(oldMeshObj);
            CreateMeshObj(chunk, mesh, coliderMesh);
        }
        public override _16x256x16VoxChunk GenerateVoxChunk(int uniqueID)
        {
            byte[]             voxData = new byte[_16x256x16VoxChunk.Count];
            _16x256x16VoxChunk res     = new _16x256x16VoxChunk(uniqueID, voxData);

            for (int x = 0; x < _16x256x16VoxChunk.Width; x++)
            {
                for (int z = 0; z < _16x256x16VoxChunk.Length; z++)
                {
                    int plainHeight = (int)(PlainSample(uniqueID, x, z) + 0.5f);

                    for (int y = 0; y < plainHeight; y++)
                    {
                        res.SetVoxel(x, y, z, 0x02);
                    }
                }
            }
            return(res);
        }
Beispiel #9
0
        public override _16x256x16VoxChunk GenerateVoxChunk(int uniqueID)
        {
            byte[]             voxData = new byte[_16x256x16VoxChunk.Count];
            _16x256x16VoxChunk result  = new _16x256x16VoxChunk(uniqueID, voxData);

            offset = _16x256x16VoxChunk.DefaultDecoderFromUniqueID2StPosition(uniqueID);

            for (int lx = 0; lx < _16x256x16VoxChunk.Width; lx++)
            {
                for (int lz = 0; lz < _16x256x16VoxChunk.Length; lz++)
                {
                    int groundHeight     = GenBaseGround(lx, lz);
                    int SnowLayerHeight  = GenSnowLayer(lx, lz);
                    int GlassLayerHeight = GenGlassLayer(lx, lz);

                    for (int h = 0; h < groundHeight; h++)
                    {
                        result.SetVoxel(lx, h, lz, (byte)VoxelType.Ground);
                    }

                    int snowSubGround = SnowLayerHeight - groundHeight;
                    if (snowSubGround > 0 && snowSubGround < snowDepth)
                    {
                        for (int h = SnowLayerHeight; h >= groundHeight; h--)
                        {
                            result.SetVoxel(lx, h, lz, (byte)VoxelType.Snow);
                        }
                    }

                    int glassSubGround = GlassLayerHeight - groundHeight;
                    if (glassSubGround > 0 && glassSubGround < glassDepth)
                    {
                        for (int h = glassSubGround; h >= groundHeight; h--)
                        {
                            result.SetVoxel(lx, h, lz, (byte)VoxelType.Glass);
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #10
0
        // Write chunk to WT
        public void WriteChunk(_16x256x16VoxChunk chunk)
        {
            if (SearchChunk(chunk.UniqueID))
            {
                int index;
                uniqueID2Index.TryGetValue(chunk.UniqueID, out index);

                bw.BaseStream.Seek(Version.Length + index * ChunkLength + UniqueIDLength, SeekOrigin.Begin);

                bw.Write(chunk.VoxData);
            }
            else
            {
                int index = uniqueID2Index.Count;
                uniqueID2Index.Add(chunk.UniqueID, index);

                bw.BaseStream.Seek(0, SeekOrigin.End);

                bw.Write(chunk.UniqueID);
                bw.Write(chunk.VoxData);
            }
        }
Beispiel #11
0
        private GameObject CreateMeshObj(_16x256x16VoxChunk chunk, Mesh mesh, Mesh coliderMesh)
        {
            GameObject meshObj = new GameObject(chunk.UniqueID.ToString());

            meshObj.transform.parent = transform;
            meshObj.AddComponent <MeshRenderer>();
            meshObj.AddComponent <MeshFilter>();

            meshObj.GetComponent <MeshRenderer>().material = voxMaterial;
            meshObj.GetComponent <MeshFilter>().mesh       = mesh;

            // Set Position
            meshObj.transform.position   = new Vector3(_16x256x16VoxChunk.Width * chunk.Position[0] * scale, 0, _16x256x16VoxChunk.Length * chunk.Position[1] * scale);
            meshObj.transform.localScale = new Vector3(scale, scale, scale);

            var colider = meshObj.AddComponent <MeshCollider>();

            colider.sharedMesh = coliderMesh;

            meshObj.layer = LayerMask.NameToLayer("VoxTerrain");

            return(meshObj);
        }
Beispiel #12
0
        // 区域更新:加载未加载区域内的chunks
        private IEnumerator LoadChunks()
        {
            List <_16x256x16VoxChunk> loadChunks = new List <_16x256x16VoxChunk>();

            foreach (var uniqueID in uniqueIDsInArea)
            {
                bool equal = false;

                foreach (var chunk in chunksInLastArea)
                {
                    if (uniqueID == chunk.UniqueID)
                    {
                        equal = true;
                    }
                }

                if (!equal) // 若uniqueID不在老区域内,则被加载
                {
                    _16x256x16VoxChunk loadChunk = wtAsset.GetChunk(uniqueID);
                    if (loadChunk == null)   // 若在wt文件中不存在,则重新创建一个
                    {
                        loadChunk = rule.GenerateVoxChunk(uniqueID);
                    }

                    loadChunks.Add(loadChunk);
                }
            }

            foreach (var loadChunk in loadChunks)
            {
                chunksInLastArea.Add(loadChunk);
            }

            if (meshingThread == null)
            {
                meshingThread = new MeshingThread();
            }

            meshingThread.MeshingChunk = loadChunks;
            meshingThread.Run();

            int cur = 0;

            while (cur < meshingThread.MeshingChunk.Count)
            {
                MeshingMaterial meshingMaterial        = meshingThread.MeshingMaterials[cur];
                MeshingMaterial coliderMeshingMaterial = meshingThread.ColiderMeshMaterials[cur];

                if (meshingMaterial == null || coliderMeshingMaterial == null)
                {
                    yield return(null);
                }
                else
                {
                    CreateMeshObj(meshingThread.MeshingChunk[cur], meshingMaterial, coliderMeshingMaterial);
                    cur++;
                }
            }

            IsMeshing = false;
        }
Beispiel #13
0
        public static MeshingMaterial GreedyMeshing_ColiderMesh(_16x256x16VoxChunk voxChunk)
        {
            if (voxChunk == null)
            {
                return(null);
            }

            int[]          size      = { _16x256x16VoxChunk.Width, _16x256x16VoxChunk.Height, _16x256x16VoxChunk.Length };
            int[]          position  = { 0, 0, 0 };
            List <Vector3> vertices  = new List <Vector3>();
            List <int>     triangles = new List <int>();

            // 遍历扫描三个维度
            for (int d = 0; d < 3; d++)
            {
                // 当前维度的二维截面的u,v坐标轴所代表的其余二个维度
                int u = (d + 1) % 3, v = (d + 2) % 3;
                // 用于辅助计算
                int[] q = { 0, 0, 0 }; q[d] = 1;
                // 用于记录当前维度截面的数据
                byte[] mask = new byte[size[u] * size[v]];
                // 用于记录Quad的方向
                int[] direction = new int[size[u] * size[v]];

                // 遍历该维度每个深度的截面数据
                for (position[d] = -1; position[d] < size[d];)
                {
                    // 求得截面数据
                    for (position[v] = 0; position[v] < size[v]; position[v]++)
                    {
                        for (position[u] = 0; position[u] < size[u]; position[u]++)
                        {
                            // 前后两层体素对比,使用异或规则(T = True,F = False),计算获得可见面
                            // Front  ||     Back
                            //   T    ||   T  -->  F
                            //   T    ||   F  -->  T
                            //   F    ||   T  -->  T
                            //   F    ||   F  -->  F
                            byte frontVoxelType = voxChunk.GetVoxel(position[0], position[1], position[2]);
                            byte backVoxelType  = voxChunk.GetVoxel(position[0] + q[0], position[1] + q[1], position[2] + q[2]);

                            bool frontExist = frontVoxelType != emptyVoxelType;
                            bool backExist  = backVoxelType != emptyVoxelType;
                            // 计算当前Voxel是否可显示
                            bool canDisplay = frontExist ^ backExist;

                            // 计算当前截面位置的类型
                            int index = position[v] * size[u] + position[u];
                            if (canDisplay)
                            {
                                //if (frontExist) mask[index] = frontVoxelType;
                                //else mask[index] = backVoxelType;
                                mask[index] = 0x01;
                            }
                            else
                            {
                                mask[index] = emptyVoxelType;
                            }

                            if (!canDisplay)
                            {
                                direction[index] = 0;
                            }
                            else
                            {
                                direction[index] = frontExist ? 1 : -1;
                            }
                        }
                    }

                    // 累加深度
                    position[d]++;

                    // 简化截面
                    for (position[v] = 0; position[v] < size[v]; position[v]++)
                    {
                        for (position[u] = 0; position[u] < size[u];)
                        {
                            int stIndex = position[v] * size[u] + position[u];

                            if (mask[stIndex] == emptyVoxelType)
                            {
                                position[u]++;
                                continue;
                            }

                            // 当前起始面朝向
                            int stDirection = direction[stIndex];
                            // 当前体素类型
                            byte curVoxelType = mask[stIndex];

                            // 计算最大宽度
                            int width = 1;
                            while (true)
                            {
                                if (width + position[u] >= size[u])
                                {
                                    break;
                                }
                                if (mask[stIndex + width] != curVoxelType || direction[stIndex + width] != stDirection)
                                {
                                    break;
                                }

                                width++;
                            }
                            // 计算最大高度
                            int  height = 1;
                            bool flag   = true;
                            while (flag)
                            {
                                if (height + position[v] >= size[v])
                                {
                                    break;
                                }
                                int temp = (height + position[v]) * size[u];
                                for (int k = 0; k < width; k++)
                                {
                                    int index = position[u] + k + temp;
                                    if (mask[index] != curVoxelType || direction[index] != stDirection)
                                    {
                                        flag = false;
                                        break;
                                    }
                                }

                                if (flag)
                                {
                                    height++;
                                }
                            }

                            // 记录结果
                            int[] du = { 0, 0, 0 }, dv = { 0, 0, 0 };
                            du[u] = width; dv[v] = height;

                            stIndex = vertices.Count;

                            vertices.Add(new Vector3(position[0], position[1], position[2]));
                            vertices.Add(new Vector3(position[0] + du[0], position[1] + du[1], position[2] + du[2]));
                            vertices.Add(new Vector3(position[0] + du[0] + dv[0], position[1] + du[1] + dv[1], position[2] + du[2] + dv[2]));
                            vertices.Add(new Vector3(position[0] + dv[0], position[1] + dv[1], position[2] + dv[2]));

                            float sU = (uMask & curVoxelType) * scale;
                            float sV = ((uMask & curVoxelType) >> 4) * scale;

                            if (stDirection == 1)
                            {
                                triangles.Add(stIndex);
                                triangles.Add(stIndex + 1);
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 3);
                                triangles.Add(stIndex);
                            }
                            else if (stDirection == -1)
                            {
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 1);
                                triangles.Add(stIndex);
                                triangles.Add(stIndex);
                                triangles.Add(stIndex + 3);
                                triangles.Add(stIndex + 2);
                            }

                            // 在截面涂黑已记录结果
                            for (int j = 0; j < height; j++)
                            {
                                int temp = (j + position[v]) * size[u];
                                for (int i = 0; i < width; i++)
                                {
                                    mask[temp + position[u] + i] = emptyVoxelType;
                                }
                            }
                            // 累加
                            position[u] += width;
                        }
                    }
                }
            }

            return(new MeshingMaterial(vertices, triangles, null));
        }
Beispiel #14
0
        public static void GreedyMeshing(_16x256x16VoxChunk voxChunk, out Mesh mesh)
        {
            if (voxChunk == null)
            {
                mesh = new Mesh();
                return;
            }

            int[]          size      = { _16x256x16VoxChunk.Width, _16x256x16VoxChunk.Height, _16x256x16VoxChunk.Length };
            int[]          position  = { 0, 0, 0 };
            List <Vector3> vertices  = new List <Vector3>();
            List <int>     triangles = new List <int>();
            List <Vector2> uvs       = new List <Vector2>();

            // 遍历扫描三个维度
            for (int d = 0; d < 3; d++)
            {
                // 当前维度的二维截面的u,v坐标轴所代表的其余二个维度
                int u = (d + 1) % 3, v = (d + 2) % 3;
                // 用于辅助计算
                int[] q = { 0, 0, 0 }; q[d] = 1;
                // 用于记录当前维度截面的数据
                byte[] mask = new byte[size[u] * size[v]];
                // 用于记录Quad的方向
                int[] direction = new int[size[u] * size[v]];

                // 遍历该维度每个深度的截面数据
                for (position[d] = -1; position[d] < size[d];)
                {
                    // 求得截面数据
                    for (position[v] = 0; position[v] < size[v]; position[v]++)
                    {
                        for (position[u] = 0; position[u] < size[u]; position[u]++)
                        {
                            // 前后两层体素对比,使用异或规则(T = True,F = False),计算获得可见面
                            // Front  ||     Back
                            //   T    ||   T  -->  F
                            //   T    ||   F  -->  T
                            //   F    ||   T  -->  T
                            //   F    ||   F  -->  F
                            byte frontVoxelType = voxChunk.GetVoxel(position[0], position[1], position[2]);
                            byte backVoxelType  = voxChunk.GetVoxel(position[0] + q[0], position[1] + q[1], position[2] + q[2]);

                            bool frontExist = frontVoxelType != emptyVoxelType;
                            bool backExist  = backVoxelType != emptyVoxelType;
                            // 计算当前Voxel是否可显示
                            bool canDisplay = frontExist ^ backExist;

                            // 计算当前截面位置的类型
                            int index = position[v] * size[u] + position[u];
                            if (canDisplay)
                            {
                                if (frontExist)
                                {
                                    mask[index] = frontVoxelType;
                                }
                                else
                                {
                                    mask[index] = backVoxelType;
                                }
                            }
                            else
                            {
                                mask[index] = emptyVoxelType;
                            }

                            if (!canDisplay)
                            {
                                direction[index] = 0;
                            }
                            else
                            {
                                direction[index] = frontExist ? 1 : -1;
                            }
                        }
                    }

                    // 累加深度
                    position[d]++;

                    // 简化截面
                    for (position[v] = 0; position[v] < size[v]; position[v]++)
                    {
                        for (position[u] = 0; position[u] < size[u];)
                        {
                            int stIndex = position[v] * size[u] + position[u];

                            if (mask[stIndex] == emptyVoxelType)
                            {
                                position[u]++;
                                continue;
                            }

                            // 当前起始面朝向
                            int stDirection = direction[stIndex];
                            // 当前体素类型
                            byte curVoxelType = mask[stIndex];

                            // 计算最大宽度
                            int width = 1;
                            while (true)
                            {
                                if (width + position[u] >= size[u])
                                {
                                    break;
                                }
                                if (mask[stIndex + width] != curVoxelType || direction[stIndex + width] != stDirection)
                                {
                                    break;
                                }

                                width++;
                            }
                            // 计算最大高度
                            int  height = 1;
                            bool flag   = true;
                            while (flag)
                            {
                                if (height + position[v] >= size[v])
                                {
                                    break;
                                }
                                int temp = (height + position[v]) * size[u];
                                for (int k = 0; k < width; k++)
                                {
                                    int index = position[u] + k + temp;
                                    if (mask[index] != curVoxelType || direction[index] != stDirection)
                                    {
                                        flag = false;
                                        break;
                                    }
                                }

                                if (flag)
                                {
                                    height++;
                                }
                            }

                            // 记录结果
                            int[] du = { 0, 0, 0 }, dv = { 0, 0, 0 };
                            du[u] = width; dv[v] = height;

                            stIndex = vertices.Count;

                            vertices.Add(new Vector3(position[0], position[1], position[2]));
                            vertices.Add(new Vector3(position[0] + du[0], position[1] + du[1], position[2] + du[2]));
                            vertices.Add(new Vector3(position[0] + du[0] + dv[0], position[1] + du[1] + dv[1], position[2] + du[2] + dv[2]));
                            vertices.Add(new Vector3(position[0] + dv[0], position[1] + dv[1], position[2] + dv[2]));

                            float sU = (uMask & curVoxelType) * scale;
                            float sV = ((uMask & curVoxelType) >> 4) * scale;

                            uvs.Add(new Vector2(sU, sV));
                            uvs.Add(new Vector2(sU + scale, sV));
                            uvs.Add(new Vector2(sU + scale, sV + scale));
                            uvs.Add(new Vector2(sU, sV + scale));

                            if (stDirection == 1)
                            {
                                triangles.Add(stIndex);
                                triangles.Add(stIndex + 1);
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 3);
                                triangles.Add(stIndex);
                            }
                            else if (stDirection == -1)
                            {
                                triangles.Add(stIndex + 2);
                                triangles.Add(stIndex + 1);
                                triangles.Add(stIndex);
                                triangles.Add(stIndex);
                                triangles.Add(stIndex + 3);
                                triangles.Add(stIndex + 2);
                            }

                            // 在截面涂黑已记录结果
                            for (int j = 0; j < height; j++)
                            {
                                int temp = (j + position[v]) * size[u];
                                for (int i = 0; i < width; i++)
                                {
                                    mask[temp + position[u] + i] = emptyVoxelType;
                                }
                            }
                            // 累加
                            position[u] += width;
                        }
                    }
                }
            }

            mesh = new Mesh();
            mesh.subMeshCount = vertices.Count / maxVerticeIndexes + 1;
            mesh.SetVertices(vertices);
            for (int i = 0; i < mesh.subMeshCount; i++)
            {
                List <int> range;
                int        sub = -i * maxVerticeIndexes;
                if (i + 1 == mesh.subMeshCount)
                {
                    range = triangles.GetRange(i * maxTrianglesIndexes, triangles.Count % maxTrianglesIndexes);
                }
                else
                {
                    range = triangles.GetRange(i * maxTrianglesIndexes, maxTrianglesIndexes);
                }
                for (int j = 0; j < range.Count; j++)
                {
                    range[j] += sub;
                }
                mesh.SetTriangles(range, i, true, i * maxVerticeIndexes);
            }
            mesh.uv = uvs.ToArray();
            mesh.RecalculateNormals();
        }