コード例 #1
0
ファイル: ChunkFile.cs プロジェクト: svifylabs/dwarfcorp
        public void FillDataFromChunk(VoxelChunk chunk)
        {
            for (int x = 0; x < Size.X; x++)
            {
                for (int y = 0; y < Size.Y; y++)
                {
                    for (int z = 0; z < Size.Z; z++)
                    {
                        int       index = chunk.Data.IndexAt(x, y, z);
                        Voxel     vox   = chunk.MakeVoxel(x, y, z);
                        WaterCell water = chunk.Data.Water[index];

                        if (vox == null)
                        {
                            Types[x, y, z] = 0;
                        }
                        else
                        {
                            Types[x, y, z] = vox.Type.ID;
                        }

                        if (water.WaterLevel > 0)
                        {
                            Liquid[x, y, z]      = water.WaterLevel;
                            LiquidTypes[x, y, z] = (short)water.Type;
                        }
                        else
                        {
                            Liquid[x, y, z]      = 0;
                            LiquidTypes[x, y, z] = 0;
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: WallBuilder.cs プロジェクト: svifylabs/dwarfcorp
        public void Put(ChunkManager manager)
        {
            VoxelChunk chunk = manager.ChunkData.ChunkMap[Vox.ChunkID];

            Voxel v = chunk.MakeVoxel((int)Vox.GridPosition.X, (int)Vox.GridPosition.Y, (int)Vox.GridPosition.Z);

            v.Type   = Type;
            v.Water  = new WaterCell();
            v.Health = Type.StartingHealth;
            chunk.NotifyTotalRebuild(!v.IsInterior);

            PlayState.ParticleManager.Trigger("puff", v.Position, Color.White, 20);

            List <Body> components = new List <Body>();

            manager.Components.GetBodiesIntersecting(Vox.GetBoundingBox(), components, CollisionManager.CollisionType.Dynamic);

            foreach (Physics phys in components.OfType <Physics>())
            {
                phys.ApplyForce((phys.GlobalTransform.Translation - (Vox.Position + new Vector3(0.5f, 0.5f, 0.5f))) * 100, 0.01f);
                BoundingBox     box     = v.GetBoundingBox();
                Physics.Contact contact = new Physics.Contact();
                Physics.TestStaticAABBAABB(box, phys.GetBoundingBox(), ref contact);

                if (!contact.IsIntersecting)
                {
                    continue;
                }

                Vector3 diff = contact.NEnter * contact.Penetration;
                Matrix  m    = phys.LocalTransform;
                m.Translation      += diff;
                phys.LocalTransform = m;
            }
        }
コード例 #3
0
ファイル: ChunkGenerator.cs プロジェクト: svifylabs/dwarfcorp
        public void GenerateWater(VoxelChunk chunk)
        {
            int   waterHeight = (int)(SeaLevel * chunk.SizeY);
            Voxel voxel       = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    int h;
                    for (int y = 0; y < waterHeight; y++)
                    {
                        h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);
                        int index = chunk.Data.IndexAt(x, y, z);
                        voxel.GridPosition = new Vector3(x, y, z);
                        if (voxel.IsEmpty && y >= h)
                        {
                            chunk.Data.Water[index].WaterLevel = 255;
                            chunk.Data.Water[index].Type       = LiquidType.Water;
                        }
                    }


                    Vector2 vec = new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z) / PlayState.WorldScale;
                    if (Overworld.GetWater(Overworld.Map, vec) != Overworld.WaterType.Volcano)
                    {
                        continue;
                    }

                    h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);


                    if (h <= 0)
                    {
                        continue;
                    }

                    chunk.Data.Water[chunk.Data.IndexAt(x, h, z)].WaterLevel = 255;
                    chunk.Data.Water[chunk.Data.IndexAt(x, h, z)].Type       = LiquidType.Lava;

                    /*
                     * for (int y = h - 1; y >= 0; y--)
                     * {
                     *  voxel.Chunk = chunk;
                     *  voxel.GridPosition = new Vector3(x, y, z);
                     *  chunk.Data.Water[voxel.Index].Type = LiquidType.None;
                     *  chunk.Data.Water[voxel.Index].WaterLevel = 0;
                     *  voxel.Type = VoxelLibrary.GetVoxelType("Stone");
                     *  voxel.Chunk.NotifyTotalRebuild(!voxel.IsInterior);
                     * }
                     */
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Finds the air above the creature.
        /// </summary>
        /// <param name="creature">The creature.</param>
        /// <returns>A voxel containing air above the creature if it exists, or null otherwise</returns>
        public Voxel FindAir(Creature creature)
        {
            int        startHeight = (int)creature.AI.Position.Y;
            int        x           = (int)creature.Physics.CurrentVoxel.GridPosition.X;
            int        z           = (int)creature.Physics.CurrentVoxel.GridPosition.Z;
            VoxelChunk chunk       = creature.Physics.CurrentVoxel.Chunk;
            Voxel      check       = chunk.MakeVoxel(0, 0, 0);

            for (int y = startHeight; y < creature.Chunks.ChunkData.ChunkSizeY; y++)
            {
                check.GridPosition = new Vector3(x, y, z);
                if (check.WaterLevel == 0 && check.IsEmpty)
                {
                    return(check);
                }
            }
            return(null);
        }
コード例 #5
0
        public void GenerateOres(VoxelChunk chunk, ComponentManager components, ContentManager content,
                                 GraphicsDevice graphics)
        {
            Vector3 origin     = chunk.Origin;
            int     chunkSizeX = chunk.SizeX;
            int     chunkSizeY = chunk.SizeY;
            int     chunkSizeZ = chunk.SizeZ;
            Voxel   v          = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    int h = chunk.GetFilledVoxelGridHeightAt(x, chunkSizeY - 1, z);
                    for (int y = 1; y < chunkSizeY; y++)
                    {
                        foreach (
                            KeyValuePair <string, VoxelLibrary.ResourceSpawnRate> spawns in VoxelLibrary.ResourceSpawns)
                        {
                            float s = spawns.Value.VeinSize;
                            float p = spawns.Value.VeinSpawnThreshold;
                            v.GridPosition = new Vector3(x, y, z);
                            if (v.IsEmpty || y >= h - 1 || !(y - h / 2 < spawns.Value.MaximumHeight) ||
                                !(y - h / 2 > spawns.Value.MinimumHeight) ||
                                !(PlayState.Random.NextDouble() <= spawns.Value.Probability) || v.Type.Name != "Stone")
                            {
                                continue;
                            }

                            float caviness = (float)NoiseGenerator.Noise((float)(x + origin.X) * s,
                                                                         (float)(z + origin.Z) * s,
                                                                         (float)(y + origin.Y + h) * s);

                            if (caviness > p)
                            {
                                v.Type = VoxelLibrary.GetVoxelType(spawns.Key);
                            }
                            continue;
                        }
                    }
                }
            }
        }
コード例 #6
0
        public void GenerateWater(VoxelChunk chunk)
        {
            int   waterHeight = (int)(SeaLevel * chunk.SizeY);
            Voxel voxel       = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    int h;
                    for (int y = 0; y <= waterHeight; y++)
                    {
                        h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);
                        int index = chunk.Data.IndexAt(x, y, z);
                        voxel.GridPosition = new Vector3(x, y, z);
                        if (voxel.IsEmpty && y >= h)
                        {
                            chunk.Data.Water[index].WaterLevel = 8;
                            chunk.Data.Water[index].Type       = LiquidType.Water;
                        }
                    }


                    Vector2 vec = new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z) / PlayState.WorldScale;
                    if (Overworld.GetWater(Overworld.Map, vec) != Overworld.WaterType.Volcano)
                    {
                        continue;
                    }

                    h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);


                    if (h <= 0)
                    {
                        continue;
                    }

                    chunk.Data.Water[chunk.Data.IndexAt(x, h, z)].WaterLevel = 8;
                    chunk.Data.Water[chunk.Data.IndexAt(x, h, z)].Type       = LiquidType.Lava;
                }
            }
        }
