예제 #1
0
        public bool TryGetValue(int x, int z, out HeightMapInfo[] heights, out int heightIndex)
        {
            int fx = x >> 8;
            int fz = z >> 8;

            heightIndex = ((z - (fz << 8)) << 8) + (x - (fx << 8));
            uint key = (uint)(((fz + 1024) << 16) + (fx + 1024));

            if (key == lastKey && lastSector != null)
            {
                heights = lastSector;
            }
            else if (!heightSectors.TryGetValue(key, out heights))
            {
                heights = new HeightMapInfo[65536];
                heightSectors.Add(key, heights);
            }
            lastSector = heights;
            lastKey    = key;
            return(heights [heightIndex].groundLevel != 0);
        }
        /// <summary>
        /// Paints the terrain inside the chunk defined by its central "position"
        /// </summary>
        /// <returns><c>true</c>, if terrain was painted, <c>false</c> otherwise.</returns>
        public override bool PaintChunk(VoxelChunk chunk)
        {
            Vector3 position = chunk.position;

            if (position.y + VoxelPlayEnvironment.CHUNK_HALF_SIZE < minHeight)
            {
                chunk.isAboveSurface = false;
                return(false);
            }

            int bedrockRow = -1;

            if ((object)bedrockVoxel != null && position.y < minHeight + VoxelPlayEnvironment.CHUNK_HALF_SIZE)
            {
                bedrockRow = (int)(minHeight - (position.y - VoxelPlayEnvironment.CHUNK_HALF_SIZE) + 1) * ONE_Y_ROW;
            }

            position.x -= VoxelPlayEnvironment.CHUNK_HALF_SIZE;
            position.y -= VoxelPlayEnvironment.CHUNK_HALF_SIZE;
            position.z -= VoxelPlayEnvironment.CHUNK_HALF_SIZE;
            Vector3 pos;

            int waterLevel = env.waterLevel > 0 ? env.waterLevel : -1;

            Voxel[] voxels = chunk.voxels;

            bool hasContent     = false;
            bool isAboveSurface = false;

            for (int z = 0; z < VoxelPlayEnvironment.CHUNK_SIZE; z++)
            {
                pos.z = position.z + z;
                int arrayZIndex = z * ONE_Z_ROW;
                for (int x = 0; x < VoxelPlayEnvironment.CHUNK_SIZE; x++)
                {
                    pos.x = position.x + x;
                    HeightMapInfo heightMapInfo = env.GetHeightMapInfoFast(pos.x, pos.z);

                    float groundLevel  = heightMapInfo.groundLevel;
                    float surfaceLevel = waterLevel > groundLevel ? waterLevel : groundLevel;
                    if (surfaceLevel < position.y)
                    {
                        // position is above terrain or water
                        isAboveSurface = true;
                        continue;
                    }

                    int hindex = GetHeightIndex(pos.x, pos.z);
                    if (hindex < 0)
                    {
                        continue;
                    }
                    VoxelDefinition vd = heights [hindex].terrainVoxelTop;
                    if ((object)vd == null)
                    {
                        continue;
                    }

                    int y = (int)(surfaceLevel - position.y);
                    if (y >= VoxelPlayEnvironment.CHUNK_SIZE)
                    {
                        y = (VoxelPlayEnvironment.CHUNK_SIZE - 1);
                    }
                    pos.y = position.y + y;

                    // Place voxels
                    int voxelIndex = y * ONE_Y_ROW + arrayZIndex + x;
                    if (pos.y > groundLevel)
                    {
                        // water above terrain
                        if (pos.y == surfaceLevel)
                        {
                            isAboveSurface = true;
                        }
                        while (pos.y > groundLevel && voxelIndex >= 0)
                        {
                            voxels [voxelIndex].Set(waterVoxel);
                            voxelIndex -= ONE_Y_ROW;
                            pos.y--;
                        }
                    }
                    else if (pos.y == groundLevel)
                    {
                        isAboveSurface = true;
                        if (voxels [voxelIndex].hasContent == 0)
                        {
                            // surface => draw voxel top, vegetation and trees
                            voxels [voxelIndex].Set(vd);
#if UNITY_EDITOR
                            if (!env.draftModeActive)
                            {
#endif
                            // Check tree probability
                            if (pos.y > waterLevel)
                            {
                                ModelDefinition treeModel = heights [hindex].treeModel;
                                if (env.enableTrees && treeModel != null)
                                {
                                    env.RequestTreeCreation(chunk, pos, treeModel);
                                }
                                else if (env.enableVegetation)
                                {
                                    VoxelDefinition vegetation = heights [hindex].vegetationVoxel;
                                    if (vegetation != null)
                                    {
                                        if (voxelIndex >= (VoxelPlayEnvironment.CHUNK_SIZE - 1) * ONE_Y_ROW)
                                        {
                                            env.RequestVegetationCreation(chunk.top, voxelIndex - ONE_Y_ROW * (VoxelPlayEnvironment.CHUNK_SIZE - 1), vegetation);
                                        }
                                        else
                                        {
                                            voxels [voxelIndex + ONE_Y_ROW].Set(vegetation);
                                        }
                                        env.vegetationCreated++;
                                    }
                                }
                            }
#if UNITY_EDITOR
                        }
#endif
                        }
                        voxelIndex -= ONE_Y_ROW;
                    }

                    // Continue filling down
                    vd = heights [hindex].terrainVoxelDirt;
                    while (voxelIndex > bedrockRow)
                    {
                        if (voxels [voxelIndex].hasContent == 0)
                        {
                            voxels [voxelIndex].SetFastOpaque(vd);
                        }
                        voxelIndex -= ONE_Y_ROW;
                    }
                    if (bedrockRow >= 0)
                    {
                        voxels [voxelIndex].SetFastOpaque(bedrockVoxel);
                    }
                    hasContent = true;
                }
            }

            chunk.isAboveSurface = isAboveSurface;
            return(hasContent);
        }
        void RefreshBiomeTexture()
        {
            if (biomeTex == null || biomeTex.width != mapResolution)
            {
                biomeTex = new Texture2D(mapResolution, mapResolution, TextureFormat.ARGB32, false);
            }

            int width  = biomeTex.width;
            int height = biomeTex.height;

            Color[] colors = new Color[width * height];

            if (env == null || tg == null)
            {
                colors.Fill <Color> (new Color(0, 0.5f, 0, 0.5f));
            }
            else
            {
                env.SetBiomeDefaultColors(false);
                colors.Fill <Color> (Misc.colorTransparent);

                // reset biome stats
                for (int k = 0; k < world.biomes.Length; k++)
                {
                    if (world.biomes [k] != null)
                    {
                        world.biomes [k].biomeMapOccurrences = 0;
                    }
                }
                // draw biome colors
                for (int j = 0; j < height; j++)
                {
                    float z  = (maxZ - minZ) * (float)j / height + minZ;
                    int   jj = j * width;
                    for (int k = 0; k < width; k++)
                    {
                        float         x    = (maxX - minX) * (float)k / width + minX;
                        HeightMapInfo info = env.GetTerrainInfo(x, z);
                        if (info.groundLevel <= tg.waterLevel)
                        {
                            colors [jj + k] = waterColor;
                        }
                        else
                        {
                            BiomeDefinition biome = info.biome;
                            if (biome == null)
                            {
                                continue;
                            }
                            biome.biomeMapOccurrences++;
                            if (biome.showInBiomeMap)
                            {
                                colors [jj + k] = biome.biomeMapColor;
                            }
                        }
                    }
                }

                int   gridCount = (int)((maxZ - minZ) / gridStep);
                Color gridColor = new Color(64, 64, 64, 0.2f);
                // draw horizontal grid lines
                for (int j = 0; j <= gridCount; j++)
                {
                    int y = (int)((height - 1f) * j / gridCount);
                    for (int k = 0; k < width; k++)
                    {
                        colors [y * width + k] = gridColor;
                    }
                }
                gridCount = (int)((maxX - minX) / gridStep);
                // draw vertical grid lines
                for (int j = 0; j <= gridCount; j++)
                {
                    int x = (int)((width - 1f) * j / gridCount);
                    for (int k = 0; k < height; k++)
                    {
                        colors [k * width + x] = gridColor;
                    }
                }
            }

            biomeTex.SetPixels(colors);
            biomeTex.Apply();
        }