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 "PathVertex.h" 00013 00014 #include "../stream_loader.h" 00015 #include "../FormErrors.h" 00016 #include "../document/MoveNodeDelta.h" 00017 00018 namespace Track 00019 { 00020 00021 const unsigned int path_vertex_newest_version = 1; 00022 00023 PathVertex::PathVertex() 00024 : file_version(0) 00025 , up_handle(0, EditAssist::VertexRotationHandle::DIR_UP) 00026 , forward_handle(0, EditAssist::VertexRotationHandle::DIR_FORWARD) 00027 { 00028 DEBUG_MESSAGE("PathVertex should be initalised with a Track*!"); 00029 assert(false); 00030 throw; 00031 } 00032 00033 PathVertex::PathVertex(const Track * track) 00034 : file_version(0) 00035 , position(btVector3(0, 0, 0)) 00036 , segment(0) 00037 , segment_index(0) 00038 , gradient(btVector3(1.0, 0.0, 0.0)) 00039 , up_handle(get_name(), EditAssist::VertexRotationHandle::DIR_UP) 00040 , forward_handle(get_name(), EditAssist::VertexRotationHandle::DIR_FORWARD) 00041 , track(track) 00042 { 00043 set_angle(btQuaternion::getIdentity()); 00044 update_handles(); 00045 } 00046 00047 PathVertex::PathVertex(std::istream & source, const Theme & theme, const Track * track) 00048 : file_version(int_from_stream(source)) 00049 , up_handle(get_name(), EditAssist::VertexRotationHandle::DIR_UP) 00050 , forward_handle(get_name(), EditAssist::VertexRotationHandle::DIR_FORWARD) 00051 , track(track) 00052 { 00053 if (file_version == 0) throw CorruptedError(); 00054 if (file_version > path_vertex_newest_version) throw NewVersionError(); 00055 source >> position >> gradient >> angle; 00056 std::string segment_name(string_from_stream(source)); 00057 segment_index = theme.get_segment_index(segment_name); 00058 set_segment(segment_index, &theme.get_segment(segment_index)); 00059 set_angle(angle); 00060 update_handles(); 00061 calculate_bounds(); 00062 } 00063 00064 PathVertex::~PathVertex() 00065 { 00066 00067 } 00068 00069 const btVector3 & PathVertex::get_position() const 00070 { 00071 return position; 00072 } 00073 00074 btVector3 PathVertex::get_position(std::size_t index) const 00075 { 00076 return btTransform(angle)(segment->get_connection(index).get_transform().getOrigin()) + position; 00077 } 00078 00079 void PathVertex::set_position(const btVector3 & position_in) 00080 { 00081 position = position_in; 00082 update_handles(); 00083 calculate_bounds(); 00084 } 00085 00086 void PathVertex::update_handles() 00087 { 00088 assert(track); 00089 up_handle.set_centre(position); 00090 up_handle.update_angle(angle); 00091 00092 forward_handle.set_centre(position); 00093 forward_handle.update_angle(angle); 00094 00095 if (segment) 00096 { 00097 connection_angles.resize(segment->get_number_of_connections()); 00098 for (std::size_t index = 0; 00099 index < segment->get_number_of_connections(); 00100 index++) 00101 { 00102 connection_handles[index]->set_position(get_position(index)); 00103 // find angles of connections. 00104 btTransform segment_connection_transform(segment->get_connection(index).get_transform()); 00105 connection_angles[index] = (btTransform(angle) * segment_connection_transform).getRotation(); 00106 } 00107 } 00108 } 00109 00110 const btVector3 & PathVertex::get_gradient() const 00111 { 00112 return gradient; 00113 } 00114 00115 btVector3 PathVertex::get_gradient(std::size_t index) const 00116 { 00117 return btTransform(get_angle(index)) 00118 (btVector3(0.0, 1.0, 0.0)); 00119 } 00120 00121 const btVector3 & PathVertex::get_up() const 00122 { 00123 return up; 00124 } 00125 00126 btVector3 PathVertex::get_up(std::size_t index) const 00127 { 00128 return btTransform(get_angle(index)) 00129 (btVector3(0.0, 0.0, 1.0)); 00130 } 00131 00132 void PathVertex::set_angle(btQuaternion angle_in) 00133 { 00134 angle = angle_in; 00135 const btTransform transform(angle_in); 00136 gradient = transform(btVector3(0, 1.0, 0.0)); 00137 up = transform(btVector3(0, 0.0, 1.0)); 00138 00139 update_handles(); 00140 calculate_bounds(); 00141 } 00142 00143 const btQuaternion & PathVertex::get_angle() const 00144 { 00145 return angle; 00146 } 00147 00148 btQuaternion PathVertex::get_angle(std::size_t index) const 00149 { 00150 return connection_angles[index]; 00151 } 00152 00153 std::size_t PathVertex::get_segment_index() const 00154 { 00155 return segment_index; 00156 } 00157 00158 void PathVertex::set_segment(std::size_t new_segment_index, const Segment * new_segment) 00159 { 00160 assert(new_segment); 00161 segment_index = new_segment_index; 00162 segment = new_segment; 00163 00164 connection_handles.clear(); 00165 connection_handles.reserve(segment->get_number_of_connections()); 00166 for (std::size_t index = 0; 00167 index < segment->get_number_of_connections(); 00168 index++) 00169 { 00170 connection_handles.push_back(boost::shared_ptr<EditAssist::SegmentConnectionHandle>( 00171 new EditAssist::SegmentConnectionHandle( 00172 *track, get_name(), index, &(segment->get_connection(index))) 00173 ) 00174 ); 00175 connection_handles.back()->set_position(get_position(index)); 00176 } 00177 calculate_bounds(); 00178 } 00179 00180 const Segment * PathVertex::get_segment() const 00181 { 00182 return segment; 00183 } 00184 00185 bool PathVertex::is_here(btVector3 start, btVector3 stop, btScalar radius) const 00186 { 00187 btVector3 line = stop - start; 00188 btVector3 to_start = position - start; 00189 btScalar u = to_start.dot(line) / line.length2(); 00190 if (u < 0.0 || u > 1.0) 00191 { 00192 //Nearest to one of the end vertices. Not valid selection. 00193 // Is either behind the viewer or depth clipped, either way 00194 // not on screen so can't be selected. 00195 return false; 00196 } 00197 btScalar distance2 = (u * line).distance2(to_start); 00198 if (distance2 < radius * radius) 00199 { 00200 return true; 00201 } 00202 return false; 00203 } 00204 00205 boost::shared_ptr<Document::DocumentDelta> PathVertex::make_delta(btVector3 new_position) const 00206 { 00207 return boost::shared_ptr<Document::DocumentDelta> 00208 ( 00209 new Document::MoveNodeDelta 00210 ( 00211 Document::NodePositionFinder(get_name()) 00212 , new_position 00213 ) 00214 ); 00215 } 00216 00217 const EditAssist::ControlPoint * PathVertex::get_control_point_here(btVector3 start, btVector3 stop, btScalar radius) const 00218 { 00219 if (up_handle.is_here(start, stop, radius)) 00220 { 00221 return &up_handle; 00222 } 00223 else if (forward_handle.is_here(start, stop, radius)) 00224 { 00225 return &forward_handle; 00226 } 00227 // check segment connection handles 00228 for (std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> >::const_iterator it = connection_handles.begin(); 00229 it != connection_handles.end(); 00230 it++ 00231 ) 00232 { 00233 if ((**it).is_here(start, stop, radius)) 00234 return &(**it); 00235 } 00236 00237 // There is no appropriate control point. 00238 return 0; 00239 } 00240 00241 void PathVertex::draw_control_points() const 00242 { 00243 up_handle.draw(); 00244 forward_handle.draw(); 00245 for (std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> >::const_iterator it = connection_handles.begin(); 00246 it != connection_handles.end(); 00247 it++ 00248 ) 00249 { 00250 (**it).draw(); 00251 } 00252 } 00253 00254 void PathVertex::set_handle_lengths(btScalar handle_length) 00255 { 00256 up_handle.set_length(handle_length); 00257 forward_handle.set_length(handle_length); 00258 update_handles(); 00259 } 00260 00261 const std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> > & 00262 PathVertex::get_connection_handles() const 00263 { 00264 return connection_handles; 00265 } 00266 00267 void PathVertex::set_track(const Track * track_in) 00268 { 00269 track = track_in; 00270 } 00271 00272 void PathVertex::add_collision_faces(btTriangleMesh & shape) const 00273 { 00274 btTransform transform(angle, position); 00275 segment->get_floor_mesh().get_distorted_faces(transform).add_faces(shape); 00276 segment->get_wall_mesh().get_distorted_faces(transform).add_faces(shape); 00277 } 00278 00279 void PathVertex::add_floor_faces(btTriangleMesh & shape) const 00280 { 00281 btTransform transform(angle, position); 00282 segment->get_floor_mesh().get_distorted_faces(transform).add_faces(shape); 00283 } 00284 00285 void PathVertex::add_ai_faces(MeshFaces & mesh) const 00286 { 00287 btTransform transform(angle, position); 00288 MeshFaces faces = segment->get_ai_mesh().get_distorted_faces(transform); 00289 faces.set_source(false, get_name()); 00290 mesh |= faces; 00291 } 00292 00293 AxisAlignedBoundingBox PathVertex::get_bounds() const 00294 { 00295 return m_bounds; 00296 } 00297 00298 void PathVertex::calculate_bounds() 00299 { 00300 m_transform = btTransform(angle, position); 00301 if(segment) 00302 { 00303 m_bounds = segment->get_graphics_mesh().get_faces().get_bounds().transform(m_transform); 00304 m_nav_mesh = segment->get_ai_mesh().get_distorted_faces(m_transform); 00305 m_nav_mesh.set_source(false, get_name()); 00306 m_navigation_graph = m_nav_mesh.get_connectivity(); 00307 } 00308 } 00309 00310 void PathVertex::draw() const 00311 { 00312 assert(segment); 00313 segment->get_texture().bind(); 00314 glPushMatrix(); 00315 btScalar mat[16]; 00316 mat[15] = 1.0; 00317 m_transform.getOpenGLMatrix(mat); 00318 glMultMatrixf(mat); 00319 segment->get_graphics_mesh().get_faces().draw(); 00320 glPopMatrix(); 00321 } 00322 00323 std::ostream & operator<<(std::ostream & destination, const PathVertex & path_vertex) 00324 { 00325 destination << path_vertex_newest_version << ' ' 00326 << path_vertex.position << ' ' 00327 << path_vertex.gradient << ' ' 00328 << path_vertex.angle << ' '; 00329 string_to_stream(destination, path_vertex.segment->get_name()); 00330 return destination; 00331 } 00332 00333 AxisAlignedBoundingBox & operator|=(AxisAlignedBoundingBox & box, 00334 const PathVertex & path_vertex) 00335 { 00336 box |= path_vertex.segment->get_graphics_mesh().get_faces().get_bounds().transform(btTransform(path_vertex.get_angle(), path_vertex.get_position())); 00337 box |= path_vertex.up_handle.get_position(); 00338 box |= path_vertex.forward_handle.get_position(); 00339 return box; 00340 } 00341 00342 }
Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.