PathVertex.cpp

Go to the documentation of this file.
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 }

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.