コード例 #7
0
ファイル: ChunkGenerator.cs プロジェクト: svifylabs/dwarfcorp
        /*
         * public void GenerateOres(VoxelChunk chunk, ComponentManager components, ContentManager content,
         *  GraphicsDevice graphics)
         * {
         *  Vector3 origin = chunk.Origin;
         *  int chunkSizeX = chunk.SizeX;
         *  int chunkSizeY = chunk.SizeY;
         *  int chunkSizeZ = chunk.SizeZ;
         *  Voxel v = chunk.MakeVoxel(0, 0, 0);
         *  for (int x = 0; x < chunkSizeX; x++)
         *  {
         *      for (int z = 0; z < chunkSizeZ; z++)
         *      {
         *          int h = chunk.GetFilledVoxelGridHeightAt(x, chunkSizeY - 1, z);
         *          for (int y = 1; y < chunkSizeY; y++)
         *          {
         *              foreach (
         *                  KeyValuePair<string, VoxelLibrary.ResourceSpawnRate> spawns in VoxelLibrary.ResourceSpawns)
         *              {
         *                  float s = spawns.Value.VeinSize;
         *                  float p = spawns.Value.VeinSpawnThreshold;
         *                  v.GridPosition = new Vector3(x, y, z);
         *                  if (v.IsEmpty || y >= h - 1 || !(y - h/2 < spawns.Value.MaximumHeight) ||
         *                      !(y - h/2 > spawns.Value.MinimumHeight) ||
         *                      !(PlayState.Random.NextDouble() <= spawns.Value.Probability) || v.Type.Name != "Stone")
         *                  {
         *                      continue;
         *                  }
         *
         *                  float caviness = (float) NoiseGenerator.Noise((float) (x + origin.X)*s,
         *                      (float) (z + origin.Z)*s,
         *                      (float) (y + origin.Y + h)*s);
         *
         *                  if (caviness > p)
         *                  {
         *                      v.Type = VoxelLibrary.GetVoxelType(spawns.Key);
         *                  }
         *                  continue;
         *              }
         *          }
         *      }
         *  }
         * }
         */

        public void GenerateFauna(VoxelChunk chunk, ComponentManager components, ContentManager content, GraphicsDevice graphics, FactionLibrary factions)
        {
            int   waterHeight = (int)(SeaLevel * chunk.SizeY);
            Voxel v           = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    Vector2         vec       = new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z) / PlayState.WorldScale;
                    Overworld.Biome biome     = Overworld.Map[(int)MathFunctions.Clamp(vec.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(vec.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;
                    BiomeData       biomeData = BiomeLibrary.Biomes[biome];

                    int y = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);

                    if (!chunk.IsCellValid(x, (int)(y - chunk.Origin.Y), z))
                    {
                        continue;
                    }

                    v.GridPosition = new Vector3(x, y, z);

                    if (chunk.Data.Water[v.Index].WaterLevel != 0 || y <= waterHeight)
                    {
                        continue;
                    }

                    foreach (FaunaData animal in biomeData.Fauna)
                    {
                        if (y <= 0 || !(PlayState.Random.NextDouble() < animal.SpawnProbability))
                        {
                            continue;
                        }


                        EntityFactory.CreateEntity <Body>(animal.Name, chunk.Origin + new Vector3(x, y, z) + Vector3.Up * 1.0f);

                        break;
                    }
                }
            }
        }
コード例 #8
0
ファイル: ChunkGenerator.cs プロジェクト: svifylabs/dwarfcorp
        public void GenerateLava(VoxelChunk chunk)
        {
            int   lavaHeight = 2;
            Voxel voxel      = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    for (int y = 0; y < lavaHeight; y++)
                    {
                        voxel.GridPosition = new Vector3(x, y, z);
                        if (voxel.IsEmpty && chunk.Data.Water[voxel.Index].WaterLevel == 0)
                        {
                            chunk.Data.Water[voxel.Index].WaterLevel = 255;
                            chunk.Data.Water[voxel.Index].Type       = LiquidType.Lava;
                        }
                    }
                }
            }
        }
コード例 #9
0
ファイル: VoxelListener.cs プロジェクト: NakedFury/dwarfcorp
        public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            if (firstIter)
            {
                if (Chunk.Data.Types[Chunk.Data.IndexAt(VoxelID.X, VoxelID.Y, VoxelID.Z)] == 0)
                {
                    Delete();
                }
                firstIter = false;
            }

            if (DestroyOnTimer)
            {
                DestroyTimer.Update(gameTime);

                if (DestroyTimer.HasTriggered)
                {
                    Die();
                    Chunk.MakeVoxel(VoxelID.X, VoxelID.Y, VoxelID.Z).Kill();
                }
            }
        }
コード例 #10
0
ファイル: WaterManager.cs プロジェクト: scorvi/dwarfcorp
        public bool DiscreteUpdate(VoxelChunk chunk)
        {
            Vector3 gridCoord = new Vector3(0, 0, 0);

            bool updateOccurred = false;

            List<int> updateList = new List<int>();
            WaterCell cellBelow = new WaterCell();

            int maxSize = chunk.SizeX*chunk.SizeY*chunk.SizeZ;
            for (int i = 0; i < maxSize; i++)
            {
                WaterCell cell = chunk.Data.Water[i];
                // Don't check empty cells or cells we've already modified.
                if (cell.WaterLevel < 1 || chunk.Data.Types[i] != 0)
                {
                    continue;
                }
                updateList.Add(i);
            }

            if(updateList.Count == 0)
            {
                return false;
            }
            Voxel voxBelow = chunk.MakeVoxel(0, 0, 0);

            List<int> indices = Datastructures.RandomIndices(updateList.Count);

            // Loop through each cell.
            foreach(int t in indices)
            {
                int idx = updateList[indices[t]];

                // Don't check empty cells or cells we've already modified.
                if (chunk.Data.Water[idx].WaterLevel < 1 || chunk.Data.Types[idx] != 0)
                {
                    continue;
                }

                gridCoord = chunk.Data.CoordsAt(idx);
                int x = (int) gridCoord.X;
                int y = (int) gridCoord.Y;
                int z = (int) gridCoord.Z;
                Vector3 worldPos = gridCoord + chunk.Origin;

                if (chunk.Data.Water[idx].WaterLevel < EvaporationLevel && PlayState.Random.Next(0, 10) < 5)
                {
                    if (chunk.Data.Water[idx].WaterLevel > 1)
                    {
                        chunk.Data.Water[idx].WaterLevel--;
                    }
                    else
                    {
                        chunk.Data.Water[idx].WaterLevel = 0;
                        chunk.Data.Water[idx].Type = LiquidType.None;
                        CreateSplash(worldPos, chunk.Data.Water[idx].Type);
                    }
                    updateOccurred = true;
                }

                bool shouldFall = false;

                // Now check the cell immediately below this one.
                // There are two cases, either we are at the bottom of the chunk,
                // in which case we must find the water from the chunk manager.
                // Otherwise, we just get the cell immediately beneath us.
                if(y > 0)
                {
                    voxBelow.GridPosition = new Vector3(x, y - 1, z);
                    if(voxBelow.IsEmpty)
                    {
                        cellBelow = voxBelow.Water;
                        shouldFall = true;
                    }
                }
                    /*
                else
                {
                    if(chunk.Manager.ChunkData.DoesWaterCellExist(worldPos))
                    {
                        Voxel voxelsBelow = chunk.Manager.ChunkData.GetVoxel(chunk, worldPos + new Vector3(0, -1, 0));

                        if(voxelsBelow != null && voxelsBelow.IsEmpty)
                        {
                            cellBelow = chunk.Manager.ChunkData.GetWaterCellAtLocation(worldPos + new Vector3(0, -1, 0));
                            shouldFall = true;
                            cellBelow.IsFalling = true;
                        }
                    }
                }
                     */

                // Cases where the fluid can fall down.
                if(shouldFall)
                {
                    // If the cell immediately below us is empty,
                    // swap the contents and move on.
                    if(cellBelow.WaterLevel < 1)
                    {
                        cellBelow.WaterLevel = chunk.Data.Water[idx].WaterLevel;
                        if(cellBelow.Type == LiquidType.None)
                        {
                            cellBelow.Type = chunk.Data.Water[idx].Type;
                        }
                        chunk.Data.Water[idx].WaterLevel = 0;
                        chunk.Data.Water[idx].Type = LiquidType.None;
                        chunk.Data.Water[idx].IsFalling = true;
                        chunk.Data.Water[idx].HasChanged = true;
                        cellBelow.HasChanged = true;
                        voxBelow.Water = cellBelow;
                        CreateSplash(worldPos, chunk.Data.Water[idx].Type);
                        CreateTransfer(worldPos, chunk.Data.Water[idx], cellBelow, cellBelow.WaterLevel);
                        updateOccurred = true;

                        continue;
                    }
                        // Otherwise, fill as much of the space as we can.
                    else
                    {
                        byte spaceLeft = (byte) (255 - cellBelow.WaterLevel);

                        if(spaceLeft > 5)
                        {
                            CreateSplash(gridCoord + chunk.Origin, chunk.Data.Water[idx].Type);
                        }

                        // Special case where we can flow completely into the next cell.
                        if (spaceLeft >= chunk.Data.Water[idx].WaterLevel)
                        {
                            byte transfer = chunk.Data.Water[idx].WaterLevel;
                            cellBelow.WaterLevel += transfer;
                            cellBelow.HasChanged = true;
                            if(cellBelow.Type == LiquidType.None)
                            {
                                cellBelow.Type = chunk.Data.Water[idx].Type;
                            }
                            chunk.Data.Water[idx].WaterLevel = 0;
                            chunk.Data.Water[idx].Type = LiquidType.None;
                            chunk.Data.Water[idx].HasChanged = true;

                            CreateTransfer(worldPos - Vector3.UnitY, chunk.Data.Water[idx], cellBelow, transfer);
                            voxBelow.Water = cellBelow;
                            updateOccurred = true;
                            continue;
                        }
                            // Otherwise, only flow a little bit, and spread later.
                        else
                        {
                            chunk.Data.Water[idx].WaterLevel -= spaceLeft;
                            cellBelow.WaterLevel += spaceLeft;
                            chunk.Data.Water[idx].HasChanged = true;
                            cellBelow.HasChanged = true;
                            if(cellBelow.Type == LiquidType.None)
                            {
                                cellBelow.Type = chunk.Data.Water[idx].Type;
                            }
                            CreateTransfer(worldPos - Vector3.UnitY, chunk.Data.Water[idx], cellBelow, spaceLeft);
                            voxBelow.Water = cellBelow;
                        }
                    }
                }

                // Now the only fluid left can spread.
                // We spread to the manhattan neighbors
                //Array.Sort(m_spreadNeighbors, (a, b) => CompareFlowVectors(a, b, chunk.Data.Water[idx].FluidFlow));

                Voxel neighbor = new Voxel();
                foreach(Vector3 spread in m_spreadNeighbors)
                {
                    bool success = chunk.Manager.ChunkData.GetVoxel(chunk, worldPos + spread, ref neighbor);

                    if(!success)
                    {
                        continue;
                    }

                    if(!neighbor.IsEmpty)
                    {
                        continue;
                    }

                    WaterCell neighborWater = neighbor.Water;

                    byte amountToMove = (byte)(Math.Min(255.0f - (float)neighborWater.WaterLevel, chunk.Data.Water[idx].WaterLevel) * GetSpreadRate(chunk.Data.Water[idx].Type));

                    if(amountToMove == 0)
                    {
                        continue;
                    }

                    if(neighborWater.WaterLevel < 2)
                    {
                        CreateSplash(worldPos + spread, chunk.Data.Water[idx].Type);
                        updateOccurred = true;
                    }

                    CreateTransfer(worldPos + spread, chunk.Data.Water[idx], neighborWater, amountToMove);

                    chunk.Data.Water[idx].WaterLevel -= amountToMove;
                    neighborWater.WaterLevel += amountToMove;

                    if(neighborWater.Type == LiquidType.None)
                    {
                        neighborWater.Type = chunk.Data.Water[idx].Type;
                    }

                    chunk.Data.Water[idx].HasChanged = true;
                    neighborWater.HasChanged = true;
                    neighbor.Water = neighborWater;

                    if (chunk.Data.Water[idx].WaterLevel >= 1)
                    {
                        continue;
                    }

                    chunk.Data.Water[idx].WaterLevel = 0;
                    chunk.Data.Water[idx].Type = LiquidType.None;
                    break;
                }
            }

            return updateOccurred;
        }
コード例 #11
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if(isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();

            accumulatedVertices.Clear();
            accumulatedIndices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            Voxel v = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);
            Voxel[] manhattanNeighbors = new Voxel[4];
            for(int x = 0; x < chunk.SizeX; x++)
            {
                for(int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for(int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);

                        if((v.IsExplored && v.IsEmpty) || !v.IsVisible)
                        {
                            continue;
                        }

                        BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type);

                        if (v.IsExplored && primitive == null) continue;
                        else if (!v.IsExplored)
                        {
                            primitive = VoxelLibrary.GetPrimitive("Bedrock");
                        }
                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }

                        Voxel worldVoxel = new Voxel();
                        for(int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace) i;
                            Vector3 delta = FaceDeltas[face];
                            faceExists[face] = chunk.IsCellValid(x + (int) delta.X, y + (int) delta.Y, z + (int) delta.Z);
                            drawFace[face] = true;

                            if(faceExists[face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int) delta.X, y + (int) delta.Y, z + (int) delta.Z);
                                drawFace[face] =  voxelOnFace.IsEmpty || !voxelOnFace.IsVisible || (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));

                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int) delta.X, y + (int) delta.Y, z + (int) delta.Z) + chunk.Origin, ref worldVoxel);
                                    drawFace[face] = !success || worldVoxel.IsEmpty || !worldVoxel.IsVisible ||
                                                     (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None &&
                                                      IsSideFace(face) &&
                                                      ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }

                        for(int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace) i;
                            if(!drawFace[face])
                            {
                                continue;
                            }
                            int faceIndex = 0;
                            int faceCount = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = accumulatedVertices.Count;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex bestKey = VoxelChunk.GetNearestDelta(vert.Position);
                                Color color = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                Vector3 offset = Vector3.Zero;
                                Vector2 texOffset = Vector2.Zero;

                                if(v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if(face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }

                                ExtendedVertex newVertex = new ExtendedVertex((vert.Position + v.Position + VertexNoise.GetNoiseVectorFromRepeatingTexture(vert.Position + v.Position) + offset),
                                    color,
                                     uvs.Uvs[vertOffset + vertexIndex] + texOffset, uvs.Bounds[faceIndex / 6]);
                                accumulatedVertices.Add(newVertex);
                            }

                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                int vertexOffset = primitive.Indices[idx];
                                accumulatedIndices.Add((short)(indexOffset + (vertexOffset - primitive.Indices[faceIndex])));
                            }
                        }
                    }
                }
            }

            Vertices = new ExtendedVertex[accumulatedVertices.Count];
            accumulatedVertices.CopyTo(Vertices);
            IndexBuffer = new IndexBuffer(graphics, typeof(short), accumulatedIndices.Count, BufferUsage.WriteOnly);
            IndexBuffer.SetData(accumulatedIndices.ToArray());

            ResetBuffer(graphics);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
コード例 #12
0
        public static void UpdateRamps(VoxelChunk chunk)
        {
            Dictionary<BoxFace, bool> faceExists = new Dictionary<BoxFace, bool>();
            Dictionary<BoxFace, bool> faceVisible = new Dictionary<BoxFace, bool>();
            Voxel v = chunk.MakeVoxel(0, 0, 0);
            Voxel vAbove = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);
            Voxel worldVoxel = new Voxel();

            for(int x = 0; x < chunk.SizeX; x++)
            {
                for(int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for(int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);
                        bool isTop = false;

                        if(y < chunk.SizeY - 1)
                        {
                            vAbove.GridPosition = new Vector3(x, y + 1, z);

                            isTop = vAbove.IsEmpty;
                        }

                        if(isTop && !v.IsEmpty && v.IsVisible && v.Type.CanRamp)
                        {

                            for(int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace) i;
                                if(!IsSideFace(face))
                                {
                                    continue;
                                }

                                Vector3 delta = FaceDeltas[face];
                                faceExists[face] = chunk.IsCellValid(x + (int) delta.X, y + (int) delta.Y, z + (int) delta.Z);
                                faceVisible[face] = true;

                                if(faceExists[face])
                                {
                                    voxelOnFace.GridPosition = new Vector3(x + (int) delta.X, y + (int) delta.Y,
                                        z + (int) delta.Z);

                                    if(voxelOnFace.IsEmpty || !voxelOnFace.IsVisible)
                                    {
                                        faceVisible[face] = true;
                                    }
                                    else
                                    {
                                        faceVisible[face] = false;
                                    }
                                }
                                else
                                {
                                    if (!chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X + 0.5f, y + (int)delta.Y + 0.5f, z + (int)delta.Z + 0.5f) + chunk.Origin, ref worldVoxel) || !worldVoxel.IsVisible)
                                    {
                                        faceVisible[face] = true;
                                    }
                                    else
                                    {
                                        faceVisible[face] = false;
                                    }
                                }

                                if(faceVisible[face])
                                {
                                    v.RampType = v.RampType | UpdateRampType(face);
                                }
                            }

                            if(RampIsDegenerate(v.RampType))
                            {
                                v.RampType = RampType.None;
                            }
                        }
                        else if(!v.IsEmpty && v.IsVisible && v.Type.CanRamp)
                        {
                            v.RampType = RampType.None;
                        }
                    }
                }
            }
        }
コード例 #13
0
        public static void UpdateCornerRamps(VoxelChunk chunk)
        {
            Voxel v = chunk.MakeVoxel(0, 0, 0);
            Voxel vAbove = chunk.MakeVoxel(0, 0, 0);
            List<Voxel> diagNeighbors = chunk.AllocateVoxels(3);
            List<VoxelVertex> top = new List<VoxelVertex>()
            {
                VoxelVertex.FrontTopLeft,
                VoxelVertex.FrontTopRight,
                VoxelVertex.BackTopLeft,
                VoxelVertex.BackTopRight
            };

            for(int x = 0; x < chunk.SizeX; x++)
            {
                for(int y = 0; y < chunk.SizeY; y++)
                {
                    for(int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);
                        bool isTop = false;

                        if(y < chunk.SizeY - 1)
                        {
                            vAbove.GridPosition =  new Vector3(x, y + 1, z);

                            isTop = vAbove.IsEmpty;
                        }

                        if(v.IsEmpty || !v.IsVisible || !isTop || !v.Type.CanRamp)
                        {
                            v.RampType = RampType.None;
                            continue;
                        }
                        v.RampType = RampType.None;

                        foreach (VoxelVertex bestKey in top)
                        {
                            List<Vector3> neighbors = VertexNeighbors2D[bestKey];
                            chunk.GetNeighborsSuccessors(neighbors, (int)v.GridPosition.X, (int)v.GridPosition.Y, (int)v.GridPosition.Z, diagNeighbors);

                            bool emptyFound = diagNeighbors.Any(vox => vox.IsEmpty);

                            if(!emptyFound)
                            {
                                continue;
                            }

                            switch(bestKey)
                            {
                                case VoxelVertex.FrontTopLeft:
                                    v.RampType |= RampType.TopBackLeft;
                                    break;
                                case VoxelVertex.FrontTopRight:
                                    v.RampType |= RampType.TopBackRight;
                                    break;
                                case VoxelVertex.BackTopLeft:
                                    v.RampType |= RampType.TopFrontLeft;
                                    break;
                                case VoxelVertex.BackTopRight:
                                    v.RampType |= RampType.TopFrontRight;
                                    break;
                            }
                        }
                    }
                }
            }
        }
