public IEnumerable <Body> EnumerateIntersectingObjects(BoundingBox box, CollisionType queryType) { PerformanceMonitor.PushFrame("CollisionManager.EnumerateIntersectingObjects"); var hash = new HashSet <Body>(); OctTree.EnumerateItems(box, hash, t => (t.CollisionType & queryType) == t.CollisionType); PerformanceMonitor.PopFrame(); return(hash); }
public void RenderInstances( GraphicsDevice Device, Shader Effect, Camera Camera, InstanceRenderer.RenderMode Mode) { int uniqueInstances = 0; RenderPass += 1; var frustrum = Camera.GetFrustrum(); foreach (var item in OctTree.EnumerateItems(frustrum)) { if (!item.Visible) { continue; } if (item.RenderPass < RenderPass) { uniqueInstances += 1; Renderer.RenderInstance(item, Device, Effect, Camera, Mode); } item.RenderPass = RenderPass; } Renderer.Flush(Device, Effect, Camera, Mode); GamePerformance.Instance.TrackValueType("Instances Drawn", uniqueInstances); }
// Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel. // Very, very slow. public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, OctTreeNode OctTree) { if (Parent == null) { yield break; } var creature = Creature; if (creature == null) { yield break; } var current = currentstate.Voxel; if (Can(MoveType.Teleport)) { var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter")); foreach (var obj in teleportObjects) { if ((obj.Position - current.WorldPosition).LengthSquared() > 2) { continue; } for (int dx = -TeleportDistance; dx <= TeleportDistance; dx++) { for (int dz = -TeleportDistance; dz <= TeleportDistance; dz++) { for (int dy = -TeleportDistance; dy <= TeleportDistance; dy++) { if (dx * dx + dy * dy + dz * dz > TeleportDistanceSquared) { continue; } VoxelHandle teleportNeighbor = new VoxelHandle(Parent.World.ChunkManager.ChunkData, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz)); if (teleportNeighbor.IsValid && teleportNeighbor.IsEmpty && !VoxelHelpers.GetNeighbor(teleportNeighbor, new GlobalVoxelOffset(0, -1, 0)).IsEmpty) { yield return(new MoveAction() { InteractObject = obj, Diff = new Vector3(dx, dx, dz), SourceVoxel = teleportNeighbor, DestinationState = currentstate, MoveType = MoveType.Teleport }); } } } } } } foreach (var v in VoxelHelpers.EnumerateCube(current.Coordinate) .Select(n => new VoxelHandle(current.Chunk.Manager.ChunkData, n)) .Where(h => h.IsValid && h.IsEmpty)) { foreach (var a in GetMoveActions(new MoveState() { Voxel = v }, OctTree).Where(a => a.DestinationState == currentstate)) { yield return(a); } if (!Can(MoveType.RideVehicle)) { continue; } // Now that dwarfs can ride vehicles, the inverse of the move actions becomes extremely complicated. We must now // iterate through all rails intersecting every neighbor and see if we can find a connection from that rail to this one. // Further, we must iterate through the entire rail network and enumerate all possible directions in and out of that rail. // Yay! var bodies = new HashSet <Body>(); OctTree.EnumerateItems(v.GetBoundingBox(), bodies); var rails = bodies.OfType <Rail.RailEntity>().Where(r => r.Active); foreach (var rail in rails) { if (rail.GetContainingVoxel() != v) { continue; } /* * if (!DwarfGame.IsMainThread) * { * for (int i = 0; i < 1; i++) * { * Drawer3D.DrawBox(rail.GetBoundingBox(), Color.Purple, 0.1f, false); * System.Threading.Thread.Sleep(1); * } * } */ foreach (var neighborRail in rail.NeighborRails.Select(neighbor => creature.Manager.FindComponent(neighbor.NeighborID) as Rail.RailEntity)) { var actions = GetMoveActions(new MoveState() { Voxel = v, VehicleState = new VehicleState() { Rail = rail, PrevRail = neighborRail } }, OctTree); foreach (var a in actions.Where(a => a.DestinationState == currentstate)) { yield return(a); /* * if (!DwarfGame.IsMainThread && a.MoveType == MoveType.RideVehicle) * { * for (int i = 0; i < 10; i++) * { * Drawer3D.DrawBox(rail.GetBoundingBox(), Color.Red, 0.1f, false); * System.Threading.Thread.Sleep(1); * } * } */ } } foreach (var a in GetMoveActions(new MoveState() { Voxel = v, VehicleState = new VehicleState() { Rail = rail, PrevRail = null } }, OctTree).Where(a => a.DestinationState == currentstate)) { yield return(a); } } } }
/// <summary> gets the list of actions that the creature can take from a given voxel. </summary> public IEnumerable <MoveAction> GetMoveActions(MoveState state, OctTreeNode OctTree) { if (Parent == null) { yield break; } var voxel = state.Voxel; if (!voxel.IsValid || !voxel.IsEmpty) { yield break; } var creature = Creature; if (creature == null) { yield break; } var neighborHood = GetNeighborhood(voxel.Chunk.Manager.ChunkData, voxel); bool inWater = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold); bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty); bool topCovered = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty); bool hasNeighbors = HasNeighbors(neighborHood); bool isRiding = state.VehicleState.IsRidingVehicle; var neighborHoodBounds = new BoundingBox(neighborHood[0, 0, 0].GetBoundingBox().Min, neighborHood[2, 2, 2].GetBoundingBox().Max); var neighborObjects = new HashSet <Body>(); OctTree.EnumerateItems(neighborHoodBounds, neighborObjects); var successors = EnumerateSuccessors(state, voxel, neighborHood, inWater, standingOnGround, topCovered, hasNeighbors, isRiding, neighborObjects); if (Can(MoveType.Teleport)) { var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter")); foreach (var obj in teleportObjects) { if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared) { yield return(new MoveAction() { InteractObject = obj, MoveType = MoveType.Teleport, SourceVoxel = voxel, DestinationState = new MoveState() { Voxel = new VoxelHandle(voxel.Chunk.Manager.ChunkData, GlobalVoxelCoordinate.FromVector3(obj.Position)) } }); } } } // Now, validate each move action that the creature might take. foreach (MoveAction v in successors) { var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z]; if (n.IsValid && (isRiding || n.IsEmpty || n.LiquidLevel > 0)) { // Do one final check to see if there is an object blocking the motion. bool blockedByObject = false; if (!isRiding) { var objectsAtNeighbor = neighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox())); // If there is an object blocking the motion, determine if it can be passed through. foreach (var body in objectsAtNeighbor) { var door = body as Door; // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault(); // If there is an enemy door blocking movement, we can destroy it to get through. if (door != null) { if ( creature.World.Diplomacy.GetPolitics(door.TeamFaction, creature.Faction) .GetCurrentRelationship() == Relationship.Hateful) { if (Can(MoveType.DestroyObject)) { yield return(new MoveAction { Diff = v.Diff, MoveType = MoveType.DestroyObject, InteractObject = door, DestinationVoxel = n, SourceState = state }); } blockedByObject = true; } } } } // If no object blocked us, we can move freely as normal. if (!blockedByObject && n.LiquidType != LiquidType.Lava) { MoveAction newAction = v; newAction.SourceState = state; newAction.DestinationVoxel = n; yield return(newAction); } } } }
// Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel. // Very, very slow. public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, OctTreeNode OctTree, List <Body> teleportObjects) { if (Parent == null) { yield break; } if (Creature == null) { yield break; } var current = currentstate.Voxel; if (Can(MoveType.Teleport)) { foreach (var obj in teleportObjects) { if ((obj.Position - current.WorldPosition).LengthSquared() > 2) { continue; } for (int dx = -TeleportDistance; dx <= TeleportDistance; dx++) { for (int dz = -TeleportDistance; dz <= TeleportDistance; dz++) { for (int dy = -TeleportDistance; dy <= TeleportDistance; dy++) { if (dx * dx + dy * dy + dz * dz > TeleportDistanceSquared) { continue; } VoxelHandle teleportNeighbor = new VoxelHandle(Parent.World.ChunkManager.ChunkData, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz)); if (teleportNeighbor.IsValid && teleportNeighbor.IsEmpty && !VoxelHelpers.GetNeighbor(teleportNeighbor, new GlobalVoxelOffset(0, -1, 0)).IsEmpty) { yield return(new MoveAction() { InteractObject = obj, Diff = new Vector3(dx, dx, dz), SourceVoxel = teleportNeighbor, DestinationState = currentstate, MoveType = MoveType.Teleport }); } } } } } } var storage = new MoveActionTempStorage(); foreach (var v in VoxelHelpers.EnumerateCube(current.Coordinate) .Select(n => new VoxelHandle(current.Chunk.Manager.ChunkData, n)) .Where(h => h.IsValid)) { foreach (var a in GetMoveActions(new MoveState() { Voxel = v }, OctTree, teleportObjects, storage).Where(a => a.DestinationState == currentstate)) { yield return(a); } if (!Can(MoveType.RideVehicle)) { continue; } // Now that dwarfs can ride vehicles, the inverse of the move actions becomes extremely complicated. We must now // iterate through all rails intersecting every neighbor and see if we can find a connection from that rail to this one. // Further, we must iterate through the entire rail network and enumerate all possible directions in and out of that rail. // Yay! // Actually - why not just not bother with rails when inverse pathing, since it should only be invoked when forward pathing fails anyway? var bodies = new HashSet <Body>(); OctTree.EnumerateItems(v.GetBoundingBox(), bodies); var rails = bodies.OfType <Rail.RailEntity>().Where(r => r.Active); foreach (var rail in rails) { if (rail.GetContainingVoxel() != v) { continue; } foreach (var neighborRail in rail.NeighborRails.Select(neighbor => Creature.Manager.FindComponent(neighbor.NeighborID) as Rail.RailEntity)) { var actions = GetMoveActions(new MoveState() { Voxel = v, VehicleState = new VehicleState() { Rail = rail, PrevRail = neighborRail } }, OctTree, teleportObjects, storage); foreach (var a in actions.Where(a => a.DestinationState == currentstate)) { yield return(a); } } foreach (var a in GetMoveActions(new MoveState() { Voxel = v, VehicleState = new VehicleState() { Rail = rail, PrevRail = null } }, OctTree, teleportObjects, storage).Where(a => a.DestinationState == currentstate)) { yield return(a); } } } }