Top Banner
Polygon Soup for Polygon Soup for the Programmer’s the Programmer’s Soul: 3D Soul: 3D Pathfinding Pathfinding Patrick Smith (psmith@westwood.com) Greg Hjelstrom (greg@westwood.com)
49

Polygon Soup for the Programmer’s Soul: 3D Pathfinding Patrick Smith (psmith@westwood.com) Greg Hjelstrom (greg@westwood.com)

Jan 12, 2016

Download

Documents

Marsha Hicks
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • Polygon Soup for the Programmers Soul: 3D PathfindingPatrick Smith (psmith@westwood.com)Greg Hjelstrom (greg@westwood.com)

  • IntroductionAI is an important contributor to the realism of games.Pathfinding is a major component of convincing AI.

  • Problem DomainPathfinding requires connectivity.A streetmap is a real-life example.Given this connectivity graph, paths can be found using well known algorithms such as A*.How do we get this connectivity data?

  • Connectivity SolutionsIn grid-based games the grid inherently provided the connectivity data.RTS games.Many 3D games use manual connectivity.Manually placed points and connections between points.Automatic connectivity.How?

  • Floodfilling to the Rescue!Well reuse old 2D paint program technology the recursive floodfill.For our purposes the floodfill is really a recursive physics simulation of an AI moving between points.The goal: given a seed point, detect all traversable locations in a level.

  • The Floodfill AlgorithmSimulate the AI moving in each of the 4 cardinal directions.Add each successful position to a list.Mark this position as traversable.Store the connection between positions.Pop the head of the list and recurse into it.

  • Movement SimulationThe character is represented by an axis aligned collision box.Our collision code uses swept boxes.The floodfill algorithm performs tens of millions of swept box queries so we need to make them fast.

  • Colliding with the WorldWe use a hierarchical bounding volume tree to quickly determine what meshes in the world need to be checked for collision.Each mesh contains an internal bounding volume tree to quickly determine which of its triangles need to be checked for collision.For speed and space, we use axis aligned bounding boxes.

  • Swept Box CollisionSeparating axis theoremGiven two convex polyhedra, if they are not intersecting at least one separating plane will exist.The plane normal will be defined by either:One of the faces of either objectThe cross product of two edges, one from each objectEarly rejection. Once you find a separating plane, you can reject the triangle.This algorithm can be extended to support swept convex primitives, providing time of collision.

  • Making a MoveDuring the floodfill, to move one unit in any given direction, we must successfully complete the following steps:Move up the maximum height the AI can step over.Sweep the collision box one unit in the movement direction at an angle equal to the steepest slope the AI can climb.Finally, sweep the collision box back down to the ground to see if we have a place to stand.

  • Of Units and PositionsOur pathfinding system will make good use of the AIs collision box.Unit of Distance:A unit is of the AIs collision box.Position:A position is the volume defined by splitting the collision box into four equal pieces.

  • Visualizing the DataEach position is a box.Each unit moves one box length away.This forms a sort of grid.However, since the floodfill can travel over and under overpasses there can be more then one cell for every x,y position on the grid.

  • What the Data Gives UsEach cell knows which directions it can travel (up, down, left, right).This linkage forms a connectivity graph of all possible traversable locations in the level.Given this connectivity graph we can now use our favorite shortest path algorithm to pathfind between any two points in the level.

  • Too Much Data!A typical level might require in excess of 2 million cells.This can require upwards of 128 MB of RAM just to store the graph.This is way too much data for a real time game.

  • CompressionThe goal is to combine cells into largest possible rectangular regions.

  • SectorsCompressed cells become sectors.Sectors are 3D axis-aligned boxes that the pathfind system can use to determine where an AI is in the connectivity graph.Sectors need connection data to other sectors.

  • PortalsPortals are connections between sectors.Portals can be one-way or two-way.Portals have a physical location in the world.Because of this, an AI simple needs to walk to the portal, at which point they are at the destination sector.This allows us to easily integrate teleporters such as doors, ladders, elevators, or even star-trek like teleporters.How do we generate these portals?

  • Portal GenerationDuring the compression stage, we store a list of edge cells with each sector.Each edge cell also stores which sector it belongs to.

  • Portal GenerationOnce all sectors have been generated, the edge cells can then be converted into portals.These portals know what sector they are coming from and which sector they are going to.

  • Data SummaryFloodfill the world by simulating the AI walking in a recursive pattern.Compress the millions of floodfill cells into sectors.Use the edge cells of a sector to generate portals between sectors.

  • Floodfill Demo

  • Extending the PathsolveLets consider a few pieces of information we can bake into our pathfind data that will allow us to easily path solve across teleporters such as doors, elevators, and ladders.A teleporter is a feature of the level that, when activated, will transport a game object from one part of the world to the other.

  • Floodfilling across TeleportersConsider a building with roof access via elevator only.Currently, the pathsolve will never reach the roof.To solve this:During floodfill, check each cell to see if its inside an entrance zone.Create a cell inside the exit zone for the elevator and continue floodfilling from this cell.

  • Pathsolving Across TeleportersIncorporate teleporters post floodfill. Each teleporter has an entrance and exit zone. For each teleporter in the level, check to see if both the entrance and exit zones intersect a pathfind sector.Create a teleporter portal and add it to the portal list for the entrance sector.Create a portal and add it to the portal list for the exit sector.Link the entrance portal to the exit portal as a one-way transition.

  • Teleport Portal DataEmbed as much information about the teleporter as necessary into the entrance portal.Flag specifying teleporter type.Door, elevator, ladder, etc.Teleporter mechanism ID.Keys needed to operate mechanism.

  • Solving the PathGiven our connectivity graph, solving the path is now straightforward.Given an AIs current position and a destination position we can lookup the pathfind sectors that contain these points. Path is unsolvable if either sector cannot be found.We now have a start position and end position within our connectivity graph.

  • The Pathsolve AlgorithmMost traditional shortest path algorithms can be used.A modified A* worked pretty good for Renegade.First, loop over all the portals for the starting sector.Each portal has a destination sector.Each of these destination sectors has a list of portals.Continue traversing sectors until youve reached the destination sector.

  • Path Demo

  • Time to SolveShort paths can solve quickly.Long paths take a bit longer.20 AIs solving long paths at the same time can tax even the most efficient pathsolver.

  • Distributing the SolveIf an AI takes 15 frames to solve a path in a 30 FPS game, they will only pause for a second.In most cases, this short pause is not noticeable.This means we can devote a set amount of time each frame to pathfinding and simply solve as much of each path as possible.

  • The Distributed AlgorithmThe pseudo-algorithm:

    while (Time_Left () && PathSolver != NULL) { if (PathSolver->Process (Time_Left_This_Frame)) { RELEASE (PathSolver); PathSolver = Get_Next_Path_Solver (); }}

  • The Distributed AlgorithmThe pseudo-algorithm:while (Time_Has_Not_Elapsed) {CPathfindSector * sector = Get_Least_Cost_Sector ();if (sector == NULL) {Handle_No_Path ();} else if (sector == DestinationSector) {Hande_Path_Found ();} else {CPathfindPortal *portal = NULL;while (portal = sector->Get_Next_Portal (portal)) { Process_Portal (portal);} }}

  • Robotic PathsThe results of this path solve will often look robotic.Straight lines connecting points in the portals along the path.This path can be made more organic by creating a spline which goes through its points.

  • Smoothing the PathWe chose to use a natural spline whose control points are points along the path. Unfortunately this can cause the path to stray outside of valid pathfind sectors; causing characters to get stuck against walls for example.To solve this problem, we convert the spline into a series of Bezier curves and constrain the control points to our pathfind sectors.A Bezier curve is guaranteed to be contained by the convex shape defined by its control points.

  • Visualizing the Spline

  • Innate WaypathsWaypaths are hand-placed paths consisting of a series of points.Waypaths can be linear or splined, one-way, two-way, and looping.Each point on the waypath can encode specific information such as speed up, slow down, jump, crouch, slide, crawl, etc.The path solver can bias towards these waypaths to achieve complex results.

  • Using Innate WaypathsCreate a pathfind sector without position or size.Intersect each point on the waypath with sectors that already exist in the world.Create portals at each intersection point that exit from the real-world sectors onto the imaginary innate waypath sector.Intersect each segment of the waypath with sector boundaries that already exist in the world.Create portals at these intersections as well.Flag these portals so the shortest path heuristic can make them cheaper to follow.

  • Waypath Demo

  • Learning From the PlayerPlayers can conceive of more complicated actions than AI.By allowing the AI to copy some of the players moves, they appear more intelligent.

  • Implementing LearningEverytime the player jumps and lands:Lookup the pathfind sector the player jumped from and landed in.Record the players orientation and velocity at jump time.Add a temporary jump portal from the start sector to the land sector.The AI will now seamlessly incorporate this move into its pathsolve.

  • Learning Demo

  • Vehicle PathfindingVehicles are intrinsically more difficult.Vehicles are bigger than characters.Vehicles have turn radius.Vehicles do not stop on a dime.Vehicles can roll over.Vehicles behave differently in forwards and reverse.

  • Re-using DataVehicles can reuse bipedal data.Take into consideration the vehicles turn radius when evaluating portals.If a vehicle cannot make a turn, coming from its current portal to the destination portal, then skip the destination portal.

  • Vehicle CurvesVehicles need to turn out to make sharp corners.By creating a vehicle curve that is based on the turn radius of the vehicle, the vehicle will seamlessly follow its path.Vehicle curve is composed of three parts:The exit curve from the previous point.A straight line from the exit curve to the entrance curve of the next point.The entrance curve to the next point.

  • Vehicle Curve AnatomyHere you can see the 3 distinct parts of the vehicle curve.

  • Vehicle Curve ResultsHere is a comparison of a linear (unsplined) vehicle path and the post-processed vehicle curve.

  • Vehicle Demo

  • ConclusionFloodfill solves static pathfinding.Kinks in the path arise due to the non-uniform nature of the sectors.Does not address dynamic objects.Innate waypaths and jump portals increase intelligence.Arbitrary vehicle pathfinding is difficult.Reusing data is possible, but not optimal.Vehicle curves simplify the path following logic.

  • Q & A