|
9 | 9 | #include "stdafx.h" |
10 | 10 | #include "xrAICore/Navigation/level_graph.h" |
11 | 11 |
|
12 | | -CLevelGraph::CVertex** stack_storage; |
13 | | - |
14 | 12 | #define PUSH(a) *stack_iterator++ = (a) |
15 | 13 | #define POP() vertex = *--stack_iterator |
16 | 14 |
|
17 | | -void floodfill(const CLevelGraph& level_graph, xr_vector<bool>& marks, u32 start_vertex_id) |
| 15 | +void floodfill(const CLevelGraph& level_graph, CLevelGraph::CVertex** stack_storage, xr_vector<bool>& marks, const u32 start_vertex_id) |
18 | 16 | { |
19 | 17 | CLevelGraph::CVertex** stack_iterator = stack_storage; |
20 | | - CLevelGraph::CVertex* vertex = 0; |
21 | | - CLevelGraph::const_iterator I, E; |
22 | | - u32 vertex_id; |
| 18 | + CLevelGraph::CVertex* vertex = nullptr; |
23 | 19 | PUSH(level_graph.vertex(start_vertex_id)); |
24 | 20 | while (stack_iterator != stack_storage) |
25 | 21 | { |
26 | 22 | POP(); |
27 | | - vertex_id = level_graph.vertex_id(vertex); |
| 23 | + auto vertex_id = level_graph.vertex_id(vertex); |
28 | 24 | if (marks[vertex_id]) |
29 | 25 | continue; |
30 | 26 | marks[vertex_id] = true; |
31 | | - level_graph.begin(vertex, I, E); |
32 | | - for (; I != E; ++I) |
| 27 | + for (const auto j : { 0, 1, 2, 3 }) |
33 | 28 | { |
34 | | - u32 neighbour_vertex_id = level_graph.value(vertex, I); |
| 29 | + auto neighbour_vertex_id = vertex->link(j); |
35 | 30 | if (level_graph.valid_vertex_id(neighbour_vertex_id) && !marks[neighbour_vertex_id]) |
36 | 31 | PUSH(level_graph.vertex(neighbour_vertex_id)); |
37 | 32 | } |
38 | 33 | } |
39 | 34 | } |
40 | 35 |
|
41 | | -IC bool single_link(const CLevelGraph& level_graph, u32 i1, u32 i2, u32 link_index) |
42 | | -{ |
43 | | - return (level_graph.value(level_graph.vertex(i1), link_index) != i2); |
44 | | -} |
45 | | - |
46 | 36 | bool verify_invalid_links(const CLevelGraph& graph) |
47 | 37 | { |
48 | 38 | bool result = true; |
49 | | - CLevelGraph::const_vertex_iterator I = graph.begin(); |
50 | | - CLevelGraph::const_vertex_iterator E = graph.end(); |
51 | | - for (; I != E; ++I) |
| 39 | + for (const auto &vertex : graph) |
52 | 40 | { |
53 | | - u32 vertex_id = graph.vertex_id(I); |
54 | | - CLevelGraph::const_iterator i, e; |
55 | | - graph.begin(I, i, e); |
56 | | - for (; i != e; ++i) |
| 41 | + auto vertex_id = graph.vertex_id(&vertex); |
| 42 | + for (const auto j : { 0, 1, 2, 3 }) |
57 | 43 | { |
58 | | - u32 link_vertex_id = graph.value(I, i); |
| 44 | + auto link_vertex_id = vertex.link(j); |
59 | 45 | if (!graph.valid_vertex_id(link_vertex_id)) |
60 | 46 | continue; |
61 | 47 |
|
62 | 48 | if (vertex_id == link_vertex_id) |
63 | 49 | { |
64 | | - Msg("Vertex [%d][%f][%f][%f] has link to itself", vertex_id, VPUSH(graph.vertex_position(I))); |
| 50 | + Msg("Vertex %d[%f][%f][%f] has link to itself", vertex_id, VPUSH(graph.vertex_position(vertex))); |
65 | 51 | result = false; |
66 | 52 | continue; |
67 | 53 | } |
68 | 54 | } |
69 | | - }; |
70 | | - return (result); |
| 55 | + } |
| 56 | + return result; |
71 | 57 | } |
72 | 58 |
|
73 | 59 | void verify_level_graph(LPCSTR name, bool verbose) |
74 | 60 | { |
75 | 61 | Msg("Verifying level %s", name); |
76 | 62 | Logger.Phase("Verifying level graph"); |
77 | 63 | Logger.Progress(0.f); |
78 | | - CLevelGraph* level_graph = new CLevelGraph(name); |
79 | | - if (!level_graph->header().vertex_count()) |
| 64 | + CLevelGraph level_graph(name); |
| 65 | + |
| 66 | + if (!level_graph.header().vertex_count()) |
80 | 67 | { |
81 | 68 | Logger.Progress(1.f); |
82 | 69 | Msg("Level graph is empty!"); |
83 | | - xr_delete(level_graph); |
84 | 70 | return; |
85 | 71 | } |
86 | 72 |
|
87 | | - if (!verify_invalid_links(*level_graph)) |
| 73 | + if (!verify_invalid_links(level_graph)) |
88 | 74 | { |
89 | 75 | Logger.Progress(1.f); |
90 | 76 | Msg("AI map is CORRUPTED : REGENERATE AI-MAP"); |
91 | | - xr_delete(level_graph); |
92 | 77 | return; |
93 | 78 | } |
94 | 79 |
|
95 | | - stack_storage = |
96 | | - (CLevelGraph::CVertex**)xr_malloc(level_graph->header().vertex_count() * sizeof(CLevelGraph::CVertex*)); |
97 | | - |
98 | | - xr_vector<bool> marks; |
99 | | - |
100 | 80 | xr_vector<u32> single_links; |
101 | | - single_links.reserve(level_graph->header().vertex_count()); |
| 81 | + single_links.reserve(level_graph.header().vertex_count()); |
102 | 82 | Logger.Progress(0.05f); |
103 | 83 |
|
104 | | - for (u32 i = 0, n = level_graph->header().vertex_count(); i < n; ++i) |
| 84 | + for (const auto &vertex : level_graph) |
105 | 85 | { |
106 | | - CLevelGraph::const_iterator I, E; |
107 | | - CLevelGraph::CVertex* vertex = level_graph->vertex(i); |
108 | | - level_graph->begin(vertex, I, E); |
109 | | - for (; I != E; ++I) |
| 86 | + for (const auto j : {0, 1, 2, 3}) |
110 | 87 | { |
111 | | - u32 neighbour_vertex_id = level_graph->value(vertex, I); |
112 | | - if (level_graph->valid_vertex_id(neighbour_vertex_id) && |
113 | | - single_link(*level_graph, neighbour_vertex_id, i, (I + 2) % 4)) |
| 88 | + auto neighbour_vertex_id = vertex.link(j); |
| 89 | + if (level_graph.valid_vertex_id(neighbour_vertex_id) && // Valid vertex |
| 90 | + level_graph.vertex(neighbour_vertex_id)->link((j + 2) % 4) != level_graph.vertex_id(&vertex)) // Single vertex |
114 | 91 | { |
115 | 92 | single_links.push_back(neighbour_vertex_id); |
116 | 93 | } |
117 | 94 | } |
118 | | - Logger.Progress(0.05f + 0.05f * float(i) / float(n)); |
| 95 | + Logger.Progress(0.05f + 0.05f * float(level_graph.vertex_id(&vertex)) / float(level_graph.header().vertex_count())); |
119 | 96 | } |
120 | 97 |
|
121 | 98 | bool no_single_links = single_links.empty(); |
122 | 99 | Logger.Progress(0.1f); |
123 | 100 | if (single_links.empty()) |
124 | 101 | single_links.push_back(0); |
125 | 102 |
|
126 | | - { |
127 | | - std::sort(single_links.begin(), single_links.end()); |
128 | | - xr_vector<u32>::iterator I = std::unique(single_links.begin(), single_links.end()); |
129 | | - single_links.erase(I, single_links.end()); |
130 | | - } |
| 103 | + std::sort(single_links.begin(), single_links.end()); |
| 104 | + auto I = std::unique(single_links.begin(), single_links.end()); |
| 105 | + single_links.erase(I, single_links.end()); |
131 | 106 |
|
132 | 107 | if (!no_single_links) |
133 | 108 | { |
134 | 109 | if (verbose) |
135 | | - { |
136 | | - xr_vector<u32>::const_iterator I = single_links.begin(); |
137 | | - xr_vector<u32>::const_iterator E = single_links.end(); |
138 | | - for (; I != E; ++I) |
139 | | - Msg("Vertex %d[%f][%f][%f] is single linked!", *I, VPUSH(level_graph->vertex_position(*I))); |
140 | | - } |
| 110 | + for (const auto &i : single_links) |
| 111 | + Msg("Vertex %d[%f][%f][%f] is single linked!", i, VPUSH(level_graph.vertex_position(i))); |
141 | 112 | Msg("There are %d single linked nodes!", single_links.size()); |
142 | 113 | } |
143 | 114 |
|
144 | 115 | Logger.Progress(0.15f); |
| 116 | + CLevelGraph::CVertex** stack_storage = (CLevelGraph::CVertex**)xr_malloc(level_graph.header().vertex_count() * sizeof(CLevelGraph::CVertex*)); |
| 117 | + xr_vector<bool> marks; |
145 | 118 | bool valid = true; |
146 | | - xr_vector<u32>::const_iterator I = single_links.begin(); |
147 | | - xr_vector<u32>::const_iterator E = single_links.end(); |
148 | | - for (u32 i = 0, n = single_links.size(); I != E; ++I, ++i) |
| 119 | + for (auto &i : single_links) |
149 | 120 | { |
150 | | - marks.assign(level_graph->header().vertex_count(), false); |
151 | | - floodfill(*level_graph, marks, *I); |
152 | | - xr_vector<bool>::const_iterator II = marks.begin(), BB = II; |
153 | | - xr_vector<bool>::const_iterator EE = marks.end(); |
154 | | - for (; II != EE; ++II) |
155 | | - if (!*II) |
| 121 | + marks.assign(level_graph.header().vertex_count(), false); |
| 122 | + floodfill(level_graph, stack_storage, marks, i); |
| 123 | + for (auto &j : marks) |
| 124 | + { |
| 125 | + if (!j) |
156 | 126 | { |
157 | 127 | valid = false; |
| 128 | + auto J = std::distance(&marks.front(), &j); |
158 | 129 | Msg("AI-map is NOT valid :\nNode \n%6d[%f][%f][%f]\ncannot be reached from the node\n%6d[%f][%f][%f]\n", |
159 | | - u32(II - BB), VPUSH(level_graph->vertex_position(u32(II - BB))), *I, |
160 | | - VPUSH(level_graph->vertex_position(*I))); |
| 130 | + J, VPUSH(level_graph.vertex_position(J)), |
| 131 | + i, VPUSH(level_graph.vertex_position(i))); |
161 | 132 | break; |
162 | 133 | } |
| 134 | + } |
163 | 135 |
|
164 | 136 | if (!valid) |
165 | 137 | break; |
166 | | - Logger.Progress(0.15f + 0.85f * float(i) / float(n)); |
| 138 | + Logger.Progress(0.15f + 0.85f * float(std::distance(&single_links.front(), &i)) / float(single_links.size())); |
167 | 139 | } |
168 | 140 |
|
169 | 141 | xr_free(stack_storage); |
170 | | - xr_delete(level_graph); |
171 | 142 | Logger.Progress(1.f); |
| 143 | + |
172 | 144 | if (valid) |
173 | 145 | Msg("AI-map is valid!"); |
174 | 146 |
|
|
0 commit comments