Esempio n. 1
0
        public static bool DoesVoxelHaveVisibleSurface(ChunkData Data, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return(false);
            }

            if (!V.IsVisible || V.IsEmpty)
            {
                return(false);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var neighbor = new VoxelHandle(Data, neighborCoordinate);
                if (!neighbor.IsValid)
                {
                    return(true);
                }
                if (neighbor.IsEmpty && neighbor.IsExplored)
                {
                    return(true);
                }
                if (!neighbor.IsVisible)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Run the reveal algorithm without invoking the invalidation mechanism.
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="voxel"></param>
        public static void InitialReveal(
            ChunkManager Manager,
            ChunkData Data,
            VoxelHandle voxel)
        {
            // Fog of war must be on for the initial reveal to avoid artifacts.
            bool fogOfWar = GameSettings.Default.FogofWar;

            GameSettings.Default.FogofWar = true;

            var queue = new Queue <VoxelHandle>(128);

            queue.Enqueue(voxel);

            while (queue.Count > 0)
            {
                var v = queue.Dequeue();
                if (!v.IsValid)
                {
                    continue;
                }

                foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(v.Coordinate))
                {
                    var neighbor = new VoxelHandle(Data, neighborCoordinate);
                    if (!neighbor.IsValid)
                    {
                        continue;
                    }
                    if (neighbor.IsExplored)
                    {
                        continue;
                    }

                    // We are skipping the invalidation mechanism but still need to trigger events.
                    Manager.NotifyChangedVoxel(new VoxelChangeEvent
                    {
                        Type  = VoxelChangeEventType.Explored,
                        Voxel = neighbor
                    });
                    neighbor.RawSetIsExplored();

                    if (neighbor.IsEmpty)
                    {
                        queue.Enqueue(neighbor);
                    }
                }

                v.RawSetIsExplored();
            }

            GameSettings.Default.FogofWar = fogOfWar;
        }
Esempio n. 3
0
        public static void RadiusReveal(
            ChunkManager Data,
            VoxelHandle Voxel,
            int Radius)
        {
            var queue   = new Queue <VisitedVoxel>(128);
            var visited = new HashSet <ulong>();

            if (Voxel.IsValid)
            {
                queue.Enqueue(new VisitedVoxel {
                    Depth = 1, Voxel = Voxel
                });
                Voxel.IsExplored = true;
            }

            while (queue.Count > 0)
            {
                var v = queue.Dequeue();
                if (v.Depth >= Radius)
                {
                    continue;
                }

                foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(v.Voxel.Coordinate))
                {
                    var neighbor = new VoxelHandle(Data, neighborCoordinate);
                    if (!neighbor.IsValid)
                    {
                        continue;
                    }

                    var longHash = neighborCoordinate.GetLongHash();
                    if (visited.Contains(longHash))
                    {
                        continue;
                    }
                    visited.Add(longHash);

                    neighbor.IsExplored = true;

                    if (neighbor.IsEmpty)
                    {
                        queue.Enqueue(new VisitedVoxel
                        {
                            Depth = v.Depth + 1,
                            Voxel = neighbor,
                        });
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Run the reveal algorithm without invoking the invalidation mechanism.
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="voxel"></param>
        public static void InitialReveal(
            ChunkData Data,
            VoxelHandle voxel)
        {
            // Fog of war must be on for the initial reveal to avoid artifacts.
            bool fogOfWar = GameSettings.Default.FogofWar;

            GameSettings.Default.FogofWar = true;

            var queue = new Queue <VoxelHandle>(128);

            queue.Enqueue(voxel);

            while (queue.Count > 0)
            {
                var v = queue.Dequeue();
                if (!v.IsValid)
                {
                    continue;
                }

                foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(v.Coordinate))
                {
                    var neighbor = new VoxelHandle(Data, neighborCoordinate);
                    if (!neighbor.IsValid)
                    {
                        continue;
                    }
                    if (neighbor.IsExplored)
                    {
                        continue;
                    }

                    neighbor.Chunk.NotifyExplored(neighbor.Coordinate.GetLocalVoxelCoordinate());
                    neighbor.RawSetIsExplored(true);

                    if (neighbor.IsEmpty)
                    {
                        queue.Enqueue(neighbor);
                    }
                }

                v.RawSetIsExplored(true);
            }

            GameSettings.Default.FogofWar = fogOfWar;
        }
Esempio n. 5
0
        public static IEnumerable <GlobalVoxelCoordinate> BreadthFirstSearchNonBlocking(
            ChunkManager Data,
            GlobalVoxelCoordinate Start,
            float Radius,
            Func <GlobalVoxelCoordinate, bool> IsGoal)
        {
            var queue         = new Queue <GlobalVoxelCoordinate>();
            var visited       = new HashSet <GlobalVoxelCoordinate>();
            var radiusSquared = Radius * Radius;

            queue.Enqueue(Start);
            visited.Add(Start);

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();

                if (IsGoal(current))
                {
                    yield return(current);

                    yield break;
                }

                var delta = current.ToVector3() - Start.ToVector3();
                if (delta.LengthSquared() < radiusSquared)
                {
                    foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors(current))
                    {
                        var v = new VoxelHandle(Data, neighbor);
                        if (!visited.Contains(neighbor) && v.IsValid && v.IsEmpty)
                        {
                            if (Debugger.Switches.DrawPaths)
                            {
                                Drawer3D.DrawBox(v.GetBoundingBox(), Color.Red, 0.1f, true);
                            }
                            visited.Add(neighbor);
                            queue.Enqueue(neighbor);
                        }
                    }
                }
                yield return(new GlobalVoxelCoordinate(-9999, -9999, -9999));
            }
        }
        public static bool BreadthFirstSearch(
            ChunkData Data,
            GlobalVoxelCoordinate Start,
            float Radius,
            Func <GlobalVoxelCoordinate, bool> IsGoal,
            out GlobalVoxelCoordinate Result)
        {
            var queue         = new Queue <GlobalVoxelCoordinate>();
            var visited       = new HashSet <GlobalVoxelCoordinate>();
            var radiusSquared = Radius * Radius;

            queue.Enqueue(Start);
            visited.Add(Start);

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();

                if (IsGoal(current))
                {
                    Result = current;
                    return(true);
                }

                var delta = current.ToVector3() - Start.ToVector3();
                if (delta.LengthSquared() < radiusSquared)
                {
                    foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors(current))
                    {
                        if (!visited.Contains(neighbor))
                        {
                            visited.Add(neighbor);
                            queue.Enqueue(neighbor);
                        }
                    }
                }
            }

            Result = new GlobalVoxelCoordinate(0, 0, 0);
            return(false);
        }
        public static bool VoxelIsSurroundedByWater(VoxelHandle V)
        {
            if (V.Chunk == null)
            {
                return(false);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var voxelHandle = new VoxelHandle(V.Chunk.Manager, neighborCoordinate);
                if (!voxelHandle.IsValid)
                {
                    return(false);
                }
                if (voxelHandle.IsEmpty && voxelHandle.LiquidLevel < 4)
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 8
0
        public static bool VoxelIsCompletelySurrounded(VoxelHandle V)
        {
            if (V.Chunk == null)
            {
                return(false);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var voxelHandle = new VoxelHandle(V.Chunk.Manager.ChunkData, neighborCoordinate);
                if (!voxelHandle.IsValid)
                {
                    return(false);
                }
                if (voxelHandle.IsEmpty)
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 9
0
        public static bool DoesVoxelHaveVisibleSurface(WorldManager World, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return(false);
            }
            if (V.Coordinate.Y >= World.Master.MaxViewingLevel)
            {
                return(false);
            }
            if (V.IsEmpty)
            {
                return(false);
            }
            if (V.Coordinate.Y == World.Master.MaxViewingLevel - 1)
            {
                return(true);
            }
            if (V.Coordinate.Y == VoxelConstants.ChunkSizeY - 1)
            {
                return(true);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var neighbor = new VoxelHandle(World.ChunkManager.ChunkData, neighborCoordinate);
                if (!neighbor.IsValid)
                {
                    return(true);
                }
                if (neighbor.IsEmpty && neighbor.IsExplored)
                {
                    return(true);
                }
            }

            return(false);
        }
        public static bool DoesVoxelHaveVisibleSurface(WorldManager World, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return(false);
            }
            if (V.Coordinate.Y >= World.Renderer.PersistentSettings.MaxViewingLevel)
            {
                return(false);
            }
            if (V.IsEmpty)
            {
                return(false);
            }
            if (V.Coordinate.Y == World.Renderer.PersistentSettings.MaxViewingLevel - 1)
            {
                return(true);
            }
            if (V.Coordinate.Y == World.WorldSizeInVoxels.Y - 1)
            {
                return(true);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var neighbor = new VoxelHandle(World.ChunkManager, neighborCoordinate);
                if (!neighbor.IsValid)
                {
                    return(true);
                }
                if (neighbor.IsEmpty && neighbor.IsExplored)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 11
0
// This is a more expensive terrain collision method that has fewer problems than the box-collision method.
        // It works by stepping the physics object along the gradient of the terrain field until it is out of collision.
        // It will only work if the object is on the edge of the terrain (i.e exactly one voxel in or less).
        public void ResolveTerrainCollisionGradientMethod()
        {
            Vector3 localGradient = Vector3.Zero;

            var p = Position;

            localGradient  = Position - CurrentVoxel.Center;
            localGradient += Velocity; // Prefer to push in the direction we're already going.
            foreach (var v in VoxelHelpers.EnumerateManhattanNeighbors(CurrentVoxel.Coordinate))
            {
                var handle = new VoxelHandle(World.ChunkManager, v);
                var sign   = (handle.IsValid && handle.IsEmpty) ? -1 : 1;
                localGradient += (p - handle.Center) * sign;
            }

            p += localGradient * 0.01f;
            Matrix m = LocalTransform;

            m.Translation  = p;
            LocalTransform = m;
            Velocity      += localGradient * 0.01f;
            PropogateTransforms();
            UpdateBoundingBox();
        }
Esempio n. 12
0
        public override IEnumerable <Status> Run()
        {
            PerchTime.Reset();
            WanderTime.Reset();
            TurnTime.Reset();
            while (true)
            {
                if (State == FlyState.Perching)
                {
                    PerchTime.Reset();
                    while (!PerchTime.HasTriggered)
                    {
                        Agent.Creature.Physics.Velocity     = Vector3.Zero;
                        Agent.Creature.CurrentCharacterMode = CharacterMode.Idle;
                        PerchTime.Update(DwarfTime.LastTime);
                        yield return(Act.Status.Running);
                    }
                    // When we're done flying, go back to walking and just fall.
                    Agent.Creature.CurrentCharacterMode = CharacterMode.Walking;
                    Agent.Creature.Physics.Gravity      = OriginalGravity;
                    yield return(Act.Status.Success);
                }

                Agent.Creature.Physics.Gravity = Vector3.Zero;
                // Store the last position of the bird to sample from
                Vector3 oldPosition = Agent.Position;

                // Get the height of the terrain beneath the bird.
                var surfaceHeight = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                         Agent.Chunks.ChunkData, GlobalVoxelCoordinate.FromVector3(oldPosition)))
                                    .Coordinate.Y + 1;

                // Immediately start flying.
                Agent.Creature.CurrentCharacterMode = CharacterMode.Flying;

                // Use this to determine when to start turning.
                float currentDistance = 999;

                {
                    // Pick a target within a box floating some distance above the surface.
                    float randomX = MathFunctions.Rand() * Radius - Radius / 2.0f;
                    float randomZ = MathFunctions.Rand() * Radius - Radius / 2.0f;
                    float randomY = (float)MathFunctions.Random.NextDouble() * YRadius + Altitude + surfaceHeight;

                    // Set the target to that random location.
                    LocalTarget = new Vector3(randomX + oldPosition.X, randomY, randomZ + oldPosition.Z);
                }


                // Keep flying until a timer has trigerred.
                while ((!WanderTime.HasTriggered && State == FlyState.Wandering) || (State == FlyState.SearchingForPerch))
                {
                    // If we hit the ground, switch to walking, otherwise switch to flying.
                    Agent.Creature.CurrentCharacterMode = CharacterMode.Flying;

                    WanderTime.Update(DwarfTime.LastTime);

                    // If we're near a target, or a timeout occured, pick a new ranodm target.
                    if (TurnTime.Update(DwarfTime.LastTime) || TurnTime.HasTriggered || currentDistance < TurnThreshold)
                    {
                        // Pick a target within a box floating some distance above the surface.
                        float randomX = MathFunctions.Rand() * Radius - Radius / 2.0f;
                        float randomZ = MathFunctions.Rand() * Radius - Radius / 2.0f;
                        float randomY = (float)MathFunctions.Random.NextDouble() * YRadius + Altitude + surfaceHeight;

                        // Set the target to that random location.
                        LocalTarget = new Vector3(randomX + oldPosition.X, randomY, randomZ + oldPosition.Z);
                    }

                    // Set the current distance to the target so we know when to go to a new target.
                    currentDistance = (Agent.Position - LocalTarget).Length();

                    // Output from the force controller.
                    Vector3 output =
                        Creature.Controller.GetOutput((float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds,
                                                      LocalTarget, Creature.Physics.GlobalTransform.Translation);

                    // We apply a linear combination of the force controller and the
                    // feed forward force to the bird to make it lazily turn around and fly.
                    Creature.Physics.ApplyForce(output * Damping * GravityCompensation,
                                                (float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds);


                    if (State == FlyState.Wandering && WanderTime.HasTriggered)
                    {
                        State = FlyState.SearchingForPerch;
                    }

                    if (State == FlyState.SearchingForPerch)
                    {
                        var vox = Creature.Physics.CurrentVoxel;
                        if (!vox.IsValid)
                        {
                            yield return(Act.Status.Running);

                            continue;
                        }
                        if (vox.IsValid && vox.WaterCell.WaterLevel > 0)
                        {
                            yield return(Act.Status.Running);

                            continue;
                        }

                        if (CanPerchOnGround)
                        {
                            Creature.Physics.ApplyForce(OriginalGravity, (float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds);
                            var below = new VoxelHandle(Creature.World.ChunkManager.ChunkData,
                                                        vox.Coordinate + new GlobalVoxelOffset(0, -1, 0));

                            if (below.IsValid && !below.IsEmpty && below.WaterCell.WaterLevel == 0)
                            {
                                State = FlyState.Perching;
                                continue;
                            }
                        }

                        if (CanPerchOnWalls)
                        {
                            foreach (var n in VoxelHelpers.EnumerateManhattanNeighbors(Creature.Physics.CurrentVoxel.Coordinate)
                                     .Select(c => new VoxelHandle(Creature.World.ChunkManager.ChunkData, c)))
                            {
                                if (n.IsValid && n.Coordinate.Y >= vox.Coordinate.Y && !n.IsEmpty)
                                {
                                    State = FlyState.Perching;
                                }
                            }
                        }

                        /*
                         * if (CanPerchOnObjects)
                         * {
                         *  List<Body> objetcs = new List<Body>();
                         *  PlayState.ComponentManager.GetBodiesIntersecting(Creature.Physics.BoundingBox, objetcs, CollisionManager.CollisionType.Static);
                         *
                         *  if (objetcs.Count > 0)
                         *  {
                         *      State = FlyState.Perching;
                         *      continue;
                         *  }
                         * }
                         */
                    }

                    yield return(Status.Running);
                }

                yield return(Status.Running);
            }
        }