コード例 #14
0
ファイル: WaterManager.cs プロジェクト: Solsund/dwarfcorp
        public bool DiscreteUpdate(VoxelChunk chunk)
        {
            Vector3 gridCoord = new Vector3(0, 0, 0);

            bool updateOccurred = false;

            List <int> updateList = new List <int>();
            WaterCell  cellBelow  = new WaterCell();

            int maxSize = chunk.SizeX * chunk.SizeY * chunk.SizeZ;

            for (int i = 0; i < maxSize; i++)
            {
                WaterCell cell = chunk.Data.Water[i];
                // Don't check empty cells or cells we've already modified.
                if (cell.WaterLevel < 1 || chunk.Data.Types[i] != 0)
                {
                    continue;
                }
                updateList.Add(i);
            }

            if (updateList.Count == 0)
            {
                return(false);
            }
            Voxel voxBelow = chunk.MakeVoxel(0, 0, 0);

            List <int> indices = Datastructures.RandomIndices(updateList.Count);

            // Loop through each cell.
            foreach (int t in indices)
            {
                int idx = updateList[indices[t]];


                // Don't check empty cells or cells we've already modified.
                if (chunk.Data.Water[idx].Type == LiquidType.None || chunk.Data.Types[idx] != 0)
                {
                    continue;
                }

                gridCoord = chunk.Data.CoordsAt(idx);
                int     x        = (int)gridCoord.X;
                int     y        = (int)gridCoord.Y;
                int     z        = (int)gridCoord.Z;
                Vector3 worldPos = gridCoord + chunk.Origin;

                if (chunk.Data.Water[idx].WaterLevel <= EvaporationLevel && MathFunctions.RandEvent(0.01f))
                {
                    if (chunk.Data.Water[idx].WaterLevel > 1)
                    {
                        chunk.Data.Water[idx].WaterLevel--;
                    }
                    else
                    {
                        chunk.Data.Water[idx].WaterLevel = 0;

                        if (chunk.Data.Water[idx].Type == LiquidType.Lava)
                        {
                            chunk.Data.Types[idx]           = (byte)VoxelLibrary.GetVoxelType("Stone").ID;
                            chunk.Data.Health[idx]          = (byte)VoxelLibrary.GetVoxelType("Stone").StartingHealth;
                            chunk.ShouldRebuild             = true;
                            chunk.ShouldRecalculateLighting = true;
                        }
                        chunk.Data.Water[idx].Type = LiquidType.None;
                    }
                    updateOccurred = true;
                }



                bool shouldFall = false;


                // Now check the cell immediately below this one.
                // There are two cases, either we are at the bottom of the chunk,
                // in which case we must find the water from the chunk manager.
                // Otherwise, we just get the cell immediately beneath us.
                if (y > 0)
                {
                    voxBelow.GridPosition = new Vector3(x, y - 1, z);
                    if (voxBelow.IsEmpty)
                    {
                        cellBelow  = voxBelow.Water;
                        shouldFall = true;
                    }
                }

                /*
                 * else
                 * {
                 * if(chunk.Manager.ChunkData.DoesWaterCellExist(worldPos))
                 * {
                 *  Voxel voxelsBelow = chunk.Manager.ChunkData.GetVoxel(chunk, worldPos + new Vector3(0, -1, 0));
                 *
                 *  if(voxelsBelow != null && voxelsBelow.IsEmpty)
                 *  {
                 *      cellBelow = chunk.Manager.ChunkData.GetWaterCellAtLocation(worldPos + new Vector3(0, -1, 0));
                 *      shouldFall = true;
                 *      cellBelow.IsFalling = true;
                 *  }
                 * }
                 * }
                 */

                // Cases where the fluid can fall down.
                if (shouldFall)
                {
                    // If the cell immediately below us is empty,
                    // swap the contents and move on.
                    if (cellBelow.WaterLevel < 1)
                    {
                        CreateSplash(worldPos, chunk.Data.Water[idx].Type);
                        cellBelow.WaterLevel = chunk.Data.Water[idx].WaterLevel;
                        if (cellBelow.Type == LiquidType.None)
                        {
                            cellBelow.Type = chunk.Data.Water[idx].Type;
                        }
                        chunk.Data.Water[idx].WaterLevel = 0;
                        chunk.Data.Water[idx].Type       = LiquidType.None;
                        voxBelow.Water = cellBelow;
                        CreateTransfer(worldPos, chunk.Data.Water[idx], cellBelow, cellBelow.WaterLevel);
                        updateOccurred = true;

                        continue;
                    }
                    // Otherwise, fill as much of the space as we can.
                    else
                    {
                        byte spaceLeft = (byte)(8 - cellBelow.WaterLevel);


                        // Special case where we can flow completely into the next cell.
                        if (spaceLeft >= chunk.Data.Water[idx].WaterLevel)
                        {
                            byte transfer = chunk.Data.Water[idx].WaterLevel;
                            cellBelow.WaterLevel += transfer;
                            if (cellBelow.Type == LiquidType.None)
                            {
                                cellBelow.Type = chunk.Data.Water[idx].Type;
                            }
                            chunk.Data.Water[idx].WaterLevel = 0;
                            chunk.Data.Water[idx].Type       = LiquidType.None;

                            CreateTransfer(worldPos - Vector3.UnitY, chunk.Data.Water[idx], cellBelow, transfer);
                            voxBelow.Water = cellBelow;
                            updateOccurred = true;
                            continue;
                        }
                        // Otherwise, only flow a little bit, and spread later.
                        else
                        {
                            chunk.Data.Water[idx].WaterLevel -= spaceLeft;
                            cellBelow.WaterLevel             += spaceLeft;
                            if (cellBelow.Type == LiquidType.None)
                            {
                                cellBelow.Type = chunk.Data.Water[idx].Type;
                            }
                            CreateTransfer(worldPos - Vector3.UnitY, chunk.Data.Water[idx], cellBelow, spaceLeft);
                            voxBelow.Water = cellBelow;
                        }
                    }
                }

                // Now the only fluid left can spread.
                // We spread to the manhattan neighbors
                //Array.Sort(m_spreadNeighbors, (a, b) => CompareFlowVectors(a, b, chunk.Data.Water[idx].FluidFlow));
                m_spreadNeighbors.Shuffle();
                Voxel neighbor = new Voxel();
                foreach (Vector3 spread in m_spreadNeighbors)
                {
                    bool success = chunk.Manager.ChunkData.GetVoxel(chunk, worldPos + spread, ref neighbor);

                    if (!success)
                    {
                        continue;
                    }

                    if (!neighbor.IsEmpty)
                    {
                        continue;
                    }

                    WaterCell neighborWater = neighbor.Water;

                    if (neighborWater.WaterLevel >= chunk.Data.Water[idx].WaterLevel)
                    {
                        continue;
                    }

                    byte amountToMove = (byte)(Math.Min(8.0f - (float)neighborWater.WaterLevel, chunk.Data.Water[idx].WaterLevel) * GetSpreadRate(chunk.Data.Water[idx].Type));

                    if (amountToMove == 0)
                    {
                        continue;
                    }


                    if (neighborWater.WaterLevel < 2)
                    {
                        updateOccurred = true;
                    }

                    CreateTransfer(worldPos + spread, chunk.Data.Water[idx], neighborWater, amountToMove);

                    chunk.Data.Water[idx].WaterLevel -= amountToMove;
                    neighborWater.WaterLevel         += amountToMove;

                    if (neighborWater.Type == LiquidType.None)
                    {
                        neighborWater.Type = chunk.Data.Water[idx].Type;
                    }

                    neighbor.Water = neighborWater;

                    if (chunk.Data.Water[idx].WaterLevel >= 1)
                    {
                        continue;
                    }

                    chunk.Data.Water[idx].WaterLevel = 0;
                    chunk.Data.Water[idx].Type       = LiquidType.None;
                    break;
                }
            }

            return(updateOccurred);
        }
コード例 #15
0
        public void GenerateCaves(VoxelChunk chunk)
        {
            Vector3      origin     = chunk.Origin;
            int          chunkSizeX = chunk.SizeX;
            int          chunkSizeY = chunk.SizeY;
            int          chunkSizeZ = chunk.SizeZ;
            BiomeData    biome      = BiomeLibrary.Biomes[Overworld.Biome.Cave];
            List <Voxel> neighbors  = new List <Voxel>();
            Voxel        vUnder     = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    int h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);
                    for (int i = 0; i < CaveLevels.Count; i++)
                    {
                        int y = CaveLevels[i];
                        if (y <= 0 || y >= h - 1)
                        {
                            continue;
                        }
                        Vector3 vec       = new Vector3(x, y, z) + chunk.Origin;
                        double  caveNoise = CaveNoise.GetValue((x + origin.X) * CaveNoiseScale * CaveFrequencies[i],
                                                               (y + origin.Y) * CaveNoiseScale * 3.0f, (z + origin.Z) * CaveNoiseScale * CaveFrequencies[i]);

                        double heightnoise = NoiseGenerator.Noise((x + origin.X) * NoiseScale * CaveFrequencies[i],
                                                                  (y + origin.Y) * NoiseScale * 3.0f, (z + origin.Z) * NoiseScale * CaveFrequencies[i]);

                        int caveHeight = Math.Min(Math.Max((int)(heightnoise * 5), 1), 3);

                        if (caveNoise > CaveSize)
                        {
                            bool waterFound = false;
                            for (int dy = 0; dy < caveHeight; dy++)
                            {
                                int index = chunk.Data.IndexAt(x, y - dy, z);
                                chunk.GetNeighborsManhattan(x, y - dy, z, neighbors);

                                if (neighbors.Any(v => v.WaterLevel > 0))
                                {
                                    waterFound = true;
                                }

                                if (waterFound)
                                {
                                    break;
                                }

                                chunk.Data.Types[index] = 0;
                            }

                            if (!waterFound && caveNoise > CaveSize * 1.8f && y - caveHeight > 0)
                            {
                                int indexunder = chunk.Data.IndexAt(x, y - caveHeight, z);
                                chunk.Data.Types[indexunder]      = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).ID;
                                chunk.Data.Health[indexunder]     = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).StartingHealth;
                                chunk.Data.IsExplored[indexunder] = false;
                                foreach (VegetationData veg in biome.Vegetation)
                                {
                                    if (!MathFunctions.RandEvent(veg.SpawnProbability))
                                    {
                                        continue;
                                    }

                                    if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                                    {
                                        continue;
                                    }


                                    vUnder.GridPosition = new Vector3(x, y - 1, z);
                                    if (!vUnder.IsEmpty && vUnder.TypeName == biome.GrassVoxel)
                                    {
                                        vUnder.Type = VoxelLibrary.GetVoxelType(biome.SoilVoxel);
                                        float offset = veg.VerticalOffset;
                                        if (vUnder.RampType != RampType.None)
                                        {
                                            offset -= 0.25f;
                                        }
                                        float         treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                                        GameComponent entity   = EntityFactory.CreateEntity <GameComponent>(veg.Name, chunk.Origin + new Vector3(x, y, z) + new Vector3(0, treeSize * offset, 0), Blackboard.Create("Scale", treeSize));
                                        entity.GetRootComponent().SetActiveRecursive(false);
                                        entity.GetRootComponent().SetVisibleRecursive(false);
                                        if (GameSettings.Default.FogofWar)
                                        {
                                            ExploredListener listener = new ExploredListener(
                                                PlayState.ComponentManager, entity, PlayState.ChunkManager, vUnder);
                                        }
                                    }
                                }
                            }

                            foreach (FaunaData animal in biome.Fauna)
                            {
                                if (y <= 0 || !(PlayState.Random.NextDouble() < animal.SpawnProbability))
                                {
                                    continue;
                                }


                                var entity = EntityFactory.CreateEntity <GameComponent>(animal.Name, chunk.Origin + new Vector3(x, y, z) + Vector3.Up * 1.0f);
                                entity.GetRootComponent().SetActiveRecursive(false);
                                entity.GetRootComponent().SetVisibleRecursive(false);

                                if (GameSettings.Default.FogofWar)
                                {
                                    ExploredListener listener = new ExploredListener(PlayState.ComponentManager, entity,
                                                                                     PlayState.ChunkManager, chunk.MakeVoxel(x, y, z));
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
コード例 #16
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if (isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();
            int[] ambientValues = new int[4];
            int   maxIndex      = 0;
            int   maxVertex     = 0;
            Voxel v             = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace   = chunk.MakeVoxel(0, 0, 0);

            Voxel[]      manhattanNeighbors = new Voxel[4];
            BoxPrimitive bedrockModel       = VoxelLibrary.GetPrimitive("Bedrock");
            Voxel        worldVoxel         = new Voxel();

            if (Vertices == null)
            {
                Vertices = new ExtendedVertex[1024];
            }

            if (Indexes == null)
            {
                Indexes = new ushort[512];
            }

            for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
            {
                for (int x = 0; x < chunk.SizeX; x++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);


                        if ((v.IsExplored && v.IsEmpty) || !v.IsVisible)
                        {
                            continue;
                        }

                        BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type);
                        if (v.IsExplored && primitive == null)
                        {
                            continue;
                        }
                        if (!v.IsExplored)
                        {
                            primitive = bedrockModel;
                        }

                        Color tint = v.Type.Tint;
                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures && v.IsExplored)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }

                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face  = (BoxFace)i;
                            Vector3 delta = FaceDeltas[(int)face];
                            faceExists[(int)face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                            drawFace[(int)face]   = true;

                            if (faceExists[(int)face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                drawFace[(int)face]      = (voxelOnFace.IsExplored && voxelOnFace.IsEmpty) || !voxelOnFace.IsVisible ||
                                                           (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) &&
                                                            ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));
                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref worldVoxel);
                                drawFace[(int)face] = !success || (worldVoxel.IsExplored && worldVoxel.IsEmpty) || !worldVoxel.IsVisible ||
                                                      (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None &&
                                                       IsSideFace(face) &&
                                                       ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }


                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace)i;
                            if (!drawFace[(int)face])
                            {
                                continue;
                            }


                            int faceIndex   = 0;
                            int faceCount   = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = maxVertex;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert    = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex    bestKey = primitive.Deltas[vertOffset + vertexIndex];
                                Color          color   = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                ambientValues[vertOffset] = color.G;
                                Vector3 offset    = Vector3.Zero;
                                Vector2 texOffset = Vector2.Zero;

                                if (v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if (face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }

                                if (maxVertex >= Vertices.Length)
                                {
                                    ExtendedVertex[] newVertices = new ExtendedVertex[Vertices.Length * 2];
                                    Vertices.CopyTo(newVertices, 0);
                                    Vertices = newVertices;
                                }

                                Vertices[maxVertex] = new ExtendedVertex(vert.Position + v.Position +
                                                                         VertexNoise.GetNoiseVectorFromRepeatingTexture(
                                                                             vert.Position + v.Position) + offset,
                                                                         color,
                                                                         tint,
                                                                         uvs.Uvs[vertOffset + vertexIndex] + texOffset,
                                                                         uvs.Bounds[faceIndex / 6]);
                                maxVertex++;
                            }

                            bool flippedQuad = ambientValues[0] + ambientValues[2] >
                                               ambientValues[1] + ambientValues[3];
                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                if (maxIndex >= Indexes.Length)
                                {
                                    ushort[] indexes = new ushort[Indexes.Length * 2];
                                    Indexes.CopyTo(indexes, 0);
                                    Indexes = indexes;
                                }

                                ushort vertexOffset  = flippedQuad ? primitive.FlippedIndexes[idx] : primitive.Indexes[idx];
                                ushort vertexOffset0 = flippedQuad? primitive.FlippedIndexes[faceIndex] : primitive.Indexes[faceIndex];
                                Indexes[maxIndex] =
                                    (ushort)((int)indexOffset + (int)((int)vertexOffset - (int)vertexOffset0));
                                maxIndex++;
                            }
                        }
                    }
                }
            }
            MaxIndex  = maxIndex;
            MaxVertex = maxVertex;
            GenerateLightmap(chunk.Manager.ChunkData.Tilemap.Bounds);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
コード例 #17
0
ファイル: LiquidPrimitive.cs プロジェクト: scorvi/dwarfcorp
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            //chunk.PrimitiveMutex.WaitOne();
            if(!chunk.IsVisible || IsBuilding)
            {
               // chunk.PrimitiveMutex.ReleaseMutex();
                return;
            }

            IsBuilding = true;
            //chunk.PrimitiveMutex.ReleaseMutex();

            accumulatedVertices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            int[,,] totalDepth = new int[chunk.SizeX, chunk.SizeY, chunk.SizeZ];
            for(int x = 0; x < chunk.SizeX; x++)
            {
                for(int z = 0; z < chunk.SizeZ; z++)
                {
                    bool drynessEncountered = false;
                    int previousSum = 0;

                    for(int y = 0; y < chunk.SizeY; y++)
                    {
                        WaterCell cell = chunk.Data.Water[chunk.Data.IndexAt(x, y, z)];
                        byte waterLevel = cell.WaterLevel;

                        if(cell.Type != LiqType)
                        {
                            waterLevel = 0;
                        }

                        if(drynessEncountered)
                        {
                            if(waterLevel > 0)
                            {
                                drynessEncountered = false;
                                previousSum += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                        }
                        else
                        {
                            if(waterLevel > 0)
                            {
                                previousSum += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                            else
                            {
                                drynessEncountered = true;
                                previousSum = 0;
                                totalDepth[x, y, z] = 0;
                            }
                        }
                    }
                }
            }

            int maxY = chunk.SizeY;

            if(chunk.Manager.ChunkData.Slice == ChunkManager.SliceMode.Y)
            {
                maxY = (int) Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY);
            }

            Voxel myVoxel = chunk.MakeVoxel(0, 0, 0);
            Voxel vox = chunk.MakeVoxel(0, 0, 0);
            for(int x = 0; x < chunk.SizeX; x++)
            {
                for(int y = 0; y < maxY; y++)
                {
                    for(int z = 0; z < chunk.SizeZ; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        if(chunk.Data.Water[index].WaterLevel > 0 && chunk.Data.Water[index].Type == LiqType)
                        {
                            bool isTop = false;

                            myVoxel.GridPosition = new Vector3(x, y, z);

                            for(int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace) i;
                                if(face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                Vector3 delta = faceDeltas[face];

                                bool success = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref vox);

                                if(success)
                                {
                                    if(face == BoxFace.Top)
                                    {
                                        if(vox.WaterLevel == 0 || y == (int) chunk.Manager.ChunkData.MaxViewingLevel)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }
                                    }
                                    else
                                    {
                                        if(vox.WaterLevel == 0 && vox.IsEmpty)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }

                                        bool gotVox = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x, y + 1, z) + chunk.Origin, ref vox);

                                        isTop = !gotVox || vox.IsEmpty || vox.WaterLevel == 0;
                                    }
                                }
                                else
                                {
                                    drawFace[face] = true;
                                }

                                if(!drawFace[face])
                                {
                                    continue;
                                }

                                IEnumerable<ExtendedVertex> vertices = CreateWaterFace(myVoxel, face, chunk, x, y, z, totalDepth[x, y, z], isTop);

                                foreach(ExtendedVertex newVertex in vertices.Select(vertex => new ExtendedVertex(vertex.Position + VertexNoise.GetRandomNoiseVector(vertex.Position),
                                    vertex.Color, vertex.TextureCoordinate, vertex.TextureBounds)))
                                {
                                    accumulatedVertices.Add(newVertex);
                                }
                            }
                        }
                    }
                }
            }

            try
            {
                ExtendedVertex[] vertex = new ExtendedVertex[accumulatedVertices.Count];

                for(int i = 0; i < accumulatedVertices.Count; i++)
                {
                    vertex[i] = accumulatedVertices[i];
                }

                Vertices = vertex;

                chunk.PrimitiveMutex.WaitOne();
                ResetBuffer(graphics);
                chunk.PrimitiveMutex.ReleaseMutex();
            }
            catch(System.Threading.AbandonedMutexException e)
            {
                Console.Error.WriteLine(e.Message);
            }

            IsBuilding = false;
        }
コード例 #18
0
ファイル: ChunkGenerator.cs プロジェクト: svifylabs/dwarfcorp
        public VoxelChunk GenerateChunk(Vector3 origin, int chunkSizeX, int chunkSizeY, int chunkSizeZ, ComponentManager components, ContentManager content, GraphicsDevice graphics)
        {
            float      waterHeight = SeaLevel;
            VoxelChunk c           = new VoxelChunk(Manager, origin, 1,
                                                    Manager.ChunkData.GetChunkID(origin + new Vector3(0.5f, 0.5f, 0.5f)), chunkSizeX, chunkSizeY, chunkSizeZ)
            {
                ShouldRebuild             = true,
                ShouldRecalculateLighting = true
            };

            Voxel voxel = c.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    Vector2 v = new Vector2(x + origin.X, z + origin.Z) / PlayState.WorldScale;

                    Overworld.Biome biome = Overworld.Map[(int)MathFunctions.Clamp(v.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;

                    BiomeData biomeData = BiomeLibrary.Biomes[biome];

                    Vector2 pos         = new Vector2(x + origin.X, z + origin.Z) / PlayState.WorldScale;
                    float   hNorm       = Overworld.GetValue(Overworld.Map, pos, Overworld.ScalarFieldType.Height);
                    float   h           = MathFunctions.Clamp(hNorm * chunkSizeY, 0.0f, chunkSizeY - 2);
                    int     stoneHeight = (int)Math.Max(h - 2, 1);


                    for (int y = 0; y < chunkSizeY; y++)
                    {
                        voxel.GridPosition = new Vector3(x, y, z);
                        if (y == 0)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType("Bedrock");
                            voxel.Health = 255;
                            continue;
                        }

                        if (y <= stoneHeight && stoneHeight > 1)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SubsurfVoxel);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SubsurfVoxel).StartingHealth;
                        }

                        else if ((y == (int)h || y == stoneHeight) && hNorm > waterHeight)
                        {
                            if (biomeData.ClumpGrass &&
                                NoiseGenerator.Noise(pos.X / biomeData.ClumpSize, 0, pos.Y / biomeData.ClumpSize) >
                                biomeData.ClumpTreshold)
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.GrassVoxel);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.GrassVoxel).StartingHealth;
                            }
                            else if (!biomeData.ClumpGrass)
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.GrassVoxel);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.GrassVoxel).StartingHealth;
                            }
                            else
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel).StartingHealth;
                            }
                        }
                        else if (y > h && y > 0)
                        {
                            voxel.Type = VoxelLibrary.GetVoxelType("empty");
                        }
                        else if (hNorm < waterHeight)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel).StartingHealth;
                        }
                        else
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel).StartingHealth;
                        }
                    }
                }
            }


            GenerateCaves(c);
            GenerateWater(c);

            GenerateLava(c);



            c.ShouldRebuildWater = true;
            return(c);
        }
コード例 #19
0
        public static void UpdateRamps(VoxelChunk chunk)
        {
            Dictionary <BoxFace, bool> faceExists  = new Dictionary <BoxFace, bool>();
            Dictionary <BoxFace, bool> faceVisible = new Dictionary <BoxFace, bool>();
            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel vAbove      = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);
            Voxel worldVoxel  = new Voxel();

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);
                        bool isTop = false;


                        if (y < chunk.SizeY - 1)
                        {
                            vAbove.GridPosition = new Vector3(x, y + 1, z);

                            isTop = vAbove.IsEmpty;
                        }


                        if (isTop && !v.IsEmpty && v.IsVisible && v.Type.CanRamp)
                        {
                            for (int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                if (!IsSideFace(face))
                                {
                                    continue;
                                }

                                Vector3 delta = FaceDeltas[face];
                                faceExists[face]  = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                faceVisible[face] = true;

                                if (faceExists[face])
                                {
                                    voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y,
                                                                           z + (int)delta.Z);

                                    if (voxelOnFace.IsEmpty || !voxelOnFace.IsVisible)
                                    {
                                        faceVisible[face] = true;
                                    }
                                    else
                                    {
                                        faceVisible[face] = false;
                                    }
                                }
                                else
                                {
                                    if (!chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X + 0.5f, y + (int)delta.Y + 0.5f, z + (int)delta.Z + 0.5f) + chunk.Origin, ref worldVoxel) || !worldVoxel.IsVisible)
                                    {
                                        faceVisible[face] = true;
                                    }
                                    else
                                    {
                                        faceVisible[face] = false;
                                    }
                                }


                                if (faceVisible[face])
                                {
                                    v.RampType = v.RampType | UpdateRampType(face);
                                }
                            }

                            if (RampIsDegenerate(v.RampType))
                            {
                                v.RampType = RampType.None;
                            }
                        }
                        else if (!v.IsEmpty && v.IsVisible && v.Type.CanRamp)
                        {
                            v.RampType = RampType.None;
                        }
                    }
                }
            }
        }
コード例 #20
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            //chunk.PrimitiveMutex.WaitOne();
            if (!chunk.IsVisible || IsBuilding)
            {
                // chunk.PrimitiveMutex.ReleaseMutex();
                return;
            }

            IsBuilding = true;
            //chunk.PrimitiveMutex.ReleaseMutex();

            accumulatedVertices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            int[,,] totalDepth = new int[chunk.SizeX, chunk.SizeY, chunk.SizeZ];
            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    bool drynessEncountered = false;
                    int  previousSum        = 0;

                    for (int y = 0; y < chunk.SizeY; y++)
                    {
                        WaterCell cell       = chunk.Data.Water[chunk.Data.IndexAt(x, y, z)];
                        byte      waterLevel = cell.WaterLevel;

                        if (cell.Type != LiqType)
                        {
                            waterLevel = 0;
                        }

                        if (drynessEncountered)
                        {
                            if (waterLevel > 0)
                            {
                                drynessEncountered  = false;
                                previousSum        += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                        }
                        else
                        {
                            if (waterLevel > 0)
                            {
                                previousSum        += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                            else
                            {
                                drynessEncountered  = true;
                                previousSum         = 0;
                                totalDepth[x, y, z] = 0;
                            }
                        }
                    }
                }
            }

            int maxY = chunk.SizeY;

            if (chunk.Manager.ChunkData.Slice == ChunkManager.SliceMode.Y)
            {
                maxY = (int)Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY);
            }


            Voxel myVoxel = chunk.MakeVoxel(0, 0, 0);
            Voxel vox     = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        if (chunk.Data.Water[index].WaterLevel > 0 && chunk.Data.Water[index].Type == LiqType)
                        {
                            bool isTop = false;

                            myVoxel.GridPosition = new Vector3(x, y, z);

                            for (int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                Vector3 delta = faceDeltas[face];


                                bool success = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref vox);

                                if (success)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.WaterLevel == 0 && vox.IsEmpty)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }

                                        bool gotVox = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x, y + 1, z) + chunk.Origin, ref vox);

                                        isTop = !gotVox || vox.IsEmpty || vox.WaterLevel == 0;
                                    }
                                }
                                else
                                {
                                    drawFace[face] = true;
                                }


                                if (!drawFace[face])
                                {
                                    continue;
                                }

                                IEnumerable <ExtendedVertex> vertices = CreateWaterFace(myVoxel, face, chunk, x, y, z, totalDepth[x, y, z], isTop);


                                foreach (ExtendedVertex newVertex in vertices.Select(vertex => new ExtendedVertex(vertex.Position + VertexNoise.GetRandomNoiseVector(vertex.Position),
                                                                                                                  vertex.Color, vertex.VertColor, vertex.TextureCoordinate, vertex.TextureBounds)))
                                {
                                    accumulatedVertices.Add(newVertex);
                                }
                            }
                        }
                    }
                }
            }


            try
            {
                ExtendedVertex[] vertex = new ExtendedVertex[accumulatedVertices.Count];

                for (int i = 0; i < accumulatedVertices.Count; i++)
                {
                    vertex[i] = accumulatedVertices[i];
                }


                Vertices = vertex;

                chunk.PrimitiveMutex.WaitOne();
                ResetBuffer(graphics);
                chunk.PrimitiveMutex.ReleaseMutex();
            }
            catch (System.Threading.AbandonedMutexException e)
            {
                Console.Error.WriteLine(e.Message);
            }

            IsBuilding = false;
        }
