static void BuildRock(ref FastNoise_t noise, int x, int y, int z, PinnedChunkData_t chunk)
            {
                int xMinus = x - y % 3;
                int xPlus  = x + (x + y + z) % 3;
                int yMinus = y - x % 3;
                int yPlus  = y + (y + z) % 3;
                int zMinus = z - (z + x) % 3;
                int zPlus  = z + (x + y) % 3;

                for (int i = xMinus; i < xPlus; i++)
                {
                    for (int j = yMinus; j < yPlus; j++)
                    {
                        for (int k = zMinus; k < zPlus; k++)
                        {
                            if (i >= 0 && i < VOXEL_CHUNK_SIZE_XZ && j >= 0 && j < VOXEL_CHUNK_SIZE_Y && k >= 0 && k < VOXEL_CHUNK_SIZE_XZ)
                            {
                                var ofs = i + (k * VOXEL_CHUNK_SIZE_XZ) + (j * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                chunk.flags         |= EChunkFlags.SOLID;
                                chunk.voxeldata[ofs] = EVoxelBlockType.Rock.WithFlags(EVoxelBlockFlags.FullVoxel);
                            }
                        }
                    }
                }
            }
 public JobHandle ScheduleChunkGenerationJob(WorldChunkPos_t cpos, PinnedChunkData_t chunk)
 {
     return(new ProcWorldStreaming_V1_Job_t()
     {
         cpos = cpos,
         chunk = chunk
     }.Schedule());
 }
            public void Execute()
            {
                chunk = GenerateVoxels(cpos, chunk);

                unsafe {
                    chunk.pinnedDecorationCount[0] = chunk.decorationCount;
                    chunk.pinnedFlags[0]           = chunk.flags;
                }
            }
            static PinnedChunkData_t GenerateVoxelsSinWave(WorldChunkPos_t cpos, PinnedChunkData_t chunk)
            {
                var Y_OFS = (VOXEL_CHUNK_SIZE_Y * MaxVoxelChunkLine(VOXEL_CHUNK_VIS_MAX_Y)) / 8;

                bool solid = false;
                bool air   = false;

                chunk.flags = EChunkFlags.LAYER_DEFAULT;

                WorldVoxelPos_t pos = ChunkToWorld(cpos);
                Vector3         v3  = WorldToVec3(pos);

                for (int x = 0; x < VOXEL_CHUNK_SIZE_XZ; ++x)
                {
                    for (int z = 0; z < VOXEL_CHUNK_SIZE_XZ; ++z)
                    {
                        var cs = Mathf.Cos((v3.x + x) / 64);
                        var ss = Mathf.Sin((v3.z + z) / 64);

                        for (int y = 0; y < VOXEL_CHUNK_SIZE_Y; ++y)
                        {
                            var ofs  = x + (z * VOXEL_CHUNK_SIZE_XZ) + (y * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                            var ypos = v3.y + y;

                            if (ypos < ((cs + ss) * (Y_OFS / 2)))
                            {
                                chunk.voxeldata[ofs] = EVoxelBlockType.Dirt;
                                solid = true;
                            }
                            else
                            {
                                air = true;
                                chunk.voxeldata[ofs] = EVoxelBlockType.Air;
                            }
                        }
                    }
                }

                if (solid)
                {
                    chunk.flags |= EChunkFlags.SOLID;
                }

                if (air)
                {
                    chunk.flags |= EChunkFlags.AIR;
                }

                chunk.flags |= EChunkFlags.LAYER_DEFAULT;

                return(chunk);
            }
Exemple #5
0
        static unsafe bool IsSolidXZPlane(PinnedChunkData_t chunk)
        {
            byte *solidFlags = stackalloc byte[VOXELS_PER_CHUNK_XZ];

            for (int i = 0; i < VOXELS_PER_CHUNK_XZ; ++i)
            {
                solidFlags[i] = 0;
            }

            int numSolid = 0;
            int ofs      = 0;

            for (int y = 0; y < VOXEL_CHUNK_SIZE_Y; ++y)
            {
                for (int z = 0; z < VOXEL_CHUNK_SIZE_XZ; ++z)
                {
                    int ofsxz = z * VOXEL_CHUNK_SIZE_XZ;

                    for (int x = 0; x < VOXEL_CHUNK_SIZE_XZ; ++x)
                    {
                        if (solidFlags[ofsxz] == 0)
                        {
                            var block = chunk.voxeldata[ofs].type;
                            if (block != EVoxelBlockType.Air)
                            {
                                solidFlags[ofsxz] = 1;
                                ++numSolid;
                                if (numSolid == VOXELS_PER_CHUNK_XZ)
                                {
                                    return(true);
                                }
                            }
                        }

                        ++ofsxz;
                        ++ofs;
                    }
                }
            }

            return(false);
        }
 protected override JobHandle CreateGenVoxelsJob(WorldChunkPos_t pos, PinnedChunkData_t chunk)
 {
     return(_gameMode.worldStreaming.ScheduleChunkGenerationJob(pos, chunk));
 }
            static PinnedChunkData_t GenerateVoxels(WorldChunkPos_t cpos, PinnedChunkData_t chunk)
            {
                FastNoise_t noise = FastNoise_t.New();

                chunk.flags = EChunkFlags.ALL_LAYERS_FLAGS;
                bool solid     = false;
                bool air       = true;
                bool fullVoxel = false;

                var wpos = ChunkToWorld(cpos);
                var v3   = WorldToVec3(wpos);

                for (int x = 0; x < VOXEL_CHUNK_SIZE_XZ; ++x)
                {
                    for (int z = 0; z < VOXEL_CHUNK_SIZE_XZ; ++z)
                    {
                        var xpos = (int)v3.x + x;
                        var zpos = (int)v3.z + z;

                        bool  isEmptyAtBottom   = false;
                        var   lowerGroundHeight = GetLowerGroundHeight(ref noise, xpos, zpos);
                        var   upperGroundHeight = GetUpperGroundHeight(ref noise, xpos, zpos, lowerGroundHeight);
                        float waterDepth        = CalculateRiver(ref noise, xpos, zpos, lowerGroundHeight, 0, 0, ref upperGroundHeight);
                        bool  isRoad            = CalculateRoad(ref noise, xpos, zpos, lowerGroundHeight, 0, 0, ref upperGroundHeight);

                        for (int y = 0; y < VOXEL_CHUNK_SIZE_Y; ++y)
                        {
                            var ofs  = x + (z * VOXEL_CHUNK_SIZE_XZ) + (y * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                            var ypos = v3.y + y;

                            EVoxelBlockType bt;
                            bool            isCave = false;
                            if (ypos > lowerGroundHeight && ypos <= upperGroundHeight)
                            {
                                // Let's see about some caves er valleys!
                                float caveNoise = GetPerlinValue(ref noise, xpos, ypos, zpos, 0.001f) * (0.015f * ypos) + 0.1f;
                                caveNoise += GetPerlinValue(ref noise, xpos, ypos, zpos, 0.01f) * 0.06f + 0.1f;
                                caveNoise += GetPerlinValue(ref noise, xpos, ypos, zpos, 0.02f) * 0.02f + 0.01f;
                                isCave     = caveNoise > GetPerlinNormal(ref noise, xpos, ypos, zpos, 0.01f) * 0.3f + 0.4f;
                            }

                            if (ypos <= upperGroundHeight && !isCave)
                            {
                                bt = GetBlockType(ref noise, xpos, (int)ypos, zpos, (int)upperGroundHeight, isRoad, false, out fullVoxel);
                            }
                            else
                            {
                                if (ypos < waterLevel)
                                {
                                    float temperature = GetTemperature(ref noise, (int)xpos, (int)ypos, zpos);
                                    if (IsFrozen(temperature, GetHumidity(ref noise, xpos, zpos)))
                                    {
                                        bt = EVoxelBlockType.Ice;
                                    }
                                    else
                                    {
                                        bt = EVoxelBlockType.Water;
                                    }
                                }
                                else
                                {
                                    bt = EVoxelBlockType.Air;
                                }
                            }
                            if (bt == EVoxelBlockType.Air)
                            {
                                if (y == 0)
                                {
                                    isEmptyAtBottom = true;
                                }
                                if (waterDepth > 0 && !isEmptyAtBottom)
                                {
                                    float temperature = GetTemperature(ref noise, xpos, (int)ypos, zpos);
                                    if (IsFrozen(temperature, GetHumidity(ref noise, xpos, zpos)))
                                    {
                                        bt = EVoxelBlockType.Ice;
                                    }
                                    else
                                    {
                                        bt = EVoxelBlockType.Water;
                                    }
                                    waterDepth--;
                                    solid = true;
                                }
                                else
                                {
                                    air = true;
                                }
                            }
                            else
                            {
                                solid = true;
                            }

                            if (fullVoxel)
                            {
                                chunk.voxeldata[ofs] = bt.WithFlags(EVoxelBlockFlags.FullVoxel);
                            }
                            else
                            {
                                chunk.voxeldata[ofs] = bt;
                            }
                        }
                    }
                }

                if (solid)
                {
                    chunk.flags |= EChunkFlags.SOLID;
                }
                if (air)
                {
                    chunk.flags |= EChunkFlags.AIR;
                }

                if (solid && air)
                {
                    for (int x = 0; x < VOXEL_CHUNK_SIZE_XZ; ++x)
                    {
                        for (int z = 0; z < VOXEL_CHUNK_SIZE_XZ; ++z)
                        {
                            var xpos = (int)v3.x + x;
                            var zpos = (int)v3.z + z;
                            for (int y = VOXEL_CHUNK_SIZE_Y - 1; y >= 0; --y)
                            {
                                var ofs  = x + (z * VOXEL_CHUNK_SIZE_XZ) + (y * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                var ypos = (int)v3.y + y;
                                var bt   = chunk.voxeldata[ofs].type;
                                if (bt != EVoxelBlockType.Air)
                                {
                                    if (bt == EVoxelBlockType.Water || bt == EVoxelBlockType.Leaves || bt == EVoxelBlockType.Needles || bt == EVoxelBlockType.Wood)
                                    {
                                        break;
                                    }

                                    float rock       = GetRock(ref noise, xpos, ypos, zpos);
                                    float rockCutoff = 0.35f;
                                    if (rock > rockCutoff)
                                    {
                                        float rockLimit = (1.0f - Mathf.Pow((rock - rockCutoff) / (1.0f - rockCutoff), 0.5f)) * 100 + 1;
                                        if (GetWhiteNoise(ref noise, xpos, ypos, zpos) < 1.0f / rockLimit)
                                        {
                                            BuildRock(ref noise, x, y, z, chunk);
                                        }
                                    }

                                    if (bt == EVoxelBlockType.Ice || bt == EVoxelBlockType.Sand)
                                    {
                                        break;
                                    }


                                    float humidity    = GetHumidity(ref noise, xpos, zpos);
                                    float forestPower = (1.0f - (GetPerlinNormal(ref noise, xpos, zpos, NoiseFloatScale._01) * GetPerlinNormal(ref noise, xpos + 64325, zpos + 6543, NoiseFloatScale._005))) * Mathf.Pow(humidity, 2) * (1.0f - Mathf.Pow(rock, 4));
                                    float cutoff      = 0.05f;
                                    if (forestPower > cutoff)
                                    {
                                        float forestLimit = Mathf.Pow(1.0f - (forestPower - cutoff) / (1.0f - cutoff), 8) * 100 + 4;
                                        if (GetWhiteNoise(ref noise, xpos, ypos, zpos) < 1.0f / forestLimit)
                                        {
                                            float temperature = GetTemperature(ref noise, xpos, ypos, zpos);

                                            int treeType;                                             // dead
                                            if (humidity + temperature / 100.0f + GetPerlinNormal(ref noise, xpos, zpos, NoiseFloatScale._1) * 1.5f < 1.5f)
                                            {
                                                if (temperature + 30 * GetPerlinNormal(ref noise, xpos + 422, zpos + 5357, NoiseFloatScale._1) > 60)
                                                {
                                                    treeType = 3;
                                                }
                                                else
                                                {
                                                    treeType = 2;                                                     // pine
                                                }
                                            }
                                            else if (IsFrozen(temperature, humidity))
                                            {
                                                treeType = 0;
                                            }
                                            else
                                            {
                                                treeType = 1;
                                            }
                                            BuildTree(ref noise, x, y, z, treeType, chunk);
                                            break;
                                        }
                                    }

                                    if (bt == EVoxelBlockType.Grass || bt == EVoxelBlockType.Dirt)
                                    {
                                        if (y < VOXEL_CHUNK_SIZE_Y - 1)
                                        {
                                            float flowerPower1 = 0.3f * GetPerlinNormal(ref noise, xpos, zpos, NoiseFloatScale._5)
                                                                 + 0.2f * GetPerlinNormal(ref noise, xpos + 67435, zpos + 653, NoiseFloatScale._01)
                                                                 + 0.5f * GetPerlinNormal(ref noise, xpos + 6435, zpos + 65453, NoiseFloatScale._005);
                                            float flowerPower2 = 0.4f * GetPerlinNormal(ref noise, xpos + 256, zpos + 54764, NoiseFloatScale._5)
                                                                 + 0.3f * GetPerlinNormal(ref noise, xpos + 6746435, zpos + 63, NoiseFloatScale._01)
                                                                 + 0.3f * GetPerlinNormal(ref noise, xpos + 649835, zpos + 6543, NoiseFloatScale._005);
                                            float flowerPower3 = 0.2f * GetPerlinNormal(ref noise, xpos + 7657376, zpos + 5421, NoiseFloatScale._5)
                                                                 + 0.3f * GetPerlinNormal(ref noise, xpos + 67435, zpos + 658963, NoiseFloatScale._01)
                                                                 + 0.5f * GetPerlinNormal(ref noise, xpos + 64935, zpos + 695453, NoiseFloatScale._005);
                                            float flowerPower4 = 0.3f * GetPerlinNormal(ref noise, xpos + 15, zpos + 6532, NoiseFloatScale._5)
                                                                 + 0.1f * GetPerlinNormal(ref noise, xpos + 6735, zpos + 63, NoiseFloatScale._01)
                                                                 + 0.6f * GetPerlinNormal(ref noise, xpos + 645, zpos + 6553, NoiseFloatScale._005);
                                            cutoff = 0.75f;
                                            int   flowerType  = 0;
                                            float flowerPower = 0;
                                            if (flowerPower1 > flowerPower)
                                            {
                                                flowerPower = flowerPower1;
                                                flowerType  = 0;
                                            }
                                            if (flowerPower2 > flowerPower)
                                            {
                                                flowerPower = flowerPower2;
                                                flowerType  = 1;
                                            }
                                            if (flowerPower3 > flowerPower)
                                            {
                                                flowerPower = flowerPower3;
                                                flowerType  = 2;
                                            }
                                            if (flowerPower4 > flowerPower)
                                            {
                                                flowerPower = flowerPower4;
                                                flowerType  = 3;
                                            }
                                            if (flowerPower > cutoff)
                                            {
                                                var ofs2 = x + (z * VOXEL_CHUNK_SIZE_XZ) + ((y + 1) * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                                chunk.voxeldata[ofs2] = (EVoxelBlockType)((int)EVoxelBlockType.Flowers1 + flowerType);
                                            }
                                        }
                                    }
                                    //else if (blockType == BlockType.Grass && r.Next((int)(1000 * forestPower) + 10) == 0)
                                    //{
                                    //	chunk.setBlock(x, (byte)y, z, new Block(BlockType.RedFlower));
                                    //}
                                    //else if (blockType == BlockType.Grass && r.Next((int)(50 * forestPower) + 1) == 1)
                                    //{
                                    //	chunk.setBlock(x, (byte)y, z, new Block(BlockType.LongGrass));
                                    //}
                                    break;
                                }
                            }
                        }
                    }

                    if (noise.GetWhiteNoise(cpos.cx, cpos.cy, cpos.cz) > 0.98f)
                    {
                        ConstructTower(16, 0, 16, chunk);
                    }
                }

                return(chunk);
            }
 static void BuildTree(ref FastNoise_t noise, int x, int y, int z, int treeType, PinnedChunkData_t chunk)
 {
     // Foliage
     if (treeType == 0)
     {
         // Trunk
         int height = 1 + x % 4 + y % 4 + z % 4;
         for (int i = y; i < y + height && i < VOXEL_CHUNK_SIZE_Y; i++)
         {
             var ofs = x + (z * VOXEL_CHUNK_SIZE_XZ) + (i * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
             chunk.flags         |= EChunkFlags.SOLID;
             chunk.voxeldata[ofs] = EVoxelBlockType.Wood;
         }
     }
     else if (treeType == 1)
     {
         // Trunk
         int height = 2 + x % 3 + y % 3 + z % 3;
         for (int i = y; i < y + height && i < VOXEL_CHUNK_SIZE_Y; i++)
         {
             var ofs = x + (z * VOXEL_CHUNK_SIZE_XZ) + (i * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
             chunk.flags         |= EChunkFlags.SOLID;
             chunk.voxeldata[ofs] = EVoxelBlockType.Wood;
         }
         int radius = x % 2 + y % 2 + z % 2;
         if (radius > 0)
         {
             for (int i = -radius; i <= radius; i++)
             {
                 for (int j = -radius; j <= radius; j++)
                 {
                     for (int k = -radius; k <= radius; k++)
                     {
                         int lx = x + i;
                         int lz = z + j;
                         int ly = y + k + height;
                         if (lx >= 0 && lx < VOXEL_CHUNK_SIZE_XZ && ly >= 0 && ly < VOXEL_CHUNK_SIZE_Y && lz >= 0 && lz < VOXEL_CHUNK_SIZE_XZ)
                         {
                             var ofs = lx + (lz * VOXEL_CHUNK_SIZE_XZ) + (ly * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                             chunk.flags         |= EChunkFlags.SOLID;
                             chunk.voxeldata[ofs] = EVoxelBlockType.Leaves.WithFlags(EVoxelBlockFlags.FullVoxel);
                         }
                     }
                 }
             }
         }
     }
     else if (treeType == 2)
     {
         int height = 3 + x % 2 + y % 2 + z % 2;
         for (int i = y; i < y + height && i < VOXEL_CHUNK_SIZE_Y; i++)
         {
             var ofs = x + (z * VOXEL_CHUNK_SIZE_XZ) + (i * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
             chunk.flags         |= EChunkFlags.SOLID;
             chunk.voxeldata[ofs] = EVoxelBlockType.Wood;
         }
         int radius = 1 + x % 2 + y % 2 + z % 2;
         if (radius > 0)
         {
             for (int k = -radius; k <= radius * 2; k++)
             {
                 int r = radius - (k + radius) / 3;
                 for (int i = -r; i <= r; i++)
                 {
                     for (int j = -r; j <= r; j++)
                     {
                         int lx = x + i;
                         int ly = y + k + height;
                         int lz = z + j;
                         if (lx >= 0 && lx < VOXEL_CHUNK_SIZE_XZ && ly >= 0 && ly < VOXEL_CHUNK_SIZE_Y && lz >= 0 && lz < VOXEL_CHUNK_SIZE_XZ)
                         {
                             var ofs = lx + (lz * VOXEL_CHUNK_SIZE_XZ) + (ly * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                             chunk.flags         |= EChunkFlags.SOLID;
                             chunk.voxeldata[ofs] = EVoxelBlockType.Needles;
                         }
                     }
                 }
             }
         }
     }
     else if (treeType == 3)
     {
         int height = 4 + x % 10 + y % 10 + z % 10;
         for (int i = y; i < y + height && i < VOXEL_CHUNK_SIZE_Y; i++)
         {
             var ofs = x + (z * VOXEL_CHUNK_SIZE_XZ) + (i * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
             chunk.flags         |= EChunkFlags.SOLID;
             chunk.voxeldata[ofs] = EVoxelBlockType.Wood;
         }
         for (int i = 3; i <= height; i++)
         {
             int        radius = (int)((1.0f - (float)(i - 3) / (height - 3)) * height / 3 + 1) + (x + y + z * z + i * i) % 2;
             Vector2Int branchDir;
             float      density = (float)((x + y + z + i * i) % 4 + 1) / 6f;
             if (radius > 1)
             {
                 for (int dir = 0; dir < 4; dir++)
                 {
                     if ((x + y + z + i + dir + radius) % 6 < 6 * density)
                     {
                         if (dir == 0)
                         {
                             branchDir = new Vector2Int(0, 1);
                         }
                         else if (dir == 1)
                         {
                             branchDir = new Vector2Int(0, -1);
                         }
                         else if (dir == 2)
                         {
                             branchDir = new Vector2Int(-1, 0);
                         }
                         else
                         {
                             branchDir = new Vector2Int(1, 0);
                         }
                         int ly = y + i;
                         for (int k = 1; k <= radius; k++)
                         {
                             int lx = x + branchDir.x * k;
                             int lz = z + branchDir.y * k;
                             if (lx >= 0 && lx < VOXEL_CHUNK_SIZE_XZ && ly >= 0 && ly < VOXEL_CHUNK_SIZE_Y && lz >= 0 && lz < VOXEL_CHUNK_SIZE_XZ)
                             {
                                 var ofs = lx + (lz * VOXEL_CHUNK_SIZE_XZ) + (ly * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                 chunk.flags         |= EChunkFlags.SOLID;
                                 chunk.voxeldata[ofs] = k == 1 ? EVoxelBlockType.Wood : EVoxelBlockType.Needles.WithFlags(EVoxelBlockFlags.FullVoxel);
                             }
                             if (k < radius)
                             {
                                 lx = x + branchDir.x * k + branchDir.y;
                                 lz = z + branchDir.y * k + branchDir.x;
                                 if (lx >= 0 && lx < VOXEL_CHUNK_SIZE_XZ && ly >= 0 && ly < VOXEL_CHUNK_SIZE_Y && lz >= 0 && lz < VOXEL_CHUNK_SIZE_XZ)
                                 {
                                     var ofs = lx + (lz * VOXEL_CHUNK_SIZE_XZ) + (ly * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                     chunk.flags         |= EChunkFlags.SOLID;
                                     chunk.voxeldata[ofs] = EVoxelBlockType.Needles.WithFlags(EVoxelBlockFlags.FullVoxel);
                                 }
                                 lx = x + branchDir.x * k - branchDir.y;
                                 lz = z + branchDir.y * k - branchDir.x;
                                 if (lx >= 0 && lx < VOXEL_CHUNK_SIZE_XZ && ly >= 0 && ly < VOXEL_CHUNK_SIZE_Y && lz >= 0 && lz < VOXEL_CHUNK_SIZE_XZ)
                                 {
                                     var ofs = lx + (lz * VOXEL_CHUNK_SIZE_XZ) + (ly * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                     chunk.flags         |= EChunkFlags.SOLID;
                                     chunk.voxeldata[ofs] = EVoxelBlockType.Needles.WithFlags(EVoxelBlockFlags.FullVoxel);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
            static void ConstructTower(int x, int y, int z, PinnedChunkData_t chunk)
            {
                int towerHeight = 120;

                for (int i = -1; i <= 1; i++)
                {
                    for (int j = -1; j <= 1; j++)
                    {
                        Vector3Int pos          = new Vector3Int(x + i, 0, z + j);
                        int        groundHeight = 0;
                        for (int k = towerHeight; k >= groundHeight; k--)
                        {
                            pos.y = k + y;
                            if (pos.x >= 0 && pos.x < VOXEL_CHUNK_SIZE_XZ && pos.z >= 0 && pos.z < VOXEL_CHUNK_SIZE_XZ && pos.y >= 0 && pos.y < VOXEL_CHUNK_SIZE_Y)
                            {
                                var ofs = pos.x + (pos.z * VOXEL_CHUNK_SIZE_XZ) + (pos.y * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                chunk.flags         |= EChunkFlags.SOLID;
                                chunk.voxeldata[ofs] = EVoxelBlockType.Rock;
                            }
                        }
                    }
                }
                for (int i = -3; i <= 3; i++)
                {
                    for (int j = -3; j <= 3; j++)
                    {
                        if (i > 1 || i < -1 || j > 1 || j < -1)
                        {
                            Vector3Int pos          = new Vector3Int(x + i, 0, z + j);
                            int        groundHeight = 0;
                            for (int k = towerHeight; k >= groundHeight; k--)
                            {
                                int stepIndex = 0;
                                if (j < -1)
                                {
                                    if (i < -1)
                                    {
                                        stepIndex = 0;
                                    }
                                    else if (i < 2)
                                    {
                                        stepIndex = 1;
                                    }
                                    else
                                    {
                                        stepIndex = 2;
                                    }
                                }
                                else if (j < 2)
                                {
                                    if (i > 1)
                                    {
                                        stepIndex = 3;
                                    }
                                    else
                                    {
                                        stepIndex = 7;
                                    }
                                }
                                else
                                {
                                    if (i > 1)
                                    {
                                        stepIndex = 4;
                                    }
                                    else if (i > -2)
                                    {
                                        stepIndex = 5;
                                    }
                                    else
                                    {
                                        stepIndex = 6;
                                    }
                                }
                                int modElevation = (k + stepIndex) % 7;

                                if (modElevation < 2)
                                {
                                    pos.y = k + y;
                                    if (pos.x >= 0 && pos.x < VOXEL_CHUNK_SIZE_XZ && pos.z >= 0 && pos.z < VOXEL_CHUNK_SIZE_XZ && pos.y >= 0 && pos.y < VOXEL_CHUNK_SIZE_Y)
                                    {
                                        var ofs = pos.x + (pos.z * VOXEL_CHUNK_SIZE_XZ) + (pos.y * VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ);
                                        chunk.flags |= EChunkFlags.SOLID;
                                        if (modElevation == 0 && i != 3 && i != 3 && j != -3 && j != 3 && k != towerHeight)
                                        {
                                            chunk.voxeldata[ofs] = EVoxelBlockType.Rock;
                                        }
                                        else
                                        {
                                            chunk.voxeldata[ofs] = EVoxelBlockType.Rock.WithFlags(EVoxelBlockFlags.FullVoxel);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
Exemple #10
0
    public static unsafe PinnedChunkData_t DecompressChunkData(byte *ptr, int len, PinnedChunkData_t chunk, FinalMeshVerts_t verts)
    {
        var src = ptr;

        {
            var decorationCount = *((int *)src);
            src += 4;

            for (int i = 0; i < decorationCount; ++i)
            {
                var d = default(Decoration_t);
                d.pos.x = *((float *)src);
                src    += 4;
                d.pos.y = *((float *)src);
                src    += 4;
                d.pos.z = *((float *)src);
                src    += 4;
                d.type  = (EDecorationType)(*((int *)src));
                src    += 4;

                chunk.AddDecoration(d);
            }
        }

        if ((chunk.flags & EChunkFlags.SOLID) == 0)
        {
            // empty chunk
            chunk.voxeldata.Broadcast(EVoxelBlockType.Air);

            for (int i = 0; i < verts.counts.Length; ++i)
            {
                verts.counts[i] = 0;
            }

            for (int i = 0; i < verts.submeshes.Length; ++i)
            {
                verts.submeshes[i] = 0;
            }

            return(chunk);
        }

        {
            var voxeldata = chunk.voxeldata;
            var count     = chunk.voxeldata.length;
            for (int i = 0; i < count; ++i)
            {
                voxeldata[i] = new Voxel_t(src[i]);
            }
        }

        src += chunk.voxeldata.length;

        for (int i = 0; i < verts.counts.Length; ++i)
        {
            verts.counts[i] = *((int *)src);
            src            += 4;
        }
        for (int i = 0; i < verts.submeshes.Length; ++i)
        {
            verts.submeshes[i] = *((int *)src);
            src += 4;
        }

        int totalVerts = *((int *)src);

        src += 4;
        int totalIndices = *((int *)src);

        src += 4;

        for (int i = 0; i < totalVerts; ++i)
        {
            Vector3 v3;
            v3.x = *((float *)src);
            src += 4;
            v3.y = *((float *)src);
            src += 4;
            v3.z = *((float *)src);
            src += 4;
            verts.positions[i] = v3;
        }
        for (int i = 0; i < totalVerts; ++i)
        {
            Vector3 v3;
            v3.x             = *((float *)src);
            src             += 4;
            v3.y             = *((float *)src);
            src             += 4;
            v3.z             = *((float *)src);
            src             += 4;
            verts.normals[i] = v3;
        }
        for (int i = 0; i < totalVerts; ++i)
        {
            uint c = *((uint *)src);
            src            += 4;
            verts.colors[i] = Utils.GetColor32FromUIntRGBA(c);
        }
        for (int i = 0; i < totalIndices; ++i)
        {
            verts.indices[i] = *((int *)src);
            src += 4;
        }

        return(chunk);
    }
Exemple #11
0
                void Run(PinnedChunkData_t chunk)
                {
                    _smoothVerts.Init();

                    _numVoxels = 0;

                    if ((chunk.flags & EChunkFlags.SOLID) == 0)
                    {
                        // no solid blocks in this chunk it can't have any visible faces.
                        _smoothVerts.Finish();
                        return;
                    }

                    for (int y = -BORDER_SIZE; y < VOXEL_CHUNK_SIZE_Y + BORDER_SIZE; ++y)
                    {
                        var ywrap = Wrap(y, VOXEL_CHUNK_SIZE_Y);
                        var ymin  = (ywrap == 0);
                        var ymax  = (ywrap == (VOXEL_CHUNK_SIZE_Y - 1));
                        var yofs  = VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ * ywrap;

                        var cy = (y < 0) ? 0 : (y < VOXEL_CHUNK_SIZE_Y) ? 1 : 2;

                        for (int z = -BORDER_SIZE; z < VOXEL_CHUNK_SIZE_XZ + BORDER_SIZE; ++z)
                        {
                            var zwrap = Wrap(z, VOXEL_CHUNK_SIZE_XZ);
                            var zmin  = (zwrap == 0);
                            var zmax  = (zwrap == (VOXEL_CHUNK_SIZE_XZ - 1));
                            var zofs  = VOXEL_CHUNK_SIZE_XZ * zwrap;

                            var cz = (z < 0) ? 0 : (z < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                            for (int x = -BORDER_SIZE; x < VOXEL_CHUNK_SIZE_XZ + BORDER_SIZE; ++x)
                            {
                                var xwrap = Wrap(x, VOXEL_CHUNK_SIZE_XZ);
                                var xmin  = (xwrap == 0);
                                var xmax  = (xwrap == (VOXEL_CHUNK_SIZE_XZ - 1));
                                var xofs  = xwrap;

                                var cx = (x < 0) ? 0 : (x < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                                var chunkIndex = cx + (cy * Y_PITCH) + (cz * Z_PITCH);
                                var POS_X      = chunkIndex + 1;
                                var NEG_X      = chunkIndex - 1;
                                var POS_Y      = chunkIndex + Y_PITCH;
                                var NEG_Y      = chunkIndex - Y_PITCH;
                                var POS_Z      = chunkIndex + Z_PITCH;
                                var NEG_Z      = chunkIndex - Z_PITCH;

                                var neighbor = _area[chunkIndex];

                                if (neighbor.valid != 0)
                                {
                                    var voxel = neighbor.voxeldata[zofs + yofs + xofs];
                                    if (_tables.blockContents[(int)voxel.type] == EVoxelBlockContents.None)
                                    {
                                        continue;
                                    }

                                    var blocktype = voxel.type;

                                    // avoid contents-change with neighbor blocks in unloaded-space
                                    _vn[0] = blocktype;
                                    _vn[1] = blocktype;
                                    _vn[2] = blocktype;
                                    _vn[3] = blocktype;
                                    _vn[4] = blocktype;
                                    _vn[5] = blocktype;

                                    if (xmin)
                                    {
                                        _vn[0] = neighbor.voxeldata[zofs + yofs + xofs + 1].type;
                                        if (_area[NEG_X].valid != 0)
                                        {
                                            _vn[1] = _area[NEG_X].voxeldata[zofs + yofs + VOXEL_CHUNK_SIZE_XZ - 1].type;
                                        }
                                    }
                                    else if (xmax)
                                    {
                                        if (_area[POS_X].valid != 0)
                                        {
                                            _vn[0] = _area[POS_X].voxeldata[zofs + yofs].type;
                                        }
                                        _vn[1] = neighbor.voxeldata[zofs + yofs + xofs - 1].type;
                                    }
                                    else
                                    {
                                        _vn[0] = neighbor.voxeldata[zofs + yofs + xofs + 1].type;
                                        _vn[1] = neighbor.voxeldata[zofs + yofs + xofs - 1].type;
                                    }

                                    if (ymin)
                                    {
                                        _vn[2] = neighbor.voxeldata[yofs + (VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ) + zofs + xofs].type;
                                        if (_area[NEG_Y].valid != 0)
                                        {
                                            _vn[3] = _area[NEG_Y].voxeldata[(VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ * (VOXEL_CHUNK_SIZE_Y - 1)) + zofs + xofs].type;
                                        }
                                    }
                                    else if (ymax)
                                    {
                                        if (_area[POS_Y].valid != 0)
                                        {
                                            _vn[2] = _area[POS_Y].voxeldata[zofs + xofs].type;
                                        }
                                        _vn[3] = neighbor.voxeldata[yofs - (VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ) + zofs + xofs].type;
                                    }
                                    else
                                    {
                                        _vn[2] = neighbor.voxeldata[yofs + (VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ) + zofs + xofs].type;
                                        _vn[3] = neighbor.voxeldata[yofs - (VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ) + zofs + xofs].type;
                                    }

                                    if (zmin)
                                    {
                                        _vn[4] = neighbor.voxeldata[yofs + (zofs + VOXEL_CHUNK_SIZE_XZ) + xofs].type;
                                        if (_area[NEG_Z].valid != 0)
                                        {
                                            _vn[5] = _area[NEG_Z].voxeldata[yofs + (VOXEL_CHUNK_SIZE_XZ * (VOXEL_CHUNK_SIZE_XZ - 1)) + xofs].type;
                                        }
                                    }
                                    else if (zmax)
                                    {
                                        if (_area[POS_Z].valid != 0)
                                        {
                                            _vn[4] = _area[POS_Z].voxeldata[yofs + xofs].type;
                                        }
                                        _vn[5] = neighbor.voxeldata[yofs + (zofs - VOXEL_CHUNK_SIZE_XZ) + xofs].type;
                                    }
                                    else
                                    {
                                        _vn[4] = neighbor.voxeldata[yofs + (zofs + VOXEL_CHUNK_SIZE_XZ) + xofs].type;
                                        _vn[5] = neighbor.voxeldata[yofs + (zofs - VOXEL_CHUNK_SIZE_XZ) + xofs].type;
                                    }

                                    for (int i = 0; i < 6; ++i)
                                    {
                                        _vnc[i] = _tables.blockContents[(int)_vn[i]];
                                    }

                                    var isBorderVoxel = (x < 0) || (x >= VOXEL_CHUNK_SIZE_XZ) || (y < 0) || (y >= VOXEL_CHUNK_SIZE_Y) || (z < 0) || (z >= VOXEL_CHUNK_SIZE_XZ);

                                    EmitVoxelFaces((x + BORDER_SIZE) + ((z + BORDER_SIZE) * NUM_VOXELS_XZ) + ((y + BORDER_SIZE) * NUM_VOXELS_XZ * NUM_VOXELS_XZ), x + BORDER_SIZE, y + BORDER_SIZE, z + BORDER_SIZE, voxel, isBorderVoxel);
                                }
                            }
                        }
                    }

                    _smoothVerts.Finish();
                }
 protected abstract Unity.Jobs.JobHandle CreateGenVoxelsJob(WorldChunkPos_t pos, PinnedChunkData_t chunk);
                void Run(PinnedChunkData_t chunk)
                {
                    _smoothVerts.Init();

                    if ((chunk.flags & EChunkFlags.SOLID) == 0)
                    {
                        // no solid blocks in this chunk it can't have any visible faces.
                        _smoothVerts.Finish();
                        return;
                    }

                    byte * grid       = stackalloc byte[8];
                    int *  x          = stackalloc int[3];
                    int *  edges      = stackalloc int[12];
                    byte * edgeBlocks = stackalloc byte[24];
                    float *nv         = stackalloc float[3];

                    for (x[2] = -2; x[2] < VOXEL_CHUNK_SIZE_Y + 1; ++x[2])
                    {
                        for (x[1] = -2; x[1] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[1])
                        {
                            for (x[0] = -2; x[0] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[0])
                            {
                                // read voxels around this vertex
                                // note the mask, and grid verts for the cubes are X/Y/Z, but unity
                                // is Y up so we have to swap Z/Y

                                bool isBorder = (x[0] < 0) || (x[0] >= VOXEL_CHUNK_SIZE_XZ) || (x[1] < 0) || (x[1] >= VOXEL_CHUNK_SIZE_XZ) || (x[2] < 0) || (x[2] >= VOXEL_CHUNK_SIZE_Y);

                                int cubeIndex = 0;

                                for (int i = 0; i < 8; ++i)
                                {
                                    var v = _tables.mc_cubeVerts[i];

                                    var iz    = x[2] + v[2];
                                    var zwrap = Wrap(iz, VOXEL_CHUNK_SIZE_Y);
                                    var zofs  = VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ * zwrap;                                  // zofs is really yofs in voxel data
                                    var cz    = (iz < 0) ? 0 : (iz < VOXEL_CHUNK_SIZE_Y) ? 1 : 2;

                                    var iy    = x[1] + v[1];
                                    var ywrap = Wrap(iy, VOXEL_CHUNK_SIZE_XZ);
                                    var yofs  = VOXEL_CHUNK_SIZE_XZ * ywrap;                                    // yofs is really zofs in voxel data

                                    var cy = (iy < 0) ? 0 : (iy < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                                    var ix    = x[0] + v[0];
                                    var xwrap = Wrap(ix, VOXEL_CHUNK_SIZE_XZ);
                                    var xofs  = xwrap;

                                    var cx = (ix < 0) ? 0 : (ix < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                                    var chunkIndex = cx + (cz * Y_PITCH) + (cy * Z_PITCH);
                                    var POS_X      = chunkIndex + 1;
                                    var NEG_X      = chunkIndex - 1;
                                    var POS_Y      = chunkIndex + Y_PITCH;
                                    var NEG_Y      = chunkIndex - Y_PITCH;
                                    var POS_Z      = chunkIndex + Z_PITCH;
                                    var NEG_Z      = chunkIndex - Z_PITCH;

                                    var neighbor = _area[chunkIndex];
                                    var voxel    = neighbor.valid != 0 ? neighbor.voxeldata[xofs + yofs + zofs] : EVoxelBlockType.Air;
                                    grid[i] = voxel.raw;
                                    if (_tables.blockContents[(int)voxel.type] == EVoxelBlockContents.None)
                                    {
                                        cubeIndex |= 1 << i;
                                    }
                                }

                                var edgeMask = _tables.mc_edgeTable[cubeIndex];

                                if (edgeMask == 0)
                                {
                                    // no contents change
                                    continue;
                                }

                                for (int i = 0; i < 12; ++i)
                                {
                                    edges[i] = -1;

                                    if ((edgeMask & (1 << i)) == 0)
                                    {
                                        continue;
                                    }

                                    nv[0] = 0; nv[1] = 0; nv[2] = 0;
                                    var e  = _tables.mc_edgeIndex[i];
                                    var v0 = _tables.mc_cubeVerts[e[0]];
                                    var v1 = _tables.mc_cubeVerts[e[1]];

                                    edgeBlocks[i * 2 + 0] = grid[e[0]];
                                    edgeBlocks[i * 2 + 1] = grid[e[1]];

                                    var t = 0.5f;

                                    for (int j = 0; j < 3; ++j)
                                    {
                                        nv[j] = (x[j] + v0[j] + 0.5f) + t * (v1[j] - v0[j]);
                                    }

                                    edges[i] = _smoothVerts.EmitVert(new Vector3(nv[0], nv[2], nv[1]));
                                }

                                var faces = _tables.mc_triTable[cubeIndex];
                                for (int i = 0; (i < faces.length) && (faces[i] != -1); i += 3)
                                {
                                    BoundsCheckAndThrow(faces[i + 0], 0, 12);
                                    BoundsCheckAndThrow(faces[i + 1], 0, 12);
                                    BoundsCheckAndThrow(faces[i + 2], 0, 12);

                                    Voxel_t             voxel = default(Voxel_t);
                                    EVoxelBlockContents vc    = default(EVoxelBlockContents);

                                    for (int j = 0; j < 3; ++j)
                                    {
                                        var v0v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 0]);
                                        var v1v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 1]);
                                        var v0c = _tables.blockContents[(int)v0v.type];
                                        var v1c = _tables.blockContents[(int)v1v.type];
                                        if (j > 0)
                                        {
                                            if (v0c > v1c)
                                            {
                                                if (v0c > vc)
                                                {
                                                    vc    = v0c;
                                                    voxel = v0v;
                                                }
                                            }
                                            else if (v1c > vc)
                                            {
                                                vc    = v1c;
                                                voxel = v1v;
                                            }
                                        }
                                        else
                                        {
                                            vc    = (v0c > v1c) ? v0c : v1c;
                                            voxel = (v0c > v1c) ? v0v : v1v;
                                        }
                                    }

                                    int     mat, layer;
                                    uint    smg;
                                    Color32 color;
                                    float   smoothing;

                                    GetBlockColorAndSmoothing(voxel.type, out color, out smg, out smoothing, out layer);
                                    mat = _blockMaterials[(int)voxel.type - 1];

                                    _smoothVerts.EmitTri(edges[faces[i]], edges[faces[i + 2]], edges[faces[i + 1]], smg, smoothing, color, layer, mat, isBorder);
                                }
                            }
                        }
                    }

                    _smoothVerts.Finish();
                }