00001 00005 /* Copyright © 2009, 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 00012 #include "Path.h" 00013 #include "../stream_loader.h" 00014 #include "../FormErrors.h" 00015 00016 #include <limits> 00017 00018 namespace Track 00019 { 00020 00021 const unsigned int path_newest_version = 2; 00022 00023 Path::Path(std::istream & source, const Theme & theme, const Track * track, 00024 bool editor) 00025 : file_version(int_from_stream(source)) 00026 , editor(editor) 00027 , theme(theme) 00028 , starting_edge(0) 00029 { 00030 if (file_version == 0) throw CorruptedError(); 00031 if (file_version > path_newest_version) throw NewVersionError(); 00032 // We store the graph in the stream as a vector of vertices, followed by a 00033 // vector of edges. 00034 std::size_t number_of_vertices; 00035 source >> number_of_vertices; 00036 // add vertices with descriptors 00037 for (std::size_t vertex_index = 0; 00038 vertex_index < number_of_vertices; 00039 vertex_index++) 00040 { 00041 boost::add_vertex(PathVertex(source, theme, track), graph); 00042 } 00043 00044 // now on to the edges 00045 std::size_t number_of_edges; 00046 source >> number_of_edges; 00047 for (std::size_t edge_index = 0; edge_index < number_of_edges; edge_index++) 00048 { 00049 // Read vertex indices 00050 std::size_t vert_index_start, vert_index_end; 00051 source >> vert_index_start >> vert_index_end; 00052 if ( vert_index_start > num_vertices(graph) 00053 || vert_index_end > num_vertices(graph)) 00054 { 00055 // File refers to vertices that don't exist, so it must be invalid. 00056 throw CorruptedError(); 00057 } 00058 00059 // Read edge data 00060 PathEdge edge_data(source, theme); 00061 00062 std::pair<Graph::edge_descriptor, bool> new_edge = 00063 add_edge(vert_index_start, vert_index_end, edge_data, graph); 00064 // update the edge's information (length, meshes, and so on). 00065 PathEdge & new_edge_data = graph[new_edge.first]; 00066 new_edge_data.render_mode = editor ? DrawableMesh::RM_WIREFRAME : DrawableMesh::RM_SOLID; 00067 new_edge_data.update(graph[vert_index_start].get_name(), 00068 graph[vert_index_end].get_name(), 00069 this); 00070 if (file_version >= 2) 00071 { 00072 bool is_start_edge; 00073 source >> is_start_edge; 00074 if(is_start_edge) starting_edge = new_edge_data.get_name(); 00075 } 00076 } 00077 00078 if (starting_edge == 0) 00079 { 00080 // Starting edge was not recorded. 00081 // Set it to the first edge if there is one. 00082 if (boost::num_edges(graph) > 0) 00083 { 00084 starting_edge = graph[*(boost::edges(graph).first)].get_name(); 00085 } 00086 } 00087 } 00088 00089 Path::Path(const Theme & theme, const Track * track, bool editor) 00090 : file_version(0) 00091 , editor(editor) 00092 , theme(theme) 00093 , starting_edge(0) 00094 { 00095 } 00096 00097 Path::~Path() 00098 { 00099 00100 } 00101 00102 std::ostream & operator<<(std::ostream & destination, const Path & path) 00103 { 00104 destination << path_newest_version << ' '; 00105 // vertices 00106 destination << boost::num_vertices(path.graph) << ' '; 00107 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00108 std::pair<VertexIterator, VertexIterator> vertex_range; 00109 for (vertex_range = boost::vertices(path.graph); 00110 vertex_range.first != vertex_range.second; 00111 vertex_range.first++) 00112 { 00113 destination << path.graph[*(vertex_range.first)] << ' '; 00114 } 00115 00116 destination << boost::num_edges(path.graph) << ' '; 00117 typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator; 00118 std::pair<EdgeIterator, EdgeIterator> edge_range; 00119 for (edge_range = boost::edges(path.graph); 00120 edge_range.first != edge_range.second; 00121 edge_range.first++) 00122 { 00123 // output the vertex descriptor of the source and target vertices, 00124 // so the graph can be reconstructed. 00125 destination << boost::source(*(edge_range.first), path.graph) << ' ' 00126 << boost::target(*(edge_range.first), path.graph) << ' ' 00127 // Now output the the PathEdge information. 00128 << path.graph[*(edge_range.first)] << ' ' 00129 // is this the starting edge? 00130 // we write it like this so we can safely load a Path where the 00131 // starting edge has been deleted, even though it saves space just to 00132 // identify the right one at the end. 00133 << (path.graph[*(edge_range.first)].get_name() == path.starting_edge) << ' '; 00134 } 00135 return destination; 00136 } 00137 00138 AxisAlignedBoundingBox Path::get_bounding_box() const 00139 { 00140 AxisAlignedBoundingBox result; 00141 00142 // find the bounding box of all the vertices. 00143 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00144 std::pair<VertexIterator, VertexIterator> vertex_range; 00145 for (vertex_range = boost::vertices(graph); 00146 vertex_range.first != vertex_range.second; 00147 vertex_range.first++) 00148 { 00149 result |= graph[*(vertex_range.first)]; 00150 } 00151 00152 // now expand to include control points 00153 typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; 00154 std::pair<EdgeIterator, EdgeIterator> edge_range; 00155 for (edge_range = boost::edges(graph); 00156 edge_range.first != edge_range.second; 00157 edge_range.first++) 00158 { 00159 const Graph::edge_descriptor edge_descriptor = *(edge_range.first); 00160 const PathEdge & edge = graph[edge_descriptor]; 00161 result |= edge; 00162 } 00163 00164 // add some padding. 00165 result.add_border(20.0); 00166 00167 return result; 00168 } 00169 00170 PathVertex & Path::get_node(const std::size_t index) 00171 { 00172 return graph[get_node_descriptor(index)]; 00173 } 00174 00175 const PathVertex & Path::get_node(const std::size_t index) const 00176 { 00177 return graph[get_node_descriptor(index)]; 00178 } 00179 00180 Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index) 00181 { 00182 return get_node_descriptor_internal(index); 00183 } 00184 00185 const Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index) const 00186 { 00187 return get_node_descriptor_internal(index); 00188 } 00189 00190 Path::Graph::vertex_descriptor Path::get_node_descriptor_internal(const std::size_t index) const 00191 { 00193 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00194 std::pair<VertexIterator, VertexIterator> vertex_range; 00195 for (vertex_range = boost::vertices(graph); 00196 vertex_range.first != vertex_range.second; 00197 vertex_range.first++) 00198 { 00199 const PathVertex & vertex = graph[*(vertex_range.first)]; 00200 if (vertex.get_name() == index) 00201 { 00202 return *(vertex_range.first); 00203 } 00204 } 00205 DEBUG_MESSAGE("No node has index " << index << ", aborting."); 00206 assert(false); 00207 throw; 00208 } 00209 00210 00211 PathEdge & Path::get_edge(const std::size_t index) 00212 { 00213 return graph[get_edge_descriptor(index)]; 00214 } 00215 00216 const PathEdge & Path::get_edge(const std::size_t index) const 00217 { 00218 return graph[get_edge_descriptor(index)]; 00219 } 00220 00221 Path::Graph::edge_descriptor Path::get_edge_descriptor(const std::size_t index) 00222 { 00223 return get_edge_descriptor_internal(index); 00224 } 00225 00226 const Path::Graph::edge_descriptor Path::get_edge_descriptor(const std::size_t index) const 00227 { 00228 return get_edge_descriptor_internal(index); 00229 } 00230 00231 Path::Graph::edge_descriptor Path::get_edge_descriptor_internal(const std::size_t index) const 00232 { 00234 typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator; 00235 std::pair<EdgeIterator, EdgeIterator> edge_range; 00236 for (edge_range = boost::edges(graph); 00237 edge_range.first != edge_range.second; 00238 edge_range.first++) 00239 { 00240 const PathEdge & edge = graph[*(edge_range.first)]; 00241 if (edge.get_name() == index) 00242 { 00243 return *(edge_range.first); 00244 } 00245 } 00246 DEBUG_MESSAGE("No edge has index " << index << ", aborting."); 00247 assert(false); 00248 throw; 00249 } 00250 00251 void Path::set_handle_lengths(btScalar handle_length) 00252 { 00253 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00254 std::pair<VertexIterator, VertexIterator> vertex_range; 00255 for (vertex_range = boost::vertices(graph); 00256 vertex_range.first != vertex_range.second; 00257 vertex_range.first++) 00258 { 00259 graph[*(vertex_range.first)].set_handle_lengths(handle_length); 00260 } 00261 } 00262 00263 void Path::update_connected_edges(Path::Graph::vertex_descriptor vertex_descriptor) 00264 { 00265 // edges out of the vertex 00266 typedef boost::graph_traits<Graph>::out_edge_iterator OutEdgeIterator; 00267 std::pair<OutEdgeIterator, OutEdgeIterator> out_edge_range; 00268 for (out_edge_range = boost::out_edges(vertex_descriptor, graph); 00269 out_edge_range.first != out_edge_range.second; 00270 out_edge_range.first++) 00271 { 00272 PathEdge & edge = graph[*(out_edge_range.first)]; 00273 edge.update(); 00274 } 00275 // edges into the vertex 00276 typedef boost::graph_traits<Graph>::in_edge_iterator InEdgeIterator; 00277 std::pair<InEdgeIterator, InEdgeIterator> in_edge_range; 00278 for (in_edge_range = boost::in_edges(vertex_descriptor, graph); 00279 in_edge_range.first != in_edge_range.second; 00280 in_edge_range.first++) 00281 { 00282 PathEdge & edge = graph[*(in_edge_range.first)]; 00283 edge.update(); 00284 } 00285 } 00286 00287 const EditAssist::SegmentConnectionHandle * Path::get_nearest_segment_connection_handle(btVector3 position) const 00288 { 00289 btScalar best_distance = std::numeric_limits<btScalar>::max(); 00290 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00291 std::pair<VertexIterator, VertexIterator> vertex_range; 00292 btVector3 best_handle_position(0, 0, 0); 00293 const EditAssist::SegmentConnectionHandle * best_handle = 0; 00294 for (vertex_range = boost::vertices(graph); 00295 vertex_range.first != vertex_range.second; 00296 vertex_range.first++) 00297 { 00298 const PathVertex & vertex = graph[*(vertex_range.first)]; 00299 const std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> > & handles = 00300 vertex.get_connection_handles(); 00301 00302 for (std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> >::const_iterator it = handles.begin(); 00303 it != handles.end(); 00304 it++) 00305 { 00306 btScalar this_distance = (**it).get_position().distance2(position); 00307 if (this_distance < best_distance) 00308 { 00309 best_handle = &(**it); 00310 best_distance = this_distance; 00311 } 00312 } 00313 } 00314 return best_handle; 00315 } 00316 00317 const EditAssist::SegmentConnectionHandle * Path::get_nearest_segment_connection_handle(btVector3 position, btVector3 normal) const 00318 { 00320 return get_nearest_segment_connection_handle(position); 00321 } 00322 00323 void Path::add_collision_faces(btTriangleMesh & shape) const 00324 { 00325 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00326 std::pair<VertexIterator, VertexIterator> vertex_range; 00327 for (vertex_range = boost::vertices(graph); 00328 vertex_range.first != vertex_range.second; 00329 vertex_range.first++) 00330 { 00331 graph[*(vertex_range.first)].add_collision_faces(shape); 00332 } 00333 00334 typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator; 00335 std::pair<EdgeIterator, EdgeIterator> edge_range; 00336 for (edge_range = boost::edges(graph); 00337 edge_range.first != edge_range.second; 00338 edge_range.first++) 00339 { 00340 graph[*(edge_range.first)].add_collision_faces(shape); 00341 } 00342 } 00343 00344 void Path::add_floor_faces(btTriangleMesh & shape) const 00345 { 00346 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00347 std::pair<VertexIterator, VertexIterator> vertex_range; 00348 for (vertex_range = boost::vertices(graph); 00349 vertex_range.first != vertex_range.second; 00350 vertex_range.first++) 00351 { 00352 graph[*(vertex_range.first)].add_floor_faces(shape); 00353 } 00354 00355 typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator; 00356 std::pair<EdgeIterator, EdgeIterator> edge_range; 00357 for (edge_range = boost::edges(graph); 00358 edge_range.first != edge_range.second; 00359 edge_range.first++) 00360 { 00361 graph[*(edge_range.first)].add_floor_faces(shape); 00362 } 00363 } 00364 00365 void Path::add_ai_faces(MeshFaces & mesh) const 00366 { 00367 typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; 00368 std::pair<VertexIterator, VertexIterator> vertex_range; 00369 for (vertex_range = boost::vertices(graph); 00370 vertex_range.first != vertex_range.second; 00371 vertex_range.first++) 00372 { 00373 graph[*(vertex_range.first)].add_ai_faces(mesh); 00374 } 00375 00376 typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator; 00377 std::pair<EdgeIterator, EdgeIterator> edge_range; 00378 for (edge_range = boost::edges(graph); 00379 edge_range.first != edge_range.second; 00380 edge_range.first++) 00381 { 00382 graph[*(edge_range.first)].add_ai_faces(mesh); 00383 } 00384 } 00385 00386 unsigned long int Path::get_starting_edge() const 00387 { 00388 return starting_edge; 00389 } 00390 00391 void Path::set_starting_edge(unsigned long int new_edge_name) 00392 { 00393 starting_edge = new_edge_name; 00394 } 00395 00396 00397 void Path::find_start_plane(btVector3 & normal, btScalar & distance) const 00398 { 00399 assert(starting_edge); 00400 const PathEdge & edge(get_edge(starting_edge)); 00401 btTransform transform = edge.get_transform(1.0); 00402 // plane goes through origin 00403 btVector3 origin = transform.getOrigin(); 00404 normal = transform(btVector3(0.0, 1.0, 0.0)) - origin; 00405 distance = -normal.dot(origin); 00406 } 00407 00408 btVector3 Path::find_start_position() const 00409 { 00410 assert(starting_edge); 00411 const PathEdge & edge(get_edge(starting_edge)); 00412 return edge.get_transform(1.0).getOrigin(); 00413 } 00414 00415 void Path::draw() const 00416 { 00417 // edges 00418 typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; 00419 std::pair<EdgeIterator, EdgeIterator> edge_range; 00420 for (edge_range = boost::edges(graph); 00421 edge_range.first != edge_range.second; 00422 edge_range.first++) 00423 { 00424 const PathEdge & edge = graph[*(edge_range.first)]; 00425 edge.draw(); 00426 } 00427 // vertices. 00428 typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator; 00429 std::pair<VertexIterator, VertexIterator> vertex_range; 00430 for (vertex_range = boost::vertices(graph); 00431 vertex_range.first != vertex_range.second; 00432 vertex_range.first++) 00433 { 00434 const PathVertex & vertex = graph[*(vertex_range.first)]; 00435 vertex.draw(); 00436 } 00437 } 00438 00439 void Path::conditional_draw(const OcclusionTester & occlusion_tester) const 00440 { 00444 // edges 00445 typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; 00446 std::pair<EdgeIterator, EdgeIterator> edge_range; 00447 for (edge_range = boost::edges(graph); 00448 edge_range.first != edge_range.second; 00449 edge_range.first++) 00450 { 00451 const PathEdge & edge = graph[*(edge_range.first)]; 00452 edge.conditional_draw(occlusion_tester); 00453 } 00454 // vertices. 00455 typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator; 00456 std::pair<VertexIterator, VertexIterator> vertex_range; 00457 for (vertex_range = boost::vertices(graph); 00458 vertex_range.first != vertex_range.second; 00459 vertex_range.first++) 00460 { 00461 const PathVertex & vertex = graph[*(vertex_range.first)]; 00462 vertex.conditional_draw(occlusion_tester); 00463 } 00464 } 00465 00466 AxisAlignedBoundingBox Path::get_bounds() const 00467 { 00468 // bounds of all components. 00469 AxisAlignedBoundingBox bounds; 00473 // edges 00474 typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; 00475 std::pair<EdgeIterator, EdgeIterator> edge_range; 00476 for (edge_range = boost::edges(graph); 00477 edge_range.first != edge_range.second; 00478 edge_range.first++) 00479 { 00480 const PathEdge & edge = graph[*(edge_range.first)]; 00481 bounds |= edge; 00482 } 00483 // vertices. 00484 typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator; 00485 std::pair<VertexIterator, VertexIterator> vertex_range; 00486 for (vertex_range = boost::vertices(graph); 00487 vertex_range.first != vertex_range.second; 00488 vertex_range.first++) 00489 { 00490 const PathVertex & vertex = graph[*(vertex_range.first)]; 00491 bounds |= vertex; 00492 } 00493 return bounds; 00494 } 00495 00496 }
Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.