コード例 #21
0
        public void InitializeFromChunk(VoxelChunk chunk)
        {
            if (IsBuilding)
            {
                return;
            }

            IsBuilding = true;

            int maxY = (int)Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY);


            Voxel myVoxel   = chunk.MakeVoxel(0, 0, 0);
            Voxel vox       = chunk.MakeVoxel(0, 0, 0);
            int   maxVertex = 0;

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        if (GameSettings.Default.FogofWar && !chunk.Data.IsExplored[index])
                        {
                            continue;
                        }

                        if (chunk.Data.Water[index].WaterLevel > 0 && chunk.Data.Water[index].Type == LiqType)
                        {
                            bool isTop = false;

                            myVoxel.GridPosition = new Vector3(x, y, z);

                            for (int i = 0; i < 6; i++)
                            {
                                if (Vertices == null)
                                {
                                    Vertices = new ExtendedVertex[256];
                                }
                                else if (Vertices.Length <= maxVertex + 6)
                                {
                                    ExtendedVertex[] newVerts = new ExtendedVertex[Vertices.Length * 2];
                                    Vertices.CopyTo(newVerts, 0);
                                    Vertices = newVerts;
                                }

                                BoxFace face = (BoxFace)i;
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                Vector3 delta = faceDeltas[(int)face];


                                bool success = chunk.Manager.ChunkData.GetVoxel(chunk,
                                                                                new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref vox);

                                if (success)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel)
                                        {
                                            drawFace[(int)face] = true;
                                        }
                                        else
                                        {
                                            drawFace[(int)face] = false;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.WaterLevel == 0 && vox.IsEmpty)
                                        {
                                            drawFace[(int)face] = true;
                                        }
                                        else
                                        {
                                            drawFace[(int)face] = false;
                                        }

                                        bool gotVox = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x, y + 1, z) + chunk.Origin, ref vox);

                                        isTop = !gotVox || vox.IsEmpty || vox.WaterLevel == 0;
                                    }
                                }
                                else
                                {
                                    drawFace[(int)face] = true;
                                }


                                if (!drawFace[(int)face])
                                {
                                    continue;
                                }

                                CreateWaterFace(myVoxel, face, chunk, x, y, z, isTop, Vertices, maxVertex);
                                maxVertex += 6;
                            }
                        }
                    }
                }
            }

            if (maxVertex > 0)
            {
                try
                {
                    lock (VertexLock)
                    {
                        MaxVertex    = maxVertex;
                        VertexBuffer = null;
                    }
                }
                catch (System.Threading.AbandonedMutexException e)
                {
                    Console.Error.WriteLine(e.Message);
                }
            }
            else
            {
                try
                {
                    lock (VertexLock)
                    {
                        VertexBuffer = null;
                        Vertices     = null;
                        Indexes      = null;
                        MaxVertex    = 0;
                        MaxIndex     = 0;
                    }
                }
                catch (System.Threading.AbandonedMutexException e)
                {
                    Console.Error.WriteLine(e.Message);
                }
            }
            IsBuilding = false;
        }
コード例 #22
0
ファイル: ChunkFile.cs プロジェクト: maroussil/dwarfcorp
        public void FillDataFromChunk(VoxelChunk chunk)
        {
            for(int x = 0; x < Size.X; x++)
            {
                for(int y = 0; y < Size.Y; y++)
                {
                    for(int z = 0; z < Size.Z; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        Voxel vox = chunk.MakeVoxel(x, y, z);
                        WaterCell water = chunk.Data.Water[index];

                        if(vox == null)
                        {
                            Types[x, y, z] = 0;
                        }
                        else
                        {
                            Types[x, y, z] = vox.Type.ID;
                        }

                        if(water.WaterLevel > 0)
                        {
                            Liquid[x, y, z] = water.WaterLevel;
                            LiquidTypes[x, y, z] = (short) water.Type;
                        }
                        else
                        {
                            Liquid[x, y, z] = 0;
                            LiquidTypes[x, y, z] = 0;
                        }
                    }
                }
            }
        }
コード例 #23
0
        // This will loop through the whole world and draw out all liquid primatives that are handed to the function.
        public static void InitializePrimativesFromChunk(VoxelChunk chunk, List <LiquidPrimitive> primitivesToInit)
        {
            LiquidPrimitive[] lps = new LiquidPrimitive[(int)LiquidType.Count];

            // We are going to first set up the internal array.
            foreach (LiquidPrimitive lp in primitivesToInit)
            {
                if (lp != null)
                {
                    lps[(int)lp.LiqType] = lp;
                }
            }

            // We are going to lock around the IsBuilding check/set to avoid the situation where two threads could both pass through
            // if they both checked IsBuilding at the same time before either of them set IsBuilding.
            lock (caches)
            {
                // We check all parts of the array before setting any to avoid somehow setting a few then leaving before we can unset them.
                for (int i = 0; i < lps.Length; i++)
                {
                    if (lps[i] != null && lps[i].IsBuilding)
                    {
                        return;
                    }
                }

                // Now we know we are safe so we can set IsBuilding.
                for (int i = 0; i < lps.Length; i++)
                {
                    if (lps[i] != null)
                    {
                        lps[i].IsBuilding = true;
                    }
                }

                // Now we have to get a valid cache object.
                bool cacheSet = false;
                for (int i = 0; i < caches.Count; i++)
                {
                    if (!caches[i].inUse)
                    {
                        cache       = caches[i];
                        cache.inUse = true;
                        cacheSet    = true;
                    }
                }
                if (!cacheSet)
                {
                    cache       = new LiquidRebuildCache();
                    cache.inUse = true;
                    caches.Add(cache);
                }
            }

            LiquidType      curLiqType   = LiquidType.None;
            LiquidPrimitive curPrimative = null;

            ExtendedVertex[] curVertices = null;
            int[]            maxVertices = new int[lps.Length];
            int maxY = (int)Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY);

            Voxel myVoxel   = chunk.MakeVoxel(0, 0, 0);
            Voxel vox       = chunk.MakeVoxel(0, 0, 0);
            int   maxVertex = 0;
            bool  fogOfWar  = GameSettings.Default.FogofWar;

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        if (fogOfWar && !chunk.Data.IsExplored[index])
                        {
                            continue;
                        }

                        if (chunk.Data.Water[index].WaterLevel > 0)
                        {
                            LiquidType liqType = chunk.Data.Water[index].Type;

                            // We need to see if we changed types and should change the data we are writing to.
                            if (liqType != curLiqType)
                            {
                                LiquidPrimitive newPrimitive = lps[(int)liqType];
                                // We weren't passed a LiquidPrimitive object to work with for this type so we'll skip it.
                                if (newPrimitive == null)
                                {
                                    continue;
                                }

                                maxVertices[(int)curLiqType] = maxVertex;

                                curVertices  = newPrimitive.Vertices;
                                curLiqType   = liqType;
                                curPrimative = newPrimitive;
                                maxVertex    = maxVertices[(int)liqType];
                            }

                            myVoxel.GridPosition = new Vector3(x, y, z);

                            int facesToDraw = 0;
                            for (int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                // We won't draw the bottom face.  This might be needed down the line if we add transparent tiles like glass.
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                Vector3 delta = faceDeltas[(int)face];

                                // Pull the current neighbor Voxel based on the face it would be touching.
                                bool success = myVoxel.GetNeighborBySuccessor(delta, ref vox, false);

                                if (success)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (!(vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel))
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.WaterLevel != 0 || !vox.IsEmpty)
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                }

                                cache.drawFace[(int)face] = true;
                                facesToDraw++;
                            }

                            // There's no faces to draw on this voxel.  Let's go to the next one.
                            if (facesToDraw == 0)
                            {
                                continue;
                            }

                            // Now we check to see if we need to resize the current Vertex array.
                            int vertexSizeIncrease = facesToDraw * 6;
                            if (curVertices == null)
                            {
                                curVertices           = new ExtendedVertex[256];
                                curPrimative.Vertices = curVertices;
                            }
                            else if (curVertices.Length <= maxVertex + vertexSizeIncrease)
                            {
                                ExtendedVertex[] newVerts = new ExtendedVertex[curVertices.Length * 2];
                                curVertices.CopyTo(newVerts, 0);
                                curVertices           = newVerts;
                                curPrimative.Vertices = curVertices;
                            }

                            // Now we have a list of all the faces that will need to be drawn.  Let's draw them.
                            CreateWaterFaces(myVoxel, chunk, x, y, z, curVertices, maxVertex);

                            // Finally increase the size so we can move on.
                            maxVertex += vertexSizeIncrease;
                        }
                    }
                }
            }

            // The last thing we need to do is make sure we set the current primative's maxVertices to the right value.
            maxVertices[(int)curLiqType] = maxVertex;

            // Now actually force the VertexBuffer to be recreated in each primative we worked with.
            for (int i = 0; i < lps.Length; i++)
            {
                LiquidPrimitive updatedPrimative = lps[i];
                if (updatedPrimative == null)
                {
                    continue;
                }

                maxVertex = maxVertices[i];
                if (maxVertex > 0)
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.MaxVertex    = maxVertex;
                            updatedPrimative.VertexBuffer = null;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                else
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.VertexBuffer = null;
                            updatedPrimative.Vertices     = null;
                            updatedPrimative.Indexes      = null;
                            updatedPrimative.MaxVertex    = 0;
                            updatedPrimative.MaxIndex     = 0;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                updatedPrimative.IsBuilding = false;
            }

            cache.inUse = false;
            cache       = null;
        }
コード例 #24
0
        public static void UpdateCornerRamps(VoxelChunk chunk)
        {
            Voxel              v             = chunk.MakeVoxel(0, 0, 0);
            Voxel              vAbove        = chunk.MakeVoxel(0, 0, 0);
            List <Voxel>       diagNeighbors = chunk.AllocateVoxels(3);
            List <VoxelVertex> top           = new List <VoxelVertex>()
            {
                VoxelVertex.FrontTopLeft,
                VoxelVertex.FrontTopRight,
                VoxelVertex.BackTopLeft,
                VoxelVertex.BackTopRight
            };

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < chunk.SizeY; y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);
                        bool isTop = false;


                        if (y < chunk.SizeY - 1)
                        {
                            vAbove.GridPosition = new Vector3(x, y + 1, z);

                            isTop = vAbove.IsEmpty;
                        }

                        if (v.IsEmpty || !v.IsVisible || !isTop || !v.Type.CanRamp)
                        {
                            v.RampType = RampType.None;
                            continue;
                        }
                        v.RampType = RampType.None;

                        foreach (VoxelVertex bestKey in top)
                        {
                            List <Vector3> neighbors = VertexNeighbors2D[bestKey];
                            chunk.GetNeighborsSuccessors(neighbors, (int)v.GridPosition.X, (int)v.GridPosition.Y, (int)v.GridPosition.Z, diagNeighbors);

                            bool emptyFound = diagNeighbors.Any(vox => vox.IsEmpty);

                            if (!emptyFound)
                            {
                                continue;
                            }

                            switch (bestKey)
                            {
                            case VoxelVertex.FrontTopLeft:
                                v.RampType |= RampType.TopBackLeft;
                                break;

                            case VoxelVertex.FrontTopRight:
                                v.RampType |= RampType.TopBackRight;
                                break;

                            case VoxelVertex.BackTopLeft:
                                v.RampType |= RampType.TopFrontLeft;
                                break;

                            case VoxelVertex.BackTopRight:
                                v.RampType |= RampType.TopFrontRight;
                                break;
                            }
                        }
                    }
                }
            }
        }
コード例 #25
0
ファイル: ChunkGenerator.cs プロジェクト: svifylabs/dwarfcorp
        public void GenerateVegetation(VoxelChunk chunk, ComponentManager components, ContentManager content, GraphicsDevice graphics)
        {
            int   waterHeight = (int)(SeaLevel * chunk.SizeY);
            bool  updated     = false;
            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel vUnder      = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    Vector2         vec       = new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z) / PlayState.WorldScale;
                    Overworld.Biome biome     = Overworld.Map[(int)MathFunctions.Clamp(vec.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(vec.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;
                    BiomeData       biomeData = BiomeLibrary.Biomes[biome];

                    int y = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);

                    if (!chunk.IsCellValid(x, (int)(y - chunk.Origin.Y), z))
                    {
                        continue;
                    }

                    v.GridPosition = new Vector3(x, y, z);

                    if (!v.IsEmpty || chunk.Data.Water[v.Index].WaterLevel != 0 || y <= waterHeight)
                    {
                        continue;
                    }

                    foreach (VegetationData veg in biomeData.Vegetation)
                    {
                        if (y <= 0)
                        {
                            continue;
                        }

                        if (!MathFunctions.RandEvent(veg.SpawnProbability))
                        {
                            continue;
                        }

                        if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                        {
                            continue;
                        }

                        int yh = chunk.GetFilledVoxelGridHeightAt(x, y, z);

                        if (yh > 0)
                        {
                            vUnder.GridPosition = new Vector3(x, yh - 1, z);
                            if (!vUnder.IsEmpty && vUnder.TypeName == biomeData.GrassVoxel)
                            {
                                vUnder.Type = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel);
                                updated     = true;
                                float offset = veg.VerticalOffset;
                                if (vUnder.RampType != RampType.None)
                                {
                                    offset -= 0.25f;
                                }
                                float treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                                EntityFactory.CreateEntity <Body>(veg.Name, chunk.Origin + new Vector3(x, y, z) + new Vector3(0, treeSize * offset, 0), Blackboard.Create("Scale", treeSize));
                            }
                        }

                        break;
                    }
                }
            }

            if (updated)
            {
                chunk.ShouldRebuild = true;
            }
        }
コード例 #26
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if (isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();


            accumulatedVertices.Clear();
            accumulatedIndices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);

            Voxel[] manhattanNeighbors = new Voxel[4];
            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);


                        if (v.IsEmpty || !v.IsVisible)
                        {
                            continue;
                        }

                        BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type);

                        if (primitive == null)
                        {
                            continue;
                        }

                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }


                        Voxel worldVoxel = new Voxel();
                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face  = (BoxFace)i;
                            Vector3 delta = FaceDeltas[face];
                            faceExists[face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                            drawFace[face]   = true;

                            if (faceExists[face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                drawFace[face]           = voxelOnFace.IsEmpty || !voxelOnFace.IsVisible || (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));
                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref worldVoxel);
                                drawFace[face] = !success || worldVoxel.IsEmpty || !worldVoxel.IsVisible || (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }


                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace)i;
                            if (!drawFace[face])
                            {
                                continue;
                            }
                            int faceIndex   = 0;
                            int faceCount   = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = accumulatedVertices.Count;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert      = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex    bestKey   = VoxelChunk.GetNearestDelta(vert.Position);
                                Color          color     = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                Vector3        offset    = Vector3.Zero;
                                Vector2        texOffset = Vector2.Zero;

                                if (v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if (face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }


                                ExtendedVertex newVertex = new ExtendedVertex((vert.Position + v.Position + VertexNoise.GetNoiseVectorFromRepeatingTexture(vert.Position + v.Position) + offset),
                                                                              color,
                                                                              uvs.Uvs[vertOffset + vertexIndex] + texOffset, uvs.Bounds[faceIndex / 6]);
                                accumulatedVertices.Add(newVertex);
                            }

                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                int vertexOffset = primitive.Indices[idx];
                                accumulatedIndices.Add((short)(indexOffset + (vertexOffset - primitive.Indices[faceIndex])));
                            }
                        }
                    }
                }
            }


            Vertices = new ExtendedVertex[accumulatedVertices.Count];
            accumulatedVertices.CopyTo(Vertices);
            IndexBuffer = new IndexBuffer(graphics, typeof(short), accumulatedIndices.Count, BufferUsage.WriteOnly);
            IndexBuffer.SetData(accumulatedIndices.ToArray());

            ResetBuffer(graphics);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
コード例 #27
0
ファイル: ChunkGenerator.cs プロジェクト: NakedFury/dwarfcorp
        public VoxelChunk GenerateChunk(Vector3 origin, int chunkSizeX, int chunkSizeY, int chunkSizeZ, ComponentManager components, ContentManager content, GraphicsDevice graphics)
        {
            float      waterHeight = SeaLevel + 1.0f / chunkSizeY;
            VoxelChunk c           = new VoxelChunk(Manager, origin, 1,
                                                    Manager.ChunkData.GetChunkID(origin + new Vector3(0.5f, 0.5f, 0.5f)), chunkSizeX, chunkSizeY, chunkSizeZ)
            {
                ShouldRebuild             = true,
                ShouldRecalculateLighting = true
            };

            Voxel voxel = c.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    Vector2 v = new Vector2(x + origin.X, z + origin.Z) / WorldScale;

                    Overworld.Biome biome = Overworld.Map[(int)MathFunctions.Clamp(v.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;

                    BiomeData biomeData = BiomeLibrary.Biomes[biome];

                    Vector2 pos         = new Vector2(x + origin.X, z + origin.Z) / WorldScale;
                    float   hNorm       = Overworld.LinearInterpolate(pos, Overworld.Map, Overworld.ScalarFieldType.Height);
                    float   h           = MathFunctions.Clamp(hNorm * chunkSizeY, 0.0f, chunkSizeY - 2);
                    int     stoneHeight = (int)Math.Max(h - biomeData.SoilLayer.Depth, 1);

                    int currentGrassLayer      = 0;
                    int currentSoilLayer       = 0;
                    int currentSubsurfaceLayer = 0;
                    int depthWithinSubsurface  = 0;
                    for (int y = chunkSizeY - 1; y >= 0; y--)
                    {
                        voxel.GridPosition = new Vector3(x, y, z);
                        if (y == 0)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType("Bedrock");
                            voxel.Health = 8;
                            continue;
                        }

                        if (y <= stoneHeight && stoneHeight > 1)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SubsurfaceLayers[currentSubsurfaceLayer].VoxelType);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SubsurfaceLayers[currentSubsurfaceLayer].VoxelType).StartingHealth;
                            depthWithinSubsurface++;
                            if (depthWithinSubsurface > biomeData.SubsurfaceLayers[currentSubsurfaceLayer].Depth)
                            {
                                depthWithinSubsurface = 0;
                                currentSubsurfaceLayer++;
                                if (currentSubsurfaceLayer > biomeData.SubsurfaceLayers.Count - 1)
                                {
                                    currentSubsurfaceLayer = biomeData.SubsurfaceLayers.Count - 1;
                                }
                            }
                        }

                        else if ((y == (int)h || y == stoneHeight) && hNorm > waterHeight)
                        {
                            if (biomeData.ClumpGrass &&
                                NoiseGenerator.Noise(pos.X / biomeData.ClumpSize, 0, pos.Y / biomeData.ClumpSize) >
                                biomeData.ClumpTreshold)
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.GrassLayer.VoxelType);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.GrassLayer.VoxelType).StartingHealth;
                            }
                            else if (!biomeData.ClumpGrass)
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.GrassLayer.VoxelType);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.GrassLayer.VoxelType).StartingHealth;
                            }
                            else
                            {
                                voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType);
                                voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType).StartingHealth;
                            }
                        }
                        else if (y > h && y > 0)
                        {
                            voxel.Type = VoxelLibrary.GetVoxelType("empty");
                        }
                        else if (hNorm <= waterHeight)
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel).StartingHealth;
                        }
                        else
                        {
                            voxel.Type   = VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType);
                            voxel.Health = VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType).StartingHealth;
                        }
                    }
                }
            }


            GenerateWater(c);
            GenerateLava(c);
            GenerateCaves(c, components.World);
            //GenerateAquifers(c);
            //GenerateLavaTubes(c);

            c.ShouldRecalculateLighting = true;
            c.ShouldRebuildWater        = true;
            return(c);
        }