Nagivation mesh construction and path finding for architecture environment

145 173 0
Nagivation mesh construction and path finding for architecture environment

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

NAVIGATION MESH CONSTRUCTION AND PATH_FINDING FOR ARCHITECTURE ENVIRONMENT MAO LEI NATIONAL UNIVERSITY OF SINGAPORE 2010 NAVIGATION MESH CONSTRUCTION AND PATH_FINDING FOR ARCHITECTURE ENVIRONMENT MAO LEI (B.Comp.(Hons), NUS) A THESIS SUBMITTED FOR THE DEGREE OF MASTER OF SCIENCE DEPARTMENT OF COMPUTER SCIENCE NATIONAL UNIVERSITY OF SINGAPORE 2010 Acknowledgementsttttttttttttttttttttttttttttttttttttttttttttttttttttt Firstly, I would like to show my appreciation to National University of Singapore and School of Computing for providing this research opportunity and scholarship for me. Secondly, great thanks to my supervisor, A/P Tan Tiow Seng who gave me great help in this research project and also during the whole graduate life with his invaluable guidance and constant support. Special thanks to Dr Low Kok Lim and Dr Cheng Ho-lun, for their guidance and help during my graduate life in which I have learned a lot. I would also like to acknowledge my thanks to all people in computer graphics lab, and we have great time in last few years. Last but not least, I would like to thank my family who encourage me with constant love and support. i Table of Contentsttttttttttttttttttttttttttttttttttttttttttttttttttttttt Acknowledgements i Summary Chapter 1 Introduction ix …..……………………………………………… 1 1.1 Motivation and Goal ………………………………………………... 1 1.2 Contribution …………………………………………………………. 5 1.3 A Statement of the Problem ………………………………………. 7 1.4 Thesis Structure …………………………………………………….. 8 Chapter 2 Related Works and Background ……………………………… 9 2.1 Search Space Representation ……………………………………….. 9 2.1.1 Raw Geometry Representation ……………………………… 9 2.1.2 Path Lattice Representation …………………………………... 12 2.1.3 Grid Representation and Hexagonal Representation ……….. 17 ………………………….. 20 …………………………………………….. 23 2.2.1 Precomputed Transition Table ………………………………. 23 2.2.2 A* Search ……………………………………………………… 28 2.1.4 Navigation Mesh Representation 2.2 Path Finding Algorithm Chapter 3 Navigation Mesh Construction ………………………………. 40 …………………………………………………. 43 3.1.1 Delete Useless Objects ……………………………...………… 43 3.1.2 Modify Complicated Objects 46 3.1 Selecting Process ………………………………. ii 3.1.3 Select Walkable Surface 3.1.4 Concluding Remark …………………………………… ………………………………………. 51 52 3.2 Merging Process ……………………………………………………… 53 3.2.1 Adjacent Merging …………………………………………….. 54 3.2.2 3-2 Merging …………………………………………………. 56 3.2.3 Central Point Merging ……………………………………….. 61 3.2.4 Concluding Remar ……………………………………….. 64 3.3 Sub-division Process ………………………………………………… 65 3.3.1 Recursive Sub-division Approach …………………………. 66 ……………………………… 69 ……………………………………….. 74 ……………………………………………………... 75 3.5 Multiple Levels Construction ……………………………………….. 77 3.5 Concluding Remark ………………………………………………… 79 3.3.2 New Sub-division Approach 3.3.3 Concluding Remark 3.4 Reconstruction Chapter 4 Path Finding Problem ………………………………………... 81 4.1 Path Finding on Navigation Mesh …………………………………… 84 4.1.1 A* Search Path Finding Process ……………………………..... 84 4.1.2 Path Correction Process …………………………………… 90 4.2 Two-Level Path Finding …………………………………………….. 94 4.2.1 Proof on the Time Consuming of Two-Level Path Finding …... 96 4.2.2 Implementation on Two-Level Path Finding ………………… 100 4.3 Concluding Remark …………………………………………………. 106 Chapter 5 System Built, Experiments Results and Analysis ……………. 107 ………………………………………... 107 ……………………………………………………… 107 5.1 Tools and Libraries Used 5.1.1 OGRE 5.1.2 COLLADA DOM ………………………………………... 109 …………………………………………………. 109 5.1.4 GPC …………………………………………………………... 110 5.1.3 WxWidget iii 5.2 Experiment Results and Analysis on Navigation Mesh Construction 111 5.3 Experiment Results and Analysis on Two-Level Path Finding ……….. 117 5.4 More Experiment Results …………………………………………….. 122 Chapter 6 Conclusion References …………………………………………………….... 129 131 iv List of Figurestttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Figure 1.1.1 an architecture environment (Hospital hall) ……………….. 2 Figure 1.1.2 an architecture environment (Indoor room) ……………….. 3 Figure 2.1.1 path lattice representation ………………………………….. 13 Figure 2.1.2 path lattice representation, to find a path from location 1 to location 2 …………………………………………………………. 14 Figure 2.1.3 path lattice representation, to find a path from location 1 to location 2 through a new added path node (location 3) …………... Figure 2.1.4 grid representation for search space representation 15 ………. 17 Figure 2.1.5 hexagonal representation for search space representation …... 17 Figure 2.1.6 navigation mesh representation …………………………… 20 Figure 2.2.1 a simple navigation mesh map ………………………………... 24 Figure 2.2.2 the transition table for the navigation mesh map in Figure 2.2.1 25 Figure 2.2.3 a simple scene of gird representation 29 ………………………. v Figure 2.2.4 beginning of A* search ……………………………………... 31 Figure 2.2.5 first step of A* search ……………………………………….. 34 Figure 2.2.6 second step of A* search …………………………………... 36 Figure 2.2.7 last step of A* search ……………………………………….. 37 Figure 2.2.8 final path 38 ………………………………………………… Figure 3.1.1 an indoor room, with a rug carpet on the floor …………… 44 Figure 3.1.2 an indoor room, after the rug carpet has been removed ….. 44 Figure 3.1.3 an indoor room; choose a chair with its bounding box ….. 47 Figure 3.1.4 an indoor room; represent one chair with the cover polygon of its bounding box …………………………………………….. 48 Figure 3.1.5 an indoor room; choose all the chairs and the table ……….. 49 Figure 3.1.6 an indoor room; represent the chairs and the table with the cover polygon of their bounding box ………………………………. 49 Figure 3.2.1 merging polygons into a single convex polygon ……………. 54 Figure 3.2.2 converting three convex polygons into two convex polygons 56 Figure 3.2.3 merging of mixed shapes …………………………………… 57 vi Figure 3.2.4 example for 3-2 merging …………………………………… 58 Figure 3.2.5 converting three convex polygons into one convex polygon 61 Figure 3.2.6 one point shared with four adjacent convex polygons ….. 63 ……………….... 66 Figure 3.3.1 sub-division triangles and quadrilaterals Figure 3.3.2 a floor polygon with walls is sub-divided recursively, and re-merge ……………………………………………………………………... 69 Figure 3.3.3 an optimal mesh sub-division for example shown in Figure 3.3.2 ……………………………………………………………………... Figure 4.1.1 zigzag problem in path construction ……………………... 70 92 Figure 4.2.1 best cast for sub-division for small obstacles ……………. 97 Figure 4.2.2 worst cast for sub-division for small obstacles ……………. 98 Figure 4.2.3(a) convex polygon with four obstacle polygons ……………. 101 Figure 4.2.3(b) the first-level OOBB bounding box for all four polygons 102 Figure 4.2.3(c) the second-level OOBB bounding boxes, the first one for the two obstacle polygons in the left side, and the second one for the two obstacle polygons in the right side ……………………. 102 Figure 4.2.3(d) the third-level OOBB bounding boxes, each bounding box is for each single obstacle polygon ………………………… 103 vii Figure 4.2.4 correcting a path according to an obstacle polygon ……… 105 Figure 5.2.1 a small dining room example …………………………….. 111 Figure 5.2.2 the result of merging process …………………………….. 112 Figure 5.2.3 the result of sub-division from Figure 5.2.2 ………………. 113 Figure 5.2.4 the result of sub-division From Figure 5.2.2, as taking the chairs and tables as small obstacles ………………………… 113 Figure 5.2.5 a level of a building ………………………………………. 114 Figure 5.2.6 the result after merging process from Figure 5.2.5 ……… 114 Figure 5.2.7 the result of sub-division from Figure 5.2.6 ……………….. 116 Figure 5.3.1 a basic path finding example …………………………....... 117 Figure 5.3.2 another basic path finding example ………………………… 118 Figure 5.3.3 path merging result from Figure 5.3.1 ……………………. 119 Figure 5.3.4 path merging result from Figure 5.3.2 ……………………. 120 Figure 5.3.5 a two-level path finding example ………………………… 121 Figure 5.3.6 another two-level path finding example ……………………. 121 Figure 5.4.1 a soap-factory example 122 ………………………………….. viii Figure 5.4.2 merging result in soap-factory example ……………………... 122 Figure 5.4.3 navigation mesh result in soap-factory example ……………. 123 Figure 5.4.4 path finding in soap-factory example (example 1) ……….. 123 Figure 5.4.5 path finding in soap-factory example (example 2) ……….. 124 Figure 5.4.6 a maze example …………………………………………….. 125 Figure 5.4.7 merging process in maze example ………………………….. 126 Figure 5.4.8 navigation mesh result in maze example ………………… 126 Figure 5.4.9 path finding in maze example (example 1) ………………… 127 Figure 5.4.10 path finding in maze example (example 2) ………………… 127 ix Summaryttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt With the fast development of computer science technology, path finding is kept a hot topic in research area; especially it plays an important role in game industry, video and film industry, and large model simulation. However, these approaches and underlying data structure construction are not suitable for all the situations. In this thesis, we present an approach to semi-automatically construct an underlying structure (Navigation Mesh) in the pre-computing phase, and use a two-level path-finding algorithm during the real searching time for an architecture environment. There are many path-finding algorithm approaches with their underlying data structure which represents the real walkable world for game, video and film. However, the problem arises in architecture environment is very different with these situations. In a large hospital, hotel or airports, we need to more concentrate on those small obstacles as tables, chairs, or beds, rather than the un-smooth walkable surface in games or videos. The number of these obstacles is enormous in architecture environment so that we must be careful to choose the underlying data structure construction and also the relative path-finding. In our approach, we construct a navigation mesh data structure for the underlying walkable surface with only relatively large obstacles and leave enormous number of small obstacles in the two-level path-finding phase. We will show that the real x searching time will be faster in two-level path-finding approach instead of normal path-finding approach but with bigger number of navigation meshes as we must sub-divide large navigation mesh into lots of small pieces with the enormous number of small obstacles. Keywords: Algorithms, Navigation Mesh, Path Finding, Data Structures, Computer Graphics Implemented Software and Hardware: Microsoft Visual Studio 2005 C++, OpenGL, Ogre, Collada, gpc (General Clipping Library), wxWidgets(A GUI Library) xi Chapter 1ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Introduction 1.1 Motivation and Goal Path finding in the context of games and films concerns the way in which a moving entity finds a path around an obstacle; the most important feature of path finding is real-time. Path finding has grown in very importance as games, films and their environments have become more complex. Real-time strategy games typically contain large areas of open terrain which is often relatively simple to route across. There is small number of obstacles around in a big open area. At its core, a path finding method searches a graph by starting at one point and exploring adjacent nodes until the destination node is reached, generally with the intent of finding the shortest route. Although graph searching methods such as a breath-first search would find a route if given enough time, other methods, which explorer the graph, would tend to reach the destination sooner. An analogy would be a person walking across a room; rather than examining every possible route in advance, the person would generally walk in the direction of the destination and only deviate from the path to avoid an obstruction, and make deviations as minor as possible. A common example of a graph-based path finding algorithm is Dijkstra's algorithm. 1 This algorithm begins with a start node and an "open set" of candidate nodes. At each step, the node in the open set with the lowest distance from the start is examined. The node is marked "closed", and all adjacent nodes are added to the open set if they have not already been examined. This process repeats until a path to the destination has been found. Since the lowest distance nodes are examined first, the first time the destination is found, the path to it will be the shortest path. Figure 1.1.1 an architecture environment (Hospital hall, take from website http://www.hospiten.es/hospiten/HOSPITEN/published_en/DEFAULT/node_66.jsp?S ECID=21&CATID=90&PRDID=10772) 2 Figure 1.1.2 an architecture environment (Indoor room, take from http://sociallysuperlative.com/2008/10/16/showtime-gramercy-mansion/) We can see that the real time consuming mainly depends on the number of nodes you need to go through. However, there is enormous number of small obstacles in an architecture environment (As shown in Figure 1.1.1 and 1.1.2). That refers to we need more nodes to represent the walkable area in order to avoid these obstacles. If we use the common used path finding algorithms, whatever data structures we use for the underlying data structure, we either need to use more nodes to guarantee the accuracy of the final result but more time consuming, or we construct less nodes by ignoring some obstacles to guarantee fast time consuming but less accuracy of the final result. This gives us motivation to find a more flexible approach to solve this kind of problems. If we can keep fewer nodes as in big terrain or outside field, and do not increase the real searching time much for accuracy path finding, then we can perfectly 3 deal this situation in architecture environment. Our approach is to use navigation mesh to represent the underlying data structure, only for the walkable surface with big and obvious obstacles but leave the small and unambitious obstacles for later processing. We can show that this will save the searching time, as the time we consume for checking these small obstacles in path finding phase, is much less than the time we consume for transferring more nodes because of these small obstacles in most situations. We will prove this in later chapter in the thesis. This thesis focuses on the underlying data structure construction, and the path finding algorithm for an architecture environment. During the underlying data structure construction, we choose navigation mesh as basics, and divide the walkable surface according to the big and obvious obstacles, but leave the small and unambitious obstacles for later path finding phase. Then we use a two-level path finding approach for real time searching. That is to use common used path finding algorithm on the underlying navigation mesh structure, and then check those small obstacles for the finding path. Our goal is to do the real time searching as fast as possible and guarantee the accuracy meantime. 4 1.2 Contribution The main contribution of our work is the idea of splitting the obstacles in an architecture environment into two parts. The first part with big and obvious obstacles will be processed in the underlying data structure process to get a clear walkable surface. The second part with small and unambitious obstacles will be checked after the path which has already been found to correct the finding path. We will show that the time consuming under this approach is less than the traditional approach which process all the obstacles together in the underlying data structure construction process, and then use a common path finding algorithm. The main difference is the number of nodes that increased by the sub-division of the small obstacles will be far more than the number of small obstacles we will need to check in the path finding process. This approach can decrease the real searching time in most situations. Our approach is mainly based on architecture environment which has enormous number of obstacles as chairs, desks, and sofas, and so on. 5 6 1.3 A Statement of the Problem Basically, the problem we need to solve is that we need to find a route for users from a specified starting location to a specified terminating location in a large 3D architecture model. It involves two sub problems. One is we need to decide which data structure is suitable to use in order to represent the underlying walkable surface accurately, and also flexible for later phase’s processing. The other one is how to search for a shortest route normally according to a starting point and terminating point on the constructed data structure with fastest time consuming. In this thesis, we only consider these architecture models are represented as triangle based 3D models. Summarize the above, the problem is: Given an architecture environment model of a set of triangle meshes in 3D, a starting point and a terminating point in 3D, construct a most neat and clear data structure for walkable surface, and find a shortest path from the starting point to the ending point with fastest time consuming. 7 1.4 Thesis Structure The rest of the thesis is organized as follows: Chapter 2 describes the related work and gives some survey of the background knowledge on search space representation and path finding process. Chapter 3 describes the procedure on construction of navigation mesh from a set of triangle meshes as input Chapter 4 describes the procedure of path finding on the navigation mesh and proposes the algorithm of two-level path finding. Chapter 5 concludes the whole thesis. 8 Chapter 2ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Related Work and Background This thesis studies how to build a search space representation for an architecture environment, and process a real time path finding in the constructed search space representation. Our approach is to construct a navigation mesh representation for the walkable surface in an architecture environment with relatively big and obvious obstacles, and process a two-level path finding algorithm to find out the route. The based requirement we talk about in this thesis is on the architecture environment with enormous number of obstacles. This chapter introduces the existing search space representation approaches to represent the walkable surface of a 3D model, and the path finding algorithms. 2.1 Search Space Representation. 2.1.1 Raw Geometry Representation. This is possible to process a path finding algorithm on raw geometry of the virtual world. This approach is that we did very few modifications on the raw geometry of the virtual world (delete all those polygons which are not walkable, and find out a base height for the base walkable surface) before the path finding process. 9 This approach is the most naïve one for search space representation. That refers to we nearly do nothing in the search space representation construction part. It is a very easy work in space representation construction, but leaves all the difficulties and problems into the path finding part. One severe problem is that we cannot recognize correctly of the walkable surfaces against the obstacles. Suppose the model is a set of triangle meshes in 3D space, the only information we can retrieve is the height value of each triangle mesh. This does not help us telling which piece of triangle mesh can be walkable, but another piece of triangle mesh cannot be walkable. Another severe problem is the time consuming of real path finding process. Normally there are millions of triangle meshes for a single large level. The time consuming for us to find a route from a starting point to a terminating point will be very long as we need to traverse most part of the meshes, and need to differentiate different part of the model. Anyway, we can find a more accurate path from the raw geometry representation against other search space representations, because the raw geometry representation illustrates the natural representation of the model. However, we will not use this representation in most cases as because it cannot finish path finding process in real 10 time, and it will make the path finding algorithm too complicated. 11 2.1.2 Path Lattice Representation. In [01], the article talked about a technique to a path finding approach in a specific search space representation, named path lattice (the points of visibility). A path lattice approach begins with scattering a number of points throughout the whole 3D world. These are the initial “path nodes”. Usually, these are manually placed in the level by the level designer himself. Then the editor will examine all the lines between all these path nodes placed in this level to determine whether it is possible to walk in a straight line from any path node to any other. For any lines which can be walkable, we donate it as an edge; otherwise ignore this line. Then the designer can use this resulting network to find a path from any node to any other. As shown in figure 2.1.1, the whole structure is one level of the virtual world, and the green nodes are the designer placed path nodes, and the light blue lines are the walkable paths. 12 Figure 2.1.1 path lattice representation However, the path lattice approach has some severe limitations in practice. First is the problem of path node placement. Most path lattice systems rely on level designer to place path nodes in the architecture model they create manually. This can create an enormous amount of work for the level designers in a very large model, adding significant productivity overhead for every new level a designer creates. It also introduces a significant potential source of errors, since the path finding process must now depend on the level designers in order to achieve basic competence. Some systems automatically place path nodes in a level. However, these are rare and are seldom able to achieve the results that a human can achieve by placing the path 13 nodes manually. Second is the problem of limited representation. The path lattice only contains data indicating which locations in the virtual world are directly connected to which other locations. Once we attempt to move to a location that does not have a path node nearby, the lattice is essentially useless. It has no way of knowing there the walls are. It is incapable of realizing that there is a big pillar standing in the middle of three path nodes connected in a triangle. And the moment we encounter a dynamic obstacle (such as a crate or another AI character), our path lattice becomes useless, and we must query the virtual world directly. Figure 2.1.2 path lattice representation, to find a path from location 1 to location 2 14 Figure 2.1.3 path lattice representation, to find a path from location 1 to location 2 through a new added path node (location 3) The main limitation of the path lattice approach is that it frequently generates low-quality movement paths. All the paths must follow the walkable “edges” that have been already created. As shown in Figure 2.1.2, if we want to find a path from location 1 to location 2, we need to traverse the path nodes which are already existed. The red edges are one solution that we will find from path lattice approach. This seems abnormal from human being’s view. The more proper way is we need to plant one more path nodes (location 3) as shown in figure 2.1.3. Then this introduces another problem that is how many path nodes are enough to express the whole level surface properly. 15 The path lattice approach also suffers from serious problems with combinatorial explosion. Because our preprocessor needs to test all the lines between any two path nodes in the model, it will become an N2 problem for this test. It is quite unacceptable for a large model with enormous amount of point nodes. So clearly, this can lead to very long computing time for an architecture model, also with potential severe errors according to the amount of manual work. The problem is exacerbated by the fact that we usually need to insert mode path nodes to make the final movement look better, and this puts the path quality against the performance. 16 2.1.3 Grid Representation and Hexagonal Representation [02] Introduces a simple way to represent a search space is with a regular structure to represent the search space. Normally use grid representation or hexagonal representation, as shown in figure 2.1.4 and figure 2.1.5. Figure 2.1.4 grid representation for search space representation Figure 2.1.5 hexagonal representation for search space representation. 17 The advantage of grid representation and hexagonal representation is that they are easier to build the space search representation. As all the shape of the units is the same, the only process we need to do is to check whether this unit can be walkable or not. This is done by checking the boundary of the walkable surfaces and obstacles. However, the accuracy of the representation depends on the size of each unit. If the size is smaller, then the representation is more accurate, vice versa. We can carefully check the boundary of the surfaces and obstacles, there are many units occupy both the inside space and the outside space of the boundary lines. Then all these units must be considered as un-walkable. If the size of each unit is big, we will definitely lose lots of walkable space. If the seize of each unit is small, we will lose few of the walkable space, but this will introduce another problem which is the time consuming for path finding. Grid representation and hexagonal representation are limited in that they often require a large number of unit cells to adequately represent a virtual world as we discussed in the previous paragraph. Larger virtual world and higher-resolution unit cells increase the total number of cells used in the space search representation, which increase the search space representation’s memory and can make the real time path finding very slow. Also, the grid representation and hexagonal representation cannot completely cover all the walkable surfaces in the virtual world as we shown in the figures. 18 Grid representation and hexagonal representation based system can also suffer from path quality issues as a result of the underlying representation. If AI agents can only walk along the four cardinal directions between neighboring unit cells (assuming this representation is a grid representation), this will likely result in unattractive angular paths composed entirely of straight lines and 90-degree turns. 19 2.1.4 Navigation Mesh Representation Figure 2.1.6 navigation mesh representation [03] talks about the basic idea of navigation mesh representation. A navigation mesh representation is a representation the covers the whole walkable surfaces of the virtual world with convex polygons. As shown in Figure 2.1.6. The navigation mesh representation has certain key advantages. One is the navigation mesh representation can cover every walkable surface that any AI in the virtual world could reasonably be expected to walk on. And the navigation mesh representation attempts to cover the walkable surface of the virtual world with something reasonably close to the fewest possible of polygons. 20 The navigation mesh representation allows us to reliably find the optimal paths for AIs with various shapes and movement capabilities. The navigation mesh representation can handle indoor environment and expansive outdoor terrain equally well. The main disadvantage of a navigation mesh representation is that it can require storage of a large number of polygons, particularly in expansive and geometrically complex environment. However, the walkable surface of the architecture is not as that complex as the outdoor terrain we normally see in the game. That lets us avoid this disadvantage as much as possible. The guarantee of the convexity is essential. Convex polygons allow us to guarantee that an AI can freely walk in a straight line from any point within a polygon to any other point within the same polygon. Each polygon is therefore a node in the search graph, and the links between adjacent polygons are the edges of the graph. Also the navigation mesh representation is more flexible for path finding process. Note that it is generally not feasible to use the raw geometry itself for path finding process, as this will be unnecessarily complex. Because of all the advantages of the navigation mesh representation and the avoidance of the disadvantage, we will choose the navigation mesh representation as our search space representation for architecture environment with improvements in the 21 construction process of the navigation mesh representation. 22 2.2 Path Finding Algorithm Path finding algorithm is essential in modern games, films, AI systems. There are several ways to do path finding process. We will talk about two popular approaches in this part, which are precomputed transition table and A* search. 2.2.1 Precomputed Transition Table Precomputed solutions for path finding are rapidly gaining favor in modern games, AI systems. Dynamic path finding is expensive on CPU time, and developers would very much like to find a way to spend more of the valuable CPU cycles on the bigger problems. Precomputed navigation information accomplishes this by almost completely eliminating the runtime cost of path finding. The basic component of the precomputed path finding scheme is a lookup table that effectively encodes the best paths between every pair of nodes in a level. This lookup table is called a transition table, because each of the entries represents the next step in the path from some source node toward a specific goal node. In other words, for every pair of nodes S and G, the table entry [S][G] gives the index of the node that should be visited next when moving from S to G. The precomputed path finding has been described in [04]. 23 As an example, consider the simple navigation mesh map in Figure 2.2.1, which shows a network of nodes including connectivity information and path costs. The circles represent navigation mesh nodes, and arrows represent connecting edges. Each number along an edge is the cost to traverse the edge. Figure 2.2.1 a simple navigation mesh map. 24 For this simple navigation mesh networks, we can describe a complete best-path solution using a transition table, as shown in Figure 2.2.2. Source Node Goal Node 1 2 3 4 5 6 7 8 1 1 2 3 3 2 3 2 2 2 1 2 1 1 5 1 5 5 3 1 1 3 4 4 4 4 4 4 3 3 3 4 6 6 6 6 5 2 2 8 8 5 8 8 8 6 4 5 4 4 5 6 5 5 7 8 8 8 8 8 8 7 8 8 3 5 3 3 5 3 7 8 Figure 2.2.2 the transition table for the navigation mesh map in Figure 2.2.1. To determine the best path from one node to another, we simply do a serious of lookups into the table that gives us each of the steps (or transitions) from the source node to the goal node. For example, to determine the best path from node 3 to node 8, we first look at the [3][8] entry in the transition table, which is 4. Now we’ve reduced the problem to determining the best path from node 4 to node 8. The transition table entry for [4][8] gives us 6, which is the next node on the path. We continue in this fashion until the transition table returns the goal node, at which point we have the complete path solution. In this example, the final path solution is 3, 4, 6, 5, and 8. 25 Using the transition table, the actual code for determining a best path is very simple. Indeed: void buildBestPath(int source, int goal, list& path) { path.push_back(source); while (source != goal) { Source = transitionTable[source][goal]; path.push_back(source); } } As indicated in the code example, the process of building the path from source to goal is simply a series of table lookups. This is significantly faster than performing a full search at runtime whenever a path is needed. Of course, any precomputed solution comes with a price: memory. Today’s virtual world levels are enormous, and even well optimized navigation mesh maps can contain literally thousands of nodes. The sheer volume of information can render a very attractive preprocessed solution completely unfeasible otherwise, especially on console platforms where memory is at premium, while a transition table like that in Figure 2.2.2 gives us fast best path determination, a similar table for a large 26 navigation mesh map could be prohibitive in size. A large virtual level can easily contain a thousand navigation mesh nodes or more. The corresponding table would require n2 = 1,000,000 entries, potentially using several megabytes of precious memory. This could be even more if we need to carry the data for the whole virtual world except just one level. Then this makes us unable to accomplish this as it takes too much memory. To compare the A* search we talk about later, it may be faster a bit, but memory price cost is too much. 27 2.2.2 A* Search In computer science, A* search is a computer algorithm that is widely used in path finding and graph traversal, the process of plotting an efficiently traversable path between points, called nodes. A* uses a best-first search and finds the least-cost path from a given source node to one goal node. It uses a distance-plus-cost heuristic function (usually denoted f(x)) to determine the order in which the search visits nodes in the tree. The distance-plus-cost heuristic is a sum of two functions: The path-cost function, which is the cost from the starting node to the current node (usually denoted g(x)) and an admissible "heuristic estimate" of the distance to the goal node (usually denoted h(x)). The h(x) part of the f(x) function must be an admissible heuristic; that is, it must not overestimate the distance to the goal. Thus, for an application like routing, h(x) might represent the straight-line distance to the goal, since that is physically the smallest possible distance between any two points or nodes. 28 We take a small example to illustrate the idea of A* search here. Let’s assume we have a virtual world within a wall in the middle of the virtual world. Our aim is to walk from a starting point A to a terminating point B. As shown in Figure 2.2.3, with red being the starting point A, and blue being the ending point B, and the yellow filled squares being the wall in between. (As described in [21]) Figure 2.2.3 a simple scene of gird representation As in this small and simplified example, we just donate each node in the search space as a square. Simplifying the search area as we done here is the first step of path finding which we will preprocess the raw geometry into navigation meshes in our architecture model. The goal here is that we want to find a path from square A to square B avoid walking through the blue wall. Our path is represented as the squares which we need to traverse in order to reaching B from A. Here, we are using the centre point system to illustrate our simplest A* search 29 algorithm. The centre point system is that whenever we want to calculate the distance of any two squares, we use their centre point as variables. And also the final path will be represented as from one centre point of a square to another centre point of the adjacent square. The main purpose in this section is to illustrate the idea of A* search. Before the algorithm process, we first create two lists: “open list”, and “closed list”. The “open list” means all the potential squares which will be checked according to the current square, and the “closed list” means all the potential squares which will be in the final path. We begin the search by doing the following: 1. We begin with the starting square A. we put square A into the “open list”. The “open list” is kind of shopping list, that we need to check all the items here to decide which one possibly can be added into the final path. Initially, we just put square A as it is the starting square. 2. Then look at all the squares which are adjacent to the starting square A. If they are walkable as donated in black color in the figure 2.2.3, we put them into the “open list”. If they are un-walkable (like walls, obstacles, etc), we just ignore these squares. And we set all the adjacent squares’ parent as the starting square 30 A here, that will help us to trace the final path. 3. Drop square A from the “open list” and put it into the “closed list”. Square A must be in the final path comparing with all other squares in the “open list”, thus we need to put it into the “closed list” at first. At this point, we should have something as illustrated as the following figure. The red square which is outlined by dark green is our starting square A. The dark green outline indicates that this square is in the “closed list”. And all the adjacent black squares which are outlined in orange are in the “open list”. Each has a green pointer that points back to its parent, which is the starting square. As shown in Figure 2.2.4. Figure 2.2.4 beginning of A* search The key to determining which squares to be chosen to the final path is the following equation: 31 F = G + H (as we explained previously) where G = the movement cost to move from the starting point A to a given square on the grid, following the path generated to get there. H = the estimated movement cost to move from that given square on the grid to the final destination, square B. We really don’t know the actual distance until we find the path, thus we just estimate the value here. Our path is generated by repeatedly going through our open list and choosing the square with the lowest F value. This process will be described in more detail a bit further later. First let’s look more closely at how we calculate the equation. As described above, the G value is the movement cost to move from the starting point to a given square on the grid. In this simple example, we set 10 for each horizontal or vertical move from one square to an adjacent square, and set 14 for a diagonal move from one square to an adjacent diagonal square. As the actual distance is root of 20 for a diagonal move, which is 14.141 roughly, and for simple calculation and avoid square root computation, we set 14 for a diagonal move here. 32 Here we just calculate the G value in a very specific route from the parent square to its adjacent square. It will cost the final path looking not that smooth according to the specific route we set here. However, our goal is to find out the final path here, so we will talk about these path corrections in the real algorithm later. H can be estimated in a variety of ways. The method we use here is called the Manhattan method, where we calculate the total number of squares moved horizontally and vertically to reach the target square from the current square, ignoring diagonal movement, and ignoring any obstacles that may be in the way. We are actually trying to estimate the remaining distance along the path (which is usually farther). The closer our estimate is to the actual remaining distance, the faster the algorithm will be. If we overestimate this distance, however, it is not guaranteed to give us the shortest path. In this example, using “Manhattan method” will slightly overestimate the actual distance we need to traverse. This caused the problem that the final path we find out may be not the shortest. However, talking about other methods beyond our scope here, we using “Manhattan method” to illustrate our basic A* search here. Even with a bit overestimation, the final path will still be near shortest. 33 Figure 2.2.5 first step of A* search F is calculated by adding G and H. The results of the first step in our search can be seen in Figure 2.2.5. The F, G, and H scores are written in each square. As is indicated in the square to the immediate right of the starting square, F is printed in the top left, G is printed in the bottom left, and H is printed in the bottom right. We examine the Figure 2.2.5; those squares which are left or right to the starting square have the G value 10 (horizontally); those squares which are up or down to the starting square have the G value 10 (vertically); and all the remaining squares have the G value 14 (diagonally). 34 The H scores are calculated by estimating the Manhattan distance to the red target square, moving only horizontally and vertically and ignoring the wall that is in the way. So by this method, we look at the square which is right to the starting square has the H value 30, as it has 3 horizontal squares from the terminating square. And the square which is up to the starting square has the G value 50, as it has 1 vertical square and 4 horizontal squares from the terminating square. The F score for each square, again, is simply calculated by adding G and H together. As shown in Figure 2.2.5, on the top left for each adjacent squares. To continue the search, we simply choose the lowest F score square from all those that are on the open list. We then do the following with the selected square: 1. Drop it from the open list and add it to the closed list. 2. Check all the adjacent squares to the current square. If the square is already in the “closed list” or is un-walkable, then ignore it. Then if the square is not in the “open list”, put it into the “open list”, calculate its G, H, and F value, and set its parent to the current square. 3. If an adjacent square is already in the “open list”, then we check whether the current path is better than the previous path. That is, we calculate the G, H, F 35 value of this adjacent square according to the current square. If the F value is smaller than the previous, update all the values, and set the parent to the current square; if not, then we keep the previous values for this adjacent square. In our current “open list”, we have 8 squares which are adjacent to the starting square. From these, we choose the square with the smallest F value which is the square right to the starting square with F value 40. It is highlight in blue in Figure 2.2.6 . Figure 2.2.6 second step of A* search This time, when we check the adjacent squares we find that the one to the immediate right is a wall square, so we ignore that. The same goes for the one just above that. We also ignore the square just below the wall. 36 That leaves five other squares. We follow the instructions we have described above, and we can just adjust those adjacent squares to the current squares which are already in the “open list”. We ignore the three adjacent squares which are wall as they are un-walkable; also we ignore the starting square as it is already in the “closed list”. Figure 2.2.7 last step of A* search We repeat this process until we add the target square to the closed list, at which point it looks something like Figure 2.2.7. Note that the parent square for the square two squares below the starting square has been changed from the previous illustration. Before it had a G score of 28 and pointed back to the square above it and to the right. Now it has a score of 20 and points to the square just above it. This will always happen during our search especially for a large 37 searching space. Most of the times, we will find out a better path than the previous path according to a specific search nodes, so we will need to change is parent in order to change the path direction. At this stage, we reach the terminating square. Now we traverse from the terminating square according to its parent. In such backwards search, we will eventually reach the starting square which is square A. Then this is our final path that we are looking for. As shown in Figure 2.2.8. Moving from the starting square A to the destination square B is simply a matter of moving from the center of each square (the node) to the center of the next square on the path, until we reach the target. Figure 2.2.8 final path As we illustrated in this part, A* works well in real time path finding strategy. It 38 processes fast and do not occupy extra memory as precomputed transition table in our built system, we use A* search as main search strategy to find the path. 39 Chapter 3ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Navigation Mesh Construction In this chapter, we will talk about the navigation mesh construction process in detail. A navigation mesh structure is a set of convex polygons that describe the “walkable” surface of a 3D environment. It is simple, highly intuitive “floor plan” that AI characters can use for navigation and path finding in the virtual world. So our goal is to illustrate the whole walkable surface in the virtual world into a set of convex polygons, where the number of the polygons is as less as possible. And our assumption here is that the input model consists of triangle meshes. Someone might be wondering why it is necessary for the polygons to be convex. Convexity is the only way we can guarantee that an AI character can move in a straight line from any point in the polygon to any other. A navigation mesh path consists of a list of adjacent nodes to travel on. Convexity allows us to guarantee that with a valid path, an AI character can simply walk in a straight line from each node to the next one on the list. The problem of finding the simplest set of convex polygons to cover a given area is referred to as the optimal convex partition problem in computational geometry. The best known algorithm so far to solve this problem is in O(n3logn), which can refer to 40 paper [06], which means very, very slow in programming. For a very large level in virtual world, we may need take days to finish computing a simpler convex polygon representation for one level. This is not realistic and practical in practice. That’s why we lose benefit of simplest, or called optimal solution for this problem, but get a near optimal solution with much, much faster computing time in O(e+n), where e is the number of edges in the virtual world, and n is the number of points. The algorithm presented here is based on the previous navigation mesh construction algorithm, which can refer to article [07]. Although the algorithm the article presented does not guarantee that we end up with the absolute minimum number of polygons covering the floor surface, it is guaranteed to give us no more than four times the minimum number. After we improve this algorithm by more steps of merging and more optimal sub-division process, we believe that the number of convex polygons can reduce further. It is also very fast, with the appropriate data structure. It can be performed in leaner time. The basic algorithm can be summarized as follows: 1. Begin with a set of triangle meshes which represent the walkable surface. 41 2. Remove those edges between two polygons which can come up with a convex polygon. 3. Repeat until we can no longer perform step 2. This is basic for process the underlying walkable surface. We will need to take care of the obstacles. These obstacles normally do not belong to the underlying walkable surface. We need to subtract these obstacles from the underlying constructed navigation meshes. This step is referred to sun-division process. We organize this chapter as follows: 3.1 will talk about selecting process, 3.2 will talk about convex polygon merging process, 3.3 will talk about sub-division process, and 3.4 will talk about reconstruction process when the underlying raw geometry has been changed. 42 3.1 Selecting Process In this part, we begin the whole algorithm by selecting those triangle meshes which are potentially walkable surface, or the surface of obstacles, also delete those definitely useless triangle meshes, and modify some complicated triangle meshes into simpler representation. This part includes 3 consecutive processes, 3.1.1 will show the process of deleting the useless triangle meshes, and 3.1.2 will show the process of modifying complicated triangle meshes, and 3.1.3 will show the process of selecting walkable surfaces and the surface of obstacles. In the last, 3.1.4 will give a conclusion. 3.1.1 Delete Useless Objects The virtual world can consist of many different objects, but some objects are useless for us to consider in path finding. Like some objects are outside the architecture, which are useless for navigation mesh construction. And some objects are essentially coincident with the floor area, which will be repeatedly constructed. As shown in Figure 3.1.1, there is a rug carpet on the floor. If we do not delete this rug carpet, then the later construction will construct a navigation mesh for this rug carpet which is essentially coincident with the underlying floor. This will cause 43 conflict when we process path finding. Figure 3.1.1 an indoor room, with a rug carpet on the floor. The easiest way is that we choose all these kinds of object, and then delete them. As they are useless for our later navigation mesh construction and path finding process, and will waste the construction time consuming. As shown in Figure 3.1.2, we deleted the rug carpet, and this will not affect our later navigation mesh construction. Figure 3.1.2 an indoor room, after the rug carpet has been removed. 44 In this step, we just simply choose all these useless objects, and then delete them. 45 3.1.2 Modify Complicated Objects. In many virtual scenes, we will counter the small objects with very complicated structure, as chairs, tables, flowerpot, even animals. These complicated objects normally consists thousands of triangle meshes, even tens of thousands of triangle meshes. Then what is the purpose that we process all of these triangle meshes and construct navigation mesh for these objects. This is meaningless for us to process these kinds of objects and waste most of the construction time consuming. Our solution is to re-present these kinds of objects into a simplest representation, which is the cover of bounding box. As these objects are not like the ones we mentioned in part 3.1.1, they are essential components of the scene, mostly are the obstacles. These objects always consist of thousands of triangle meshes, and even more. However, the walkable surface underlying as floor normally consist of much fewer triangle meshes. Compare to these two kinds of objects, actually we spend small percent of the CPU time on constructing the navigation meshes for the main part, but spend large percent of the CPU time on constructing the navigation meshes for the secondary part. However, we are not necessarily to process each triangle meshes in these complicated objects. As they are normally obstacles, this refers to the purpose of our construction 46 on these object is to avoid to walk across them. Then we’d better use a simple polygon to represent these complicated objects. This will not affect the final result of the path finding process at all. So our solution here is using the top polygon of the bounding box of the complicated object to represent itself. As shown in Figure 3.1.3, there are six chairs and one table. In realistic, we are impossible to walk through the area that the chairs and table occupy. We can choose the chairs and the table, one by one and use the cover polygon to represent them. As shown in Figure 3.14, we use the cover polygon of the boundary box of one chair to represent the chair. Figure 3.1.3 an indoor room; choose a chair with its bounding box. 47 Figure 3.1.4 an indoor room; represent one chair with the cover polygon of its bounding box We offer another function of selecting a group of objects, and using the cover polygon of these objects to represent this group of objects. As shown in Figure 3.1.5 and 3.1.6. We choose all the chairs and the table together; use the cover polygon to represent all of them. 48 Figure 3.1.5 an indoor room; choose all the chairs and the table Figure 3.1.6 an indoor room; represent the chairs and the table with the cover polygon of their bounding box 49 In this step, we modify all of these complicated objects by using the cover polygon of their bounding boxes which will not affect the final path finding process. 50 3.1.3 Selecte Walkable Surfaces In this step, we begin the process by looking at the raw geometry of the virtual world. We can query the system for the polygons that make up all of the surfaces of a level (floors, walls, ceilings, and so on). Now we need to select the walkable surfaces. Assuming that our AI characters cannot walk on walls or ceilings, we can simply iterate over all of the triangle meshes in the level and determine which ones face upward. Each triangle mesh in the level should include a normal value; that is, a vector that points in a direction perpendicular to the triangle mesh. We only want triangle meshes whose normal points more or less upwards; that is, surfaces that are more or less flat. We can measure the angle between a triangle mesh’s normal and vertical line, and if the angle is greater than a certain “maximum angle” threshold, the surface is too steep to walk on. In this step, we select out all the triangle meshes whose normal points more or less upwards, which are potential walkable surfaces, or the cover surfaces of the obstacles. 51 3.1.4 Concluding Remark In the first part of this chapter, we do a series of preprocess steps to serve later construction process. In conclusion here, we firstly delete those objects are useless or essentially coincident with the underlying floor; we secondly modify those very complicated objects by representing them as the cover polygons of their bounding boxes; we lastly select out all the potential walkable surface, or the cover surfaces of the obstacles, whose normal points more or less upwards (by threshold). 52 3.2 Merging Process In this part, we will talk about one of the most essential processes in the navigation mesh construction. Our goal here is to compose as big as possible convex polygons from the huge list of triangle meshes from the last step. If we wanted, we could use the huge list of triangle meshes directly, without optimizing it further, but chances are we want to compact the navigation meshes further to lower our memory requirements and speed up the final path finding process. Notice here, the path finding process will be faster if the underlying search space is smaller normally. Our goal here is more or less the same as the optimal convex partition problem; but we cannot guarantee the solution is most optimal. Our goal is speed up the convex partition problem by local merging between the small convex polygons, and try to get a near optimal solution. In this part, we talk about three merging processes consecutively, 3.2.1 will show the process of adjacent merging, and 3.2.2 will show the process of 3-2 merging, and 3.2.3 will show the process of central point merging. At last, we will conclude in 3.2.4. 53 3.2.1 Adjacent Merging In this step, we process the most fundamental merging algorithm which is adjacent merging. It simply tells us to merge pairs of adjacent convex polygons into single, larger convex polygons. Figure 3.2.1 gives an example of how we can merge six nodes into a single node by repeated merging. By continuously repeating this process until there are no more nodes left to merge, we can dramatically reduce the number of convex polygons in our search space. Figure 3.2.1 merging polygons into a single convex polygon Adjacent Merging works as follows. 1. Find a pair of adjacent nodes (i.e., two nodes that share an edge between them) whose normals are nearly identical (i.e, their surfaces face the same direction). 2. Check to see if both nodes share the same two points along their shared edge. If the two ednpoints of those edges are not the same, we cannot merge these nodes. 54 3. Attempt to eliminate the edge and merge the remaining vertices into a single convex polygon. If you cannot make a convex polygon, the nodes cannot be merged. If you can, delete both of the existing nodes and replace them with the new node. Step 3 requires a bit more explanation. In order to merge two polygons A and B to form polygon C, we begin by pointing at the clockwise-most shared vertex in the A’s vertex list. In other words, we look at the two vertices shared between A and B, and find the furthest vertex in clockwise order in A. We then add all of A’s vertices to C’s vertex list. We now look at the last vertex added to A; this should be the other vertex shared between A and B. We locate this vertex in B’s vertex list and add all of B’s vertices beginning with this vertex. Now we simplify the remaining polygon by eliminating any unnecessary vertices. A vertex is deemed unnecessary if it is redundant (i.e., the vertex is identical to the vertex immediately before it or after it in the vertex list), or if it is unnecessary to maintain the shape of the shape of the polygon (i.e., if we look at the line between the previous vertex and the next vertex and the current vertex lies somewhere on that line). For doing so, we can merge all adjacent convex polygons if possible. 55 3.2.2 3-2 Merging However, there’s still plenty of room for improvement. Take a look at figure 3.2.2. If we inspect our navigation meshes closely, we will notice that there are a couple of places in the navigation meshes that share this pattern, where two polygons adjoin a third polygon and the first two polygons each share one of their sides with the third. Figure 3.2.2 converting three convex polygons into two convex polygons. An algorithm we refer to as “3-2 Merging” will allow us to merge these three nodes together into two much simpler polygons, as shown in the rightmost image. Note that this technique does not only with four-sided polygons. Figure 3.2.3 uses quadrilaterals merged into one triangle and one quad. The image on the left is the original geometry, and the image on the right is after merging. 56 Figure 3.2.3 merging of mixed shapes. 3-2 merging is a difficult process, but it is well worth the effort. The algorithm works as follows. Note that we should only attempt the 3-2 merging process after we have already completed the basic adjacent merging process previously described. 1. Identify two adjacent nodes that share exactly one vertex between them. We will call these nodes A and B. These are equivalent to the bottom tow quads in the first image in Figure 3.2.2. The fact that these nodes will exist as separate polygons after the basic merge step proves that they cannot be merged together on their own, because, otherwise the adjacent merging step would have merged them already 2. Identify a single node adjacent to both of those original nodes, if one exists. This would be the large top node in the first image in Figure 3.2.2. We will call this node C. 57 3. Determine if A and B both have one edge that runs parallel to an edge on C, and ensure that the endpoints of these parallel edges share one point in common so that they could be merged into a single line. If either node does not share parallel adjacent edge, it means that his set of nodes is not a candidate for a 3-2 merge. This is equivalent to the vertical edges along the sides of the first image in Figure 3.2.2. 4. We begin the actual merge process by first discovering a point that is shared by A and B and are on an edge in C (as shown in Figure 3.2.4). Figure 3.2.4 example for 3-2 merging To avoid confusion with the names of the polygons, we will use numbers to refer to 58 vertices, and we will call this point 1. Note that node C will not actually contain point 1; the point only lies along one of C’s edges. 5. We now determine which of A and B holds the vertex we wish to use for splitting – this is vertex 2 in Figure 3.2.4. We note that A and B each has two vertices one edge away from vertex 1. However, in each case, one of these vertices is shared with C. We take the two remaining vertices (vertices 2 and 3 in our example here), and whichever is closest to vertex 1 must be the right one – in this case, vertex 2. Again, note that the vertex 2 is not actually a vertex in B; it merely lies along one of B’s edge. 6. Now we consider tracing a line from 2 to 5. In order to do this, however we need to figure out exactly where point 5 is. We begin by noticing that there are two vertices one edge away from vertex 2: 1 and 4. Since it cannot be 1, it must be 4. We then extend the line from 4 to 2 off into infinity in the direction of vertex 2. We attempt to determine where it intersects another edge of B (i.e., where it intersects B along any line but the line between 1 and 3). If there is no intersection, then these nodes are not a candidate for a 3-2 merging, and we should try again with another set of nodes. If we do find a point, we call this point 59 5 and proceed. 7. We now split B into separate nodes by nodes by dividing it along the line from 2 to 5. We will call these sub-nodes B1 and B2, where B1 is the top node (the node that contains vertex 1). To perform this split, we iterate over the list of B’s vertices and insert each of points 5 and 2 into the vertex list twice in the appropriate position in the list. We can then search through this list and split it into two new vertex lists. 8. We now merge B1 with node A using the merging process described in the previous section. We will call this new node AB. 9. We can use the merging procedure to merge node AB with C to form ABC. We have now reduced the three nodes A, B and C to two nodes, ABC and B2. Now that the process is finished, and we will check all possible candidates for 3-2 merging. In this step, we will check all candidates for 3-2 merging. 60 3.2.3 Central Point Merging At this stage we still have room for improvement. Take a look at Figure 3.2.5. If we inspect our navigation meshes closely, we will notice that there are a couple of places in the navigation meshes that share this pattern, where three polygons share a same node in the centre. Figure 3.2.5 converting three convex polygons into one convex polygon An algorithm we refer to as “Central Point Merging” will allow us to merge these three nodes together one simpler and big polygon, as shown in the rightmost image. Central point merging is not that difficult, but the searching time of the central point may be consuming much. The algorithm works as follows. Note that we should only attempt the central point merging process after we have already completed the basic adjacent merging process and 3-2 merging process previously described. 61 1. Check each point one by one in current search space; find out those points that are adjacent with exactly three convex polygons. Here we emphasize the exact number is 3, as any other numbers will not be a candidate for a central point merging process. If the number of adjacent convex polygon is 1 or 2, then this will definitely share the pattern in Figure 3.2.5. If the number of adjacent convex polygon is 4, as shown in Figure 3.2.6. One possibility (the left image) is that A and B share with one edge; B and C share with one edge; C and D share with one edge; D and A share with one edge; and the point is in the centre surrounded by the four adjacent convex polygons. Anyhow, if any of AB, BC, CD, and DA shares the same two endpoints, then they must be checked in the adjacent merging process; otherwise, they definitely cannot be merged in central point merging process as some of the edges do not share the same two endpoints. And the other situation is that the point is the boundary point of the surface (the right image), then it cannot be a candidate for a central point merging process. The same situation can be checked when the number of adjacent convex polygons is bigger than 4. So here we just get the point which share exactly with three adjacent convex polygons. 62 Figure 3.2.6 one point shared with four adjacent convex polygons. 2. Find out the number of adjacent edges this point share. If the number is 4, then this refers to this point is a boundary point. Such point is not a candidate for a central point merging, as explained in the right image in Figure 3.2.6. If the number is 3, then we continue checking. 3. For each edge, check its endpoint which is not the central point. For each edge, it must be shared with its two adjacent convex polygons at the same two points. If this fails, then it refers to that this central point is not a candidate for central point merging. 4. When we reach this step 4, then we actually find a candidate for central point merging. Then we merge the three convex polygons one by one using the algorithm we have been mentioned in previous section. Continuously repeat step 1 – 4, until we finish all the point in the search space, then we are done with the central point merging process. 63 3.2.4 Concluding Remark At this point, our navigation mesh is pretty close to optimal. However, we can still take a bit further. If we look closely at our navigation mesh, we will notice that there are many tiny nodes still remaining in the mesh that are much too small to be useful. Small as they are, they still require as much memory as a larger node, because we still need several bytes to store the coordinates of each vertex in the node’s vertex list plus the node’s normal. If we cull out these tiny nodes, we will not only vastly reduce the memory requirements, we will also improve runtime performance, since our path finding algorithm will no longer have to include these useless little nodes in an A* search. Once our navigation mesh has been generated, we can simply iterate all of the nodes and determine the surface area of each. Then, determine a good threshold for the minimum surface area, so that if any node’s area is below that threshold, we consider it too small to be useful and remove it from the navigation mesh. 64 3.3 Sub-division Process In this part, we talk about another essential process which is sub-division. In many cases, we will have extra geometry to deal with, which are called obstacles. For example, imagine that a level designer places a large, immobile treasure chest in the middle of a room. This is a single high-polygon object. The floor, however, can be represented as several big convex polygons. This means that we need to do the work ourselves. We need to manually subtract the treasure chest from the floor surface. Here we only subtract those relatively big and obvious obstacles, and leave those relatively small obstacles to the path finding process. This problem we will talk about in the path finding part. Now we concentrate on the problem of subtracting obstacles from the walkable surface. The problem is difficult. Though we can use some simpler solution, this will cause the navigation mesh mess. We first talk about the simple solution in 3.3.1, and then talk about our solution in 3.3.2. Lastly there is a conclusion in 3.3.3. 65 3.3.1 Recursive Sub-division Approach We can use recursive sub-division to divide any node into smaller nodes. If we took the sub-division to infinity (which we won’t), we’d eventually end up with an infinite number of infinitely small sub-nodes, and every sub-nodes would be either totally covered by the obstacle or totally outside the object. Recursive sub-division simply means splitting the polygon into some number of smaller polygons. There will be exactly as many new sub-polygons as there are vertices in the original polygon. Note that the resulting sub-polygons will always be four-sided. Figure 3.3.1 sub-division triangles and quadrilaterals. 66 The following algorithm demonstrates how to sub-divide a polygon. Figure 3.3.1 demonstrates sub-division for a square and a triangle. 1. Determine the centre of the polygon by averaging the X, Y, and Z components of the polygon’s vertices. 2. Find the midpoint of each of the polygon’s edges. 3. Add new polygons by using the centre and two midpoints along with each of the node’s original vertices. Now we know how to sub-divide a navigation mesh node, let’s show how to use this process to subtract an obstacle from the node. We begin by sib-dividing each navigation mesh node that intersects the obstacle. For each sub-node generated from that original node, we either keep the sub-node around (if it does not intersect the obstacle at all), throw it out (if it is totally inside the obstacle), or sub-divide it again (recursively) if it is partly inside and partly outside the obstacle. Once we reach a minimum polygon size (which is a threshold here), we will throw out the sub-node instead of sub-dividing it further. This stops us from sub-dividing 67 infinitely, and also gives us a threshold value that we can use to determine how close the navigation mesh should approach a given obstacle. After we deal with all the obstacles, we will re-merge all the sub-nodes in the search space using the three steps of merging we mentioned in 3.2. This approach will mostly make the navigation mesh mess, and definitely will cost much time in re-merging which we are doing the redundant work, and the result mostly depends on the threshold we choose. Thus, we improve the sub-division process using another approach in the next section. 68 3.3.2 New Sub-division Approach Previous section describes a method of dealing with intersecting geometry by recursive sub-division of polygons, each time splitting an N-sided polygon into N four-sided polygons sharing a vertex at the centre of the original polygon. This works fairly well in some cases, such as high-polygon obstacle immobile obstacle in the centre of a room with well-defined floor surface. However, there are other situations in which it generates many more polygons then necessary. For example, consider a case of rooms and corridors created by placing wall polygons on top of floor polygons that have not been cut to match the shape of the rooms, as shown in Figure 3.3.2. After four recursive sub-divisions (as shown in the middle image in Figure 3.3.2), 27 polygons remain. The large number of polygons is a result of using cuts that do not correspond to lines of intersections. An optimal mesh sub-division, such as the one shown in Figure 3.3.3, would contain only six convex polygons. Figure 3.3.2 a floor polygon with walls is sub-divided recursively, and re-merge. 69 Figure 3.3.3 an optimal mesh sub-division for example shown in Figure 3.3.2 In order to get a more specific sub-division algorithm, it is worthwhile to start by defining the goal. To limit the problem, let us consider the sub-division of a single ground polygon, denoted by p. We also have a set of W of convex polygons that can potentially intersect p (which are the obstacles in our system). It is initially assumed that no polygon in W is coplanar with p. The desired output is a partition of p consisting of convex polygons. It is required that none of these output polygons intersects those polygons in W, except along the boundary lines. After applying polygon merging process we mentioned in 3.2 on the output convex polygons, we would like it to be close to optimal. This is in terms of the number of convex polygons. And also we desire a reasonably fast execution time. The propose algorithm can be described simply as: We just sub-divide the ground polygon p according to the edges of those obstacles intersect with the ground polygon p. 70 The whole procedure is like this: 1. Check all the convex polygons, to see whether they intersect with p or not. Put all the intersected polygons in a single list, called obstacle-list L. 2. Take one polygon m from L, then check the rest polygons in L to see whether they intersect with m or not. If one polygon n intersects with m, then calculate a new polygon q = (m AND n); delete n from the list L, and replace m with q; and then continue the checking, until we finish checking all the polygons in the list L. 3. Construct a list E, and push all the edges of all the polygons in L into E. Calculate the distances of the central point of p to each edge in E, and sort all the edges in E according to this distance. 4. Get the first element in E, which is the edge with the shortest distance from itself to the central point of p. sub-divide p into two polygons p1, and p2 with the sub-divided edge e. 5. Create two lists L1 and L2, which L1 represents all the obstacles that interest with p1 and L2 represents all the obstacles that intersect with p2. Check all the polygons in the list L. 71 5.1.If the polygon is totally inside in p1, then push this polygon into L1. 5.2.If the polygon is totally inside in p2, then push this polygon into L2. 5.3.If the polygon is totally superposed with p1, then delete this polygon, p1, and L1. 5.4.If the polygon is totally superposed with p2, then delete this polygon, p2, and L2. 5.5.If the polygon partially inside p1 and partially inside p2, then we divide this polygon into two sub-polygons according to the sub-divided edge e. push the sub-polygon which is totally inside in p1 into L1, and push the other sub-polygon into L2. 6. Check the size of the list L1 and L2. If L1 is empty, then we store p1 as the output convex polygon, and if L2 is empty, then we store p2 as the output convex polygon. 7. If either p1 or p2 is not the output convex polygon, or not has been deleted in step 5, then repeat step 3-6 for (p1, L1) if needed, and (p2, L2) if needed. 72 8. After no more polygons needed to be sub-divided further, that refers to we get all the output polygons. Then re-merge all the output polygons using the previous 3 steps merging process which we have been talked about. Finally we will get a near optimal solution (small number of output polygons according to the number of obstacles) after sub-division process. 73 3.3.3 Concluding Remark In this sub-section, we presented two polygon sub-division algorithms that can be used to sub-divide the ground polygons to handle all those obstacles. The first one is easier for implementing, but will cause mess output polygons (wasting some walkable surfaces which near the boundaries of the obstacles) and generate enormous number of output polygons in some cases. The second one we presented is more complicated, but will generate nice sub-division with small number of output polygons. However, this algorithm will require a significant amount of implementation works compared to the first algorithm. Nevertheless, the second algorithm we presented here has provided better solutions. 74 3.4 Reconstruction This is a serious problem that a level designer will consider when building models and navigation mesh for later path finding. The problem is how to reconstruct a navigation mesh if we just slightly changed the raw geometry of the virtual world. It is commonly seen in 3D architecture model design. There are two situations need to be considered: If the level designer changed most part of the raw geometry of the underlying architecture model, then it is very tedious to reconstruct the corresponding navigation mesh according to the changed part. Here, we suggest the whole navigation mesh should be reconstructed from the new raw geometry of the architecture model. If the level designer just changed the small part of the underlying architecture model, then we’d better to reconstruct the corresponding navigation mesh accordingly depending on the changed part of the underlying architecture model. To do so, we compare the already computed navigation mesh with the new raw geometry of the architecture model. Click on the convex polygons which are needed to be destroyed, and select all the triangle meshes which need to be reconstructed; notice for those obstacles which are already been in the old architecture model but 75 will affect the new coming convex polygons from the new raw geometry of the model. 76 3.5 Multiple Levels Construction Here we introduce the approach to deal architecture model with multiple levels. As for many architecture models, like hospitals, airports, hotels, always have multiple levels. We process the previous algorithms consecutively for each level, including adjacent merging process, 3-2 merging process, and central point merging process, and sub-vision process. Then each level will has its own navigation mesh which represents the whole walkable surface in this level. For the connection between levels, we assume there are only two components here. One is elevators, and the other one is staircase. For elevators, we indicate elevator adding and choose a small range of a convex polygon in one level; accordingly all the levels will be assumed to have elevator location at the same location automatically. Of course, the designer can delete the elevator remark for a specific level. Then the AI character can traverse from one level to another level through the specific elevator location. For staircase, it requires more work. If we want to add staircase for two levels, we first indicate staircase adding; choose one ending point for the staircase in one level, and then choose the other ending point for the staircase for the other level. We should 77 add all the staircases one by one by the designer’s manual work. Hence, we can combine all the levels in an architecture model to be a whole complete navigation mesh for this architecture model. 78 3.6 Concluding Remark In this chapter, we proposed a series of algorithms to construct a navigation mesh from a raw geometry of architecture model (normally we consider the raw geometry as the triangle meshes, but can be any shapes of convex polygons). There are mainly three steps consecutively. The first step is selecting process, where we delete all the useless objects, convert high-polygon objects into a cover polygon of their bounding box, and select the polygons whose normals more or less toward up (only this kind of triangle meshes are possible for AI characters to walk on). This step we mainly to preprocess the huge list of triangle meshes for later construction process. The second step is merging process, where we process adjacent merging, 3-2 merging and central point merging consecutively. The idea behind them is to construct large convex polygons from the enormous amount of small and tiny polygons, and reduce the number of convex polygons dramatically. This also eases the later path finding process. The Third step is sub-division process, which we deal with obstacles. As obstacles must be avoided to cross over in path finding stage, thus we choose to sub-divide the walkable surface according to these obstacles. For each walkable convex polygon, we 79 sub-divide it by the edges of the polygons which intersect with this walkable convex polygon. Then all the output convex polygons producing after this step are definitely valid for AI characters to walk on. Normally the resulting convex polygons will be our navigation mesh for the underlying architecture model. In the last, we also mention the problem of reconstruction, as normally the level designer will modify the virtual level for many times. For large modifications of the raw geometry of the underlying architecture model, we suggest to reconstruct the entire navigation mesh; but for small modifications of the raw geometry of the underlying architecture model, we’d better to reconstruct the navigation mesh partially according to the modified part of the raw geometry of the architecture model. All these help us to achieve getting an near optimal navigation mesh for the input architecture model. 80 Chapter 4ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Path Finding Problem In this chapter, we will talk about the algorithm of path finding on our constructed navigation mesh. Path finding is an essential function in architecture model, as we are satisfied to know where to go from the location we are standing on or a starting location to our destination location. The whole navigation mesh we built in the previous chapter are serves the underlying search space for path finding. At its core, a path finding method searches a graph by starting at one point and exploring adjacent nodes until the destination node is reached, generally with the intent of finding the shortest route. Although graph searching methods such as a breadth-first search would find a route if given enough time, other methods, which explore the graph, would tend to reach the destination sooner. An analogy would be a person walking across a room; rather than examining every possible route in advance, the person would generally walk in the direction of the destination and only deviate from the path to avoid an obstruction, and make deviations as minor as possible. A common example of a graph-based path finding algorithm is Dijkstra's algorithm. This algorithm begins with a start node and an "open set" of candidate nodes. At each 81 step, the node in the open set with the lowest distance from the start is examined. The node is marked "closed", and all adjacent nodes are added to the open set if they have not already been examined. This process repeats until a path to the destination has been found. Since the lowest distance nodes are examined first, the first time the destination is found, the path to it will be the shortest path. A* search is a variant of Dijkstra's algorithm commonly used in games and films. Instead of looking at the distance from the start node, A* search chooses nodes based on the estimated distance from the start to the destination. The estimate is formed by adding the known distance from the start to a guess of the distance to the goal. The guess, called the heuristic, improves the behavior relative to Dijkstra's algorithm. When the heuristic is 0, A* search is equivalent to Dijkstra's algorithm. As the heuristic estimate increases and gets closer to the true distance, A* search continues to find optimal paths, but runs faster (by virtue of examining fewer nodes). When the heuristic is exactly the true distance, A* examines the fewest nodes. (However, it is generally impractical to write a heuristic function that always computes the true distance.) As the heuristic increases, A* examines fewer nodes but no longer guarantees an optimal path. In many games this is acceptable and even desirable, to keep the algorithm running quickly. This chapter mainly consists of two parts. In 4.1, we will show the path finding algorithm we implemented on the constructed navigation mesh; in 4.2, we will talk 82 about two-level path finding according to the relatively small obstacles; and give an conclusion in 4.3. 83 4.1 Path Finding on Navigation Mesh. 4.1.1 A* Search Path Finding Process We have explained the A* search path finding algorithm in Chapter 2, and we will apply the idea of the A* search for our path finding system on navigation mesh. A* is like other graph-searching algorithms in that it can potentially search a huge area of the map. It’s like Dijkstra’s algorithm in that it can be used to find a shortest path. It’s like Greedy Best-First-Search in that it can use a heuristic to guide itself. In the simple case, it is as fast as Best-First-Search We recall the representation of the A* search algorithm F = G + H where G is the total distance the path has taken to get from the starting position to the current location. H is the estimated distance from the current location to the terminating position. A heuristic function is used to create this estimate on how far away it will take to reach the terminating point. 84 In our implementation, we set the heuristic function is the Euclidean distance of the shortest distance from current polygon to the terminating point. And we will penalize the estimated distance if the path changed its direction from the previous convex polygon. We denote a group (c, p, k, B, p_id) to represent path finding unit, where c is the current convex polygon that is searched; p is the starting point for this convex polygon, k is the slope of the previous path; B is a Boolean value to represent whether the path direction has been changed or not; and p_id is the convex polygon id of the previous convex polygon through which the path goes to the current convex polygon. We denote the starting point as s; the terminating point as t; the starting convex polygon cs; the terminating polygon ct; and the initial path slope as k0, which is the slope of the line from s to t. The whole procedure is shown as follows: 1. Create an initial node (cs, s, k0, True, -1), and create an empty list called Open List. Push the initial node into the Open List. 2. Create an empty list called Closed List. We talked about the open list and close 85 list in Chapter 2 on the basic A* search algorithm. 3. If the Open List is empty, then exit the algorithm with failure. 4. Select the first node in the Open List, remove it from the Open List, and push this node into the Closed List. We denote this node as (cn, pn, kn, Bn, p_idn). 5. If cn is the goal convex polygon, exit successfully with the solution obtained by tracing a path along the path from cn to cs by the p_id, until we reach the p_id is -1, which is in the starting node. 6. If cn is not the goal convex polygon, check all the adjacent convex polygons of cn. 7. Then we calculate the G value of each adjacent convex polygon which is the exact distance from the starting point to the current convex polygon we are reaching. We extend pn with the slope kn, and check which adjacent convex polygon will be reached from this line, denote this adjacent convex polygon as cn+1 with the intersection point of pn+1. Calculate the distance from pn to pn+1, and add this distance with the G value of node (cn, pn, kn, Bn, p_idn). This is the G value for convex polygon cn+1 and we set the Boolean value Bn+1 as True. 86 For all the rest adjacent convex polygons, we choose the mid-point of the adjacent edge between the convex polygon and cn; denote this mid-point as pn+1. Calculate the distance from pn to pn+1, and add this distance with the G value of node (cn, pn, kn, Bn, p_idn). This is the G value for the rest adjacent convex polygons with the point pn+1 as the mid-point of the adjacent edge between this convex polygon and cn and we set the Boolean value Bn+1 as False. Notice that the first polygon which is reached by the line from pn with slope k0 does not change the direction of the previous path, and the rest all changed the direction of the previous path. 8. Then we calculate the H value of each adjacent convex polygon. We penalize those convex polygons which change the direction of the previous path. For the convex polygon which did not change the direction of the previous path, we use the Euclidean distance from pn+1 to the terminating point ct as the H value. And for those convex polygons which changed the direction of the previous path, we use (1.1 x the Euclidean distance from pn+1 to the terminating point ct) as the H value. 87 9. Then we add up the G value and H value into F value for all the adjacent convex polygons. Check all the adjacent convex polygons. Ignoring those which are already in the Closed List, and add all the adjacent convex polygons if they are not in the Open List already. For each of them, if an adjacent convex polygon is already in the Open List, check to see if this path to this convex polygon is a better one. In other words, check to see if the G value for this convex polygon is lower. If not, we do not do anything. On the other hand, if the G value of this new path is lower, change the parent of this convex polygon to cn. Finally, update both the F value and G value for this convex polygon. 10. Sort the Open List in order of the increasing F value. We’d better to construct this Open List as a binary search tree to speed up our inserting, modifying and deleting functions. 11. If the Open List is not empty, or we have not reached the final convex polygon where the terminating point ct belongs to, repeat the process from Step 3. 88 Here we have done the path finding algorithm either with a actual path found or no path from the starting point to the terminating point. This is the path we can find from the starting point to the terminating point without those relatively small and tiny obstacles. 89 4.1.2 Path Correction Process With the result of A* search path finding process, we can get a series of convex polygons to consist of the route from the starting point to the terminating point. Initially, we use the mid-point of the adjacent edges between two consecutive polygons to construct the real path. However, this will cause the problem of zig-zag, and makes the actual path not that nature. In this section, we talk about an algorithm to smooth the path. Here is the procedure: 1. Take the starting point. Then calculate the smallest distance from the starting point to the consecutive boundary edge from the whole route. And set the point in the consecutive boundary edge which has the smallest distance to the starting point as the consecutive point, push this point to the path point list. Then take this point as current point. 2. Keep finding the next point in the consecutive boundary edge to the current point with the shortest distance from this next point to the current point. Then push this next point into the path point list, and take the next point as current point. 3. Recursively do step 2, until we reach the terminating point. Now we get a list of points from the starting point to the terminating point which consist a route. 90 4. Connect each two consecutive points as lines. Push these lines into a Stack in order. 5. Take two lines from the top of the Stack, to check whether they can be merged into a single line according to the constructed navigation mesh. If they can be merged into a single line, then merge them into a single line and push this single line into the Stack. If they cannot be merged into a single line, then take the first line into the final path list, and push the second line back into the Stack. 6. Keep doing step 5 until we have no lines in the Stack. This algorithm will give us a far better path which looks more nature. We will show some experiment results in Chapter 5. The rational of why we choose the shortest node in the consecutive edge to be the next point is stated here. The main reason is that initially we have no idea where will have barriers that block our way. Then the more nature way to construct the path is that we always go to the shortest route first. Because of the point merging process in the path smoothing process, we will finally get a turn if needed to go to the direction which directs to the terminating point. 91 Another approach is that we go along the direction to the terminating point initially, until we are blocked by barriers then make a turn. There are two problems in this approach. First, we will have no idea how should we direct once we are blocked by a barrier. Second, this will cause a zigzag route and we even cannot correct it in the points merging process, as shown in Figure 4.1.1 as an example. Because once we need to change direction, we definitely will change direction again to the initial direction (our goal is terminating point). For other choices, mid-point of the edge will still generate zigzag route in our experiment, and end-points of the edge is a choice, but the result is worse than the shortest point approach. So in our system, we use shortest point to construct the route. Starting point Barrier 1 Barrier 2 Barrier 3 Terminating point Figure 4.1.1 zigzag problem in path construction. After we get the actual path, we then want to still smooth the path further. The idea is that we may get a shorter path if we start from the terminating point, and terminates at the starting point. So here we calculate another path from the terminating point to the starting point. 92 Then compare the two paths. As we will have two lists of points, and one point in one list is corresponding to another point in the other list in an anti-order. We take one point from the first list, and its corresponding point from the second list. Then compare which point will result a shorter path, set this point in the final result. In this way, the algorithm will get us a shortest path most of the time. 93 4.2 Two-Level Path Finding In this section, we would like to talk about the problem of the relatively small and tiny obstacles. We prefer to deal with these obstacles after the basic path finding algorithm with two main reasons. The first reason is these obstacles will dramatically increase the number of convex polygons and mess the underlying navigation mesh if we process them in the sub-division section. For a n-sided obstacle polygon, the underlying walkable polygon will be sub-divided into two sub-polygons at least, but normally will be sub-divided into n sub-polygons according to the number of edges of the obstacle polygon. This will definitely increase the number of final convex polygons in navigation mesh dramatically. Also the shape of the walkable polygons will be peculiar-looking if the obstacle polygon is not in normal shape. This will affect the final path that the path looks like abnormal. Then we need to do lots of redundant work to smooth the final path. The second reason is normally these obstacles will not be walked across. Like a group of small chairs, flowerpots, or even brooms against the walls, which the AI characters are normally will not walk across them. Notice that we always choose the midpoint of the edges of the convex polygons to construct the path, which means the AI characters will not walk against the walls or boundaries of the walkable surface most of the time. 94 That’s why it not worthwhile to sub-divide the walkable surface with these small obstacles to make the underlying navigation mesh structure huge and complicated. For these reasons, we choose to deal with these obstacles after we processed the basic A* search algorithm to get a path. In 4.2.1, we will show the two-level path finding will normally speed up the path finding process in practice; and in 4.2.2, we will show the actual implementation on two-level path finding. 95 4.2.1 Proof on the Time Consuming of Two-Level Path Finding In this sub-section, we compare with the time consuming of the one if we sub-divide the underlying navigation mesh with these small obstacles and do a basic path finding, with the one if we check these small obstacles after basic path finding. If we do sub-division for one underlying walkable polygon with n small obstacles which is k-sided obstacle polygon each, then the number of resulting sub-polygons will be at least (n+1) in the best case, and will be at (kn-n+1) in the worst case. As shown in Figure 4.2.1, for each obstacle, the best case is only two sides of the obstacle polygon are not overlapping with the edges of the underlying walkable convex polygon. Notice that we only talk about relatively small and tiny obstacles here, so we ignore one situation in which only one side of the obstacle polygon is not overlapping with the edges of the underlying walkable convex polygon. Thus, in this situation, each convex polygon will be sub-divided into two sub-polygons; that is we add two sub-polygons and delete the original polygon, and this will result in (n+1) sub-polygons if we deal with n small obstacles in which they all share the pattern as shown in Figure 4.2.1. This is rarely to see, but we need to consider. 96 Figure 4.2.1 best cast for sub-division for small obstacles. As shown in Figure 4.2.2, for each obstacle, the worst case is that none of the sides of the obstacle polygon are overlapping with the edges of the underlying walkable convex polygon. Then we need to sub-divide the underlying convex polygon according to every edge of the obstacle polygon. Thus, in this situation, each polygon will be sub-divided into four sub-polygons (we assume the obstacle is 4-sided here, which is normally seen); that is we add four sub-polygons and delete the original polygon, and this will result in (kn-n+1) sub-polygons if we deal with n small obstacles in which they all share the pattern as shown in Figure 4.2.2. This is for the worst case, which will be normally seen in the virtual scene. 97 Figure 4.2.2 worst cast for sub-division for small obstacles. From the previous discussion, we can conclude that averagely there will be O(n) sub-polygons if we sub-divide the underlying convex polygon with n obstacle polygons. In basic path finding algorithm, we mostly will search these sub-polygons if we originally will search in the initial underlying convex polygon. That means, we will waste time consuming on checking these sub-polygons even the AI character will rarely walk through these obstacles. However, for two-level path finding, we can partition all these obstacles and just check after basic A* search has been finished. The idea is we split the underlying convex polygon evenly like binary tree, and using OOBB bounding box to represent the group of obstacles. The time consuming of checking these obstacles then will be in O(logn) in average. We will show the detail of this process in the next sub-section. We need to say it is easier if we just process sub-division for whatever obstacles, and 98 the implementation will be much easier. However, this cause the navigation mesh structure huge and mess, and it also will slow down the real-time path finding search. That’s why we choose to do a two-level path finding to optimize the solution. 99 4.2.2 Implementation on Two-Level Path Finding In this section, we will talk about the implementation of two-level path finding in detail. There are mainly two steps. The first step is to construct a data structure to store the information of these obstacles. This step is processed after navigation mesh construction, and before the path finding process. The reason we leave this step to talk about here is this is related to the problem of two-level path finding. And the second step is to check on these obstacles and correct the path if possible. For data structure construction, this is a recursive procedure, as described in following: 1. Calculate the OOBB bounding box of all the obstacles which intersect with this underlying convex polygon. 2. Split the OOBB bounding box into two half more or less evenly. For each half, calculate the OOBB bounding box of all the obstacles in this half. 3. Repeat Step 2 recursively until there is only one obstacle in current half. 100 As shown in Figure 4.2.3, gives us an example of how to construct the data structure for obstacle polygons. As shown in (a), there are four obstacle polygons in a walkable convex polygon. The first step is we calculate the OOBB bounding box for all four obstacle polygons; this is the OOBB bounding box for first level, as shown in (b). Then we partition the first-level OOBB bounding box more or less evenly into two parts, the left two obstacle polygons belong to the first part, and the right two polygons belong to the second part. We also calculate the OOBB bounding box for the two obstacle polygons, and also for the right two obstacle polygons. These two polygons are the second-level OOBB bounding boxes, as shown in (c). Then we keep partitioning the second-level OOBB bounding boxes, and repeat the process, we will result in (d). (a) convex polygon with four obstacle polygons 101 (b) the first-level OOBB bounding box for all four polygons (c) the second-level OOBB bounding boxes, the first one for the two obstacle polygons in the left side, and the second one for the two obstacle polygons in the right side. 102 (d) the third-level OOBB bounding boxes, each bounding box is for each single obstacle polygon Figure 4.2.3 (a)-(d) shows the procedure of data structure construction. The data structure is actually a binary tree, this gives a averagely O(logn) time consuming to check what obstacle polygons intersect with the path we processed from the basic A* search algorithm. In the actual two-level path finding process, once we get a path and a convex polygon, we would like to check whether we need to correct the path according to these small obstacles. The procedure is shown as following: 1. If there are no obstacles in this convex polygon, then just exit. 2. Get the root OOBB bounding box, and then process it to the next step. 103 3. If this OOBB bounding box is a leaf node in the data structure, then check whether the obstacle polygon involved in this OOBB bounding box intersects with the path or not If it intersects with the path, then correct the path according to this obstacle. The correcting process will be shown in later. If it does not intersect with the path, then stops. 4. If this OOBB bounding box is not a leaf node in the data structure, check whether this OOBB bounding box intersects with the path or not. If it intersects with the path, then retrieve its child node from the data structure as its left child node and right child node. Go to Step 3 to process left child node and right child node accordingly. If it does not intersect with the path, then stops. 5. Once we finish checking, we get a finalized path. For correcting process we mentioned in Step 3, we just expand the obstacle polygon 104 by a ratio which is a threshold here. Then we get the two points where the path intersects at this obstacle polygon. As shown in Figure 4.2.4, we correct the path from one of the points, then along the boundary lines of the expanded polygon, and finish in the other one of the points. Figure 4.2.4 correcting a path according to an obstacle polygon. 105 4.3 Concluding Remark In this chapter, we talked about the path finding process. We do a basic A* search algorithm on the navigation mesh we build in previous chapter, and then do a two-level path finding according to those relatively small and tiny obstacles. We also compared the time consuming between the one if we sub-divide the underlying navigation mesh with these small obstacles and do a basic path finding, with the one if we check these small obstacles after basic path finding. It shows that sub-division for all obstacles will dramatically increase the number of the resulting convex polygons and will mess the shapes of the resulting convex polygons. Also the two-level path finding will definitely speed up the time consuming, as we use a binary partition to these obstacles, and also with the reason that normally the AI characters will not walk across these obstacles in practice. That will speed up the path finding process a lot. 106 Chapter 5ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt System Built, Experiment Results and Analysis We have built a system including navigation mesh construction and two-level path finding on the constructed navigation mesh; also we tested the system on various architecture models. In 5.1, we represent the tools and libraries we used for built system; in 5.2, we will show the results on navigation mesh construction; in 5.3 we will show the results on two-level path finding. 5.1 Tools and Libraries Used. In this section, we represent several tools and libraries we used for building the system, here including GRE COLLADA DOM, WxWidget, GPC and so on. We will talk about them in detail in the following paragraphs. Besides these tools and libraries, we build the system using C++ programming language on Visual Studio 2005 in Windows XP. 5.1.1 OGRE OGRE (Object-oriented Graphics Rendering Engine) is an open-source graphics 107 rendering engine that is written and maintained by a small core team, and contributed to by its ever growing community. Those of us that use it believe it's one of the better free and open engines out there today. Simply say, we use Ogre to be our rendering engine to render the virtual scene, various objects, and final path in the system. There are several features of OGRE suitable for us to build our system. It is simple, easy to use OO interface designed to minimize the effort required to render 3D scenes, and to be independent of 3D implementation i.e. Direct3D/OpenGL; There is an extensible example framework makes getting our application running is quick and simple. Common requirements like render state management, spatial culling, dealing with transparency are done for us automatically saving our time. Clean, uncluttered design and full documentation of all engine classes Proven, stable engine used in several commercial products 108 OGRE supports a number of common file formats, as “.mesh”, “.xml”, “.dae” and so on. In our system, we use COLLADA file format as the input format of the architecture model. 5.1.2 COLLADA DOM The COLLADA DOM (Document Object Model) is an application programming interface (API) that provides a C++ object representation of a COLLADA XML instance document. Lots of 3D model building software as Maya, 3dx are using COLLADA DOM as the library to convert the internal format to COLLADA format. We use COLLADA DOM here to resolve the input COLLADA file. 5.1.3 WxWidget WxWidgets is a C++ library that lets developers create applications for Windows, OS X, Linux and UNIX on 32-bit and 64-bit architectures as well as several mobile platforms including Windows Mobile, iPhone SDK and embedded GTK+. It has popular language bindings for Python, Perl, Ruby and many other languages. Unlike other cross-platform toolkits, wxWidgets gives its applications a truly native look and feel because it uses the platform's native API rather than emulating the GUI. It's also 109 extensive, free, open-source and mature. Here we use WxWidget to build the GUI, and interactive functions liking panning, rotating, object choosing, and so on. 5.1.4 GPC GPC (General Polygon Clipper Library) is a software library providing for computing the results of clipping operations on sets of polygons. It generalizes the computer graphics clipping problem of intersecting polygons with polygons. Here we use this library to help us with various polygon computations. 110 5.2 Experiment Results and Analysis on Navigation Mesh Construction Figure 5.2.1 a small dining room example. As shown in 5.2.1, we take a small dining room as a simple example to test the navigation construction functions. Firstly, we will delete the carpet as it is a useless object in the scene. And we group all the chairs and tables as a single polygon to dramatically reduce the construction time. The result is shown in Figure 5.2.2. In this simple, example, we can see all the meshes are ideally merged as big, simple 111 convex polygons. The white polygon is assumed to be the ground the surface initially, and the red polygons are assumed to be the obstacles initially. The user can modify this manually to change the obstacles to be ground surface, and vice versa. And we keep on doing sub-division, and then the result will be as the Figure 5.2.3. The blue parts are the walkable surface which is also the final navigation mesh; and the green lines are the boundary lines of the final convex polygons. Figure 5.2.2 the result of merging process. 112 Figure 5.2.3 the result of sub-division from Figure 5.2.2 We also can treat the chairs and table as the small obstacles that will need to be processed in two-level path finding. Then the result will be as shown in Figure 5.2.4. These small obstacles will not be processed in the sub-division. The blue area is the walkable surface, and the green areas are the small obstacles. Figure 5.2.4 the result of sub-division From Figure 5.2.2, as taking the chairs and tables as small obstacles. 113 Then we take a more complicated sample, as shown in Figure 5.2.5. This is a level of a building which is represented as its wireframe format. Figure 5.2.5 a level of a building. Figure 5.2.6 the result after merging process from Figure 5.2.5. Figure 5.2.6 shows the result after merging process. Also the red ones are assumed to be the obstacles and the while ones are assumed to be the ground surfaces initially. 114 There is one problem will occur in the merging process that is a convex check. If we want to check whether two adjacent convex polygons can be merged to be a big convex polygon on not, normally we just check the angle of the two points which are adjacent with the two polygons. Due to floating number errors, we need to set a threshold to check whether the degree is smaller than 180° or not. However, sometime will go wrongly that two polygons should be merged but not due to the floating number errors. Thus, some polygons actually need to be merged but not in the final result. However, we cannot set the threshold too big as we do not want to two polygons which are supposed not to be merged but merged. The Figure 5.2.7 shows the result of sub-division from Figure 5.2.6. The blue areas are the walkable surfaces, and the green lines are the boundary lines of the final convex polygons. We can see from the figure that our navigation mesh construction works well except the problem we mentioned in the previous two paragraphs. 115 Figure 5.2.7 the result of sub-division from Figure 5.2.6 116 5.3 Experiment Results and Analysis on Two-Level Path Finding In this section, we tested the algorithm of two-level path finding. Take the level for the building as we showed in previous section as example. As shown in Figure 5.3.1, it represents a basic path finding without small obstacles, in which the red dot is the starting point, and the yellow dot is the terminating point. As our goal is that do not change the previous path direction as much as possible. We can see that there are a sharp turn between line 2 and line 3; and these two lines can be combined with one line from the turn between line1 and line2, to the turn between line 3 and line 4. Actually it is possible to do further path smoothing after we find the path. Figure 5.3.1 a basic path finding example. 117 Figure 5.3.2 shows another path in this same virtual world. This one looks better, but still the sharp turn is not a good solution in actual world. Here, there are another two problems need to be considered. The first one is whether we can group some lines into one line to reduce those turns. The other one is we may shall use curve lines to represent the turns. Figure 5.3.2 another basic path finding example. In our program, we tried the first approach that check all consecutive two lines to see whether they can merge them into one line or not. We keep checking, until all consecutive two lines cannot be merged into one line. Notice that if two consecutive two lines can be merged into one line, that refers to the convex polygons which the two consecutive lines traverse are the same with the convex polygons which the 118 merged line traverses. Figure 5.3.3 and Figure 5.3.4 shows the result of the path merging process. A path consists of several edges normally. Here we use Stack to process this function. Initially we push all the edges from the start edge into a Stack S. Then we pop up two edges, and check whether they can be merged or not. If they can be merged, then merge them into one single edge, and push back it to S. If they cannot be merged, then consider them could not be modified further, and continue doing the checking for rest edges. Figure 5.3.3 path merging result from Figure 5.3.1 119 Figure 5.3.4 path merging result from Figure 5.3.2 Now we add some small obstacles into the virtual scene to test around the two-level path finding. Figure 5.3.5 shows an example. There are three small obstacles along the initial path got from the basic path finding. To avoid walk across the obstacles, we use the method proposed in chapter 4. However, this will introduce many sharp turns; the figure shows 6 sharp turns in order to avoid the obstacles. Also as shown in Figure 5.3.6, this one shows 4 sharp turns in order to avoid the obstacles. Here, we can see our approach may result a final un-smooth path. Yes, we can avoid these small obstacles successfully, but it still need further work in order to avoid these sharp turns and get smoother paths. 120 Figure 5.3.5 a two-level path finding example Figure 5.3.6 another two-level path finding example. 121 5.4 More Experiment Results Figure 5.4.1 a soap-factory example. 5.4.2 merging result in soap-factory example. 122 5.4.3 navigation mesh result in soap-factory example. 5.4.4 path finding in soap-factory example (example 1). 123 5.4.5 path finding in soap-factory example (example 2) We show a soap factory example from Figure 5.4.1 to Figure 5.4.5. Figure 5.4.1 shows the raw 3D model of this soap factory, and there are lots of single rooms with door opened in this factory model. It is suitable for our experiment for sub-division process, as there are lots of walls to be sub-divided to get the final navigation mesh. Figure 5.4.2 shows the result after merging process. The single while rectangle represents the whole floor of the factory. And all the red polygons represent the walls which are obstacles here. Figure 5.4.3 shows the result of navigation mesh of the soap factory. All the blue polygons represent the walkable floor. This gives us a basis for path finding. 124 Figure 5.4.4 and Figure 5.5.5 shows tow path finding examples. Figure 5.5.4 asks for a route from one room to another room, and Figure 5.5.5 asks for a route from the outside ground to an indoor room. The two examples both give us the correct path. However, it is still improvable to correct these paths to be more nature. We show a maze example from Figure 5.4.6 to Figure 5.4.10. Figure 5.4.6 shows the raw 3D model of this maze world. This maze example is extremely interesting that it can help us to test the path finding process to see whether we can always find a correct route in this maze world as there are many barriers in this example. Figure 5.4.6 a maze example. 125 Figure 5.4.7 merging process in maze example. Figure 5.4.8 navigation mesh result in maze example. 126 Figure 5.4.9 path finding in maze example (example 1). Figure 5.4.10 path finding in maze example (example 2). 127 Figure 5.4.7 shows the result after merging process. The single while rectangle represents the whole floor of this maze world. And all the red polygons represent the barriers which are obstacles here. Figure 5.4.8 shows the result of navigation mesh of this maze world. All the blue polygons represent the walkable floor. This gives us a basis for path finding. As we can see from the picture, our navigation mesh construction gives us a group of neat and clean convex polygons. Figure 5.4.9 and Figure 5.5.10 shows tow path finding examples. We just pick any two arbitrary points in the maze world to check whether the path finding process helps us find a correct path always. These two examples shows we can always find a correct route. However, it is still a big topic to discuss on making these paths look more nature. 128 Chapter 6ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt Conclusion and Future Work We have presented a practical and effective approach to construct a navigation mesh and do a path finding process for architecture environment with enormous number of obstacles. As the feature of the architecture environment is that there are always enormous amount of obstacles in the virtual world, we must be more careful to control the number of convex polygons in the resulting navigation mesh, and also care the shapes of the convex polygons in the resulting navigation mesh. In navigation mesh construction, we improve the result by a series of consecutive merging processes, which are adjacent merging, 3-2 merging and central point merging. This will improve the result of the navigation mesh a bit by just process adjacent merging. And we also propose the algorithm of sub-dividing the convex polygon according to the edges of the obstacles, instead of recursive sub-division. This will dramatically reduce the number of the convex polygons in the resulting navigation mesh, and avoid small and tiny convex polygons. In path finding process, we propose a way of doing two-level path finding in which we will not do sub-division for relatively small and tiny obstacles, but check them after a basic A* search has been done. We showed that this will reduce the consuming time of path finding as these obstacles normally will not be walked through, and we 129 build a fast data structure for checking and path correcting. This will be much faster than doing path finding on a huge and mess navigation mesh if we process the sub-division for all obstacles. The future work can be done in the following three areas. Firstly, all the adjacent merging, 3-2 merging and central point merging is local construction algorithm. Though the time consuming of the global algorithm as optimal polygon partition is very high, but it gives the optimal solution. We can see whether we can combine these two and get a better solution. Secondly, same as merging problem, we actually do a local approach for sub-division problem. The result should be improved if we combine this with global algorithms. Lastly, the final path will has sharp turn and unsmooth lines. It can be improved by correcting the path further mode. 130 Referencesttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt [01] Murphy, Robin R. Introduction to AI Robotics, MIT Press, 2000. [02] Snook, Greg, “Simplified 3D Movement and Path Finding” section 3.6, Game Programming Gems, Charles River Media, 2000. [03] Tozour, Paul, “Building a Near-Optimal Navigation Mesh,” p171-185, AI Game Programming Wisdom, Charles River Media, 2002. [04] Surasmith, Smith, “Preprocessed Solution for Open Terrain Navigation,” p161-170, AI Game Programming Wisdom, Charles River Media, 2002. [05] Rabin, Steve, “A* Speed Optimizations,” section 3.5, Game Programming Gems, Charles River Media, 2000. [06] Keil, J.M., “Decomposing a Polygon into Simpler Components,” p799-817, Issue 4, Volume 14, SIAM Journal on Computing, 1985. [07] O’Rourke, Joseph, Computational Geometry in C, Second Edition, Cambridge University Press, 1994. [08] B.Schacter, “Decomposition of Polygons into Convex Sets,” p1078-1082, IRRR Trans. Comput. C-27, 1978. [09] Tozour, Paul, “Search Space Representations,”p85-101, AI Game Programming Wisdom 2, Charles River Media, 2003. [10] Franstorm, Fredrik, “Improving on Near-Optimality: More Techniques for Building Navigation Meshes,” p113-128, AI Game Programming Wisdom 3, Charles River Media, 2006. 131 [11] Board, Ben, and Ducker, Mike, “Area Navigation: Expanding the Path-Finding Paradigm,” p240-255, Game Programming Gems 3, Charles River Media, 2002. [12] I Pohl, “Heuristic Search Viewed as Path Finding in a Graph,” p193-204, Issues 3-4, Volume 1, Artificial Intelligence, 1970. [13] A Botea, M Müller, J Schaeffer, “Near optimal hierarchical path-finding,” Journal of Game Development, 2004. [14] RE Korf, “Optimal Path-Finding Algorithms,” p223-267, Artificial Intelligence, 1988 [15] BJ Kim, CN Yoon, SK Han, H Jeong, “Path Finding Strategies in Scale-free Networks,” Physical Review E, 2002. [16] Brooks, R. A.. “Intelligence without Representation,” p139-159, Artificial Intelligence 47, 1991. [17] Champandard, Alex J., “Pathematics: Routing for Autonomous Agents,” Game Developers Conference Proceedings, 2003. [19] van der Sterren, William, “Path Look-up Tables – Small Is Beautiful,” p115-139, AI Game Programming Wisdom 2, Charles River Media, 2004. [20] White, Stephen, and Christensen, Christopher, “A Fast Approach to Navigation Meshes,” p307-320, Game Programming Gems 3, Charles River Media, 2002. [21] A* Pathfinding for Beginners, http://www.policyalmanac.org/games/aStarTutorial.htm 132 [...]... navigation mesh as basics, and divide the walkable surface according to the big and obvious obstacles, but leave the small and unambitious obstacles for later path finding phase Then we use a two-level path finding approach for real time searching That is to use common used path finding algorithm on the underlying navigation mesh structure, and then check those small obstacles for the finding path Our... Related Work and Background This thesis studies how to build a search space representation for an architecture environment, and process a real time path finding in the constructed search space representation Our approach is to construct a navigation mesh representation for the walkable surface in an architecture environment with relatively big and obvious obstacles, and process a two-level path finding. .. Chapter 2 describes the related work and gives some survey of the background knowledge on search space representation and path finding process Chapter 3 describes the procedure on construction of navigation mesh from a set of triangle meshes as input Chapter 4 describes the procedure of path finding on the navigation mesh and proposes the algorithm of two-level path finding Chapter 5 concludes the whole... structure construction and also the relative path- finding In our approach, we construct a navigation mesh data structure for the underlying walkable surface with only relatively large obstacles and leave enormous number of small obstacles in the two-level path- finding phase We will show that the real x searching time will be faster in two-level path- finding approach instead of normal path- finding approach... consume for checking these small obstacles in path finding phase, is much less than the time we consume for transferring more nodes because of these small obstacles in most situations We will prove this in later chapter in the thesis This thesis focuses on the underlying data structure construction, and the path finding algorithm for an architecture environment During the underlying data structure construction, ... the disadvantage, we will choose the navigation mesh representation as our search space representation for architecture environment with improvements in the 21 construction process of the navigation mesh representation 22 2.2 Path Finding Algorithm Path finding algorithm is essential in modern games, films, AI systems There are several ways to do path finding process We will talk about two popular approaches... in big terrain or outside field, and do not increase the real searching time much for accuracy path finding, then we can perfectly 3 deal this situation in architecture environment Our approach is to use navigation mesh to represent the underlying data structure, only for the walkable surface with big and obvious obstacles but leave the small and unambitious obstacles for later processing We can show... approaches and underlying data structure construction are not suitable for all the situations In this thesis, we present an approach to semi-automatically construct an underlying structure (Navigation Mesh) in the pre-computing phase, and use a two-level path- finding algorithm during the real searching time for an architecture environment There are many path- finding algorithm approaches with their underlying... are not walkable, and find out a base height for the base walkable surface) before the path finding process 9 This approach is the most naïve one for search space representation That refers to we nearly do nothing in the search space representation construction part It is a very easy work in space representation construction, but leaves all the difficulties and problems into the path finding part One... is therefore a node in the search graph, and the links between adjacent polygons are the edges of the graph Also the navigation mesh representation is more flexible for path finding process Note that it is generally not feasible to use the raw geometry itself for path finding process, as this will be unnecessarily complex Because of all the advantages of the navigation mesh representation and the avoidance ... data structure construction, and the path finding algorithm for an architecture environment During the underlying data structure construction, we choose navigation mesh as basics, and divide the...NAVIGATION MESH CONSTRUCTION AND PATH_ FINDING FOR ARCHITECTURE ENVIRONMENT MAO LEI (B.Comp.(Hons), NUS) A THESIS SUBMITTED FOR THE DEGREE OF MASTER OF SCIENCE DEPARTMENT... Mesh) in the pre-computing phase, and use a two-level path- finding algorithm during the real searching time for an architecture environment There are many path- finding algorithm approaches with

Ngày đăng: 16/10/2015, 11:59

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan