X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrackpart.cpp;h=882a6772c7f6cba1b0e9c269ad8ff6a00e0fc8df;hb=28947c087bd2d05c1850e320844f2e33fc0fc253;hp=d8dac075e68701dfc45d8dc3204d315335dd1d5b;hpb=7a36d396eded897c421424905b2c938d770df341;p=r2c2.git diff --git a/source/libr2c2/trackpart.cpp b/source/libr2c2/trackpart.cpp index d8dac07..882a677 100644 --- a/source/libr2c2/trackpart.cpp +++ b/source/libr2c2/trackpart.cpp @@ -1,4 +1,11 @@ #include +#include +#include +#include +#include +#include +#include +#include #include "trackpart.h" using namespace std; @@ -10,12 +17,18 @@ TrackPart::TrackPart(): length(0), radius(0), path(0), - dead_end(false) + dead_end(false), + shape(0) { links[0] = 0; links[1] = 0; } +TrackPart::~TrackPart() +{ + delete shape; +} + float TrackPart::get_length() const { if(radius) @@ -24,35 +37,31 @@ float TrackPart::get_length() const return length; } -TrackPoint TrackPart::get_point(float d) const +OrientedPoint TrackPart::get_point(float d) const { - TrackPoint result; + OrientedPoint result; - Transform dir_trans = Transform::rotation(dir, Vector(0, 0, 1)); if(radius) { Angle a = Angle::from_radians(d/radius); - Vector r = dir_trans.transform(Vector(0, -radius, 0)); - result.pos = pos-r+Transform::rotation(a, Vector(0, 0, 1)).transform(r); - result.dir = dir+a; + result.position = transform.transform(Vector(sin(a)*radius, (1-cos(a))*radius, 0)); + result.rotation = dir+a; } else { - result.pos = pos+dir_trans.transform(Vector(d, 0, 0)); - result.dir = dir; + result.position = transform.transform(Vector(d, 0, 0)); + result.rotation = dir; } return result; } -TrackPoint TrackPart::get_nearest_point(const Vector &p) const +OrientedPoint TrackPart::get_nearest_point(const Vector &p) const { - TrackPoint tp; - Transform dir_trans = Transform::rotation(dir, Vector(0, 0, 1)); + OrientedPoint result; if(radius) { - Vector r = dir_trans.transform(Vector(0, -radius, 0)); - Vector v = p-pos+r; + Vector v = p-transform.transform(Vector(0, radius, 0)); Angle a = Geometry::atan2(v.y, v.x)+Angle::quarter_turn()-dir; if(radius<0) a = Angle::half_turn()-a; @@ -60,18 +69,18 @@ TrackPoint TrackPart::get_nearest_point(const Vector &p) const a = min(max(a, Angle::zero()), Angle::from_radians(length)); if(radius<0) a = -a; - tp.pos = pos-r+Transform::rotation(a, Vector(0, 0, 1)).transform(r); - tp.dir = dir+a; + result.position = transform.transform(Vector(sin(a)*radius, (1-cos(a))*radius, 0)); + result.rotation = dir+a; } else { Vector v = p-pos; - Vector dir_vec = dir_trans.transform(Vector(1, 0, 0)); + Vector dir_vec = transform.transform_linear(Vector(1, 0, 0)); float d = min(max(dot(dir_vec, v), 0.0f), length); - tp.pos = pos+dir_vec*d; - tp.dir = dir; + result.position = pos+dir_vec*d; + result.rotation = dir; } - return tp; + return result; } void TrackPart::check_link(TrackPart &other) @@ -80,14 +89,14 @@ void TrackPart::check_link(TrackPart &other) unsigned n_other_eps = (other.is_dead_end() ? 1 : 2); for(unsigned i=0; i=0 && a<=length && r>=-width/2 && r<=width/2); + Geometry::ExtrudedShape ring( + Geometry::Intersection( + Geometry::Circle(abs(radius)+0.02), + Geometry::Negation(Geometry::Circle(abs(radius)-0.02))), + 0.01); + Geometry::HalfSpace start_wall(Vector(-1, 0, 0)); + Geometry::HalfSpace end_wall(rotated_vector(Vector(1, 0, 0), + Angle::from_radians(length*(radius<0 ? -1 : 1)))); + /* This box only exists so the bounding boxes of curves make sense. It + can be removed when libmspmath produces better bounding boxes. */ + float w = sin(length)*(abs(radius)+0.02); + float h = (1-cos(length))*abs(radius-0.02)+0.04; + Geometry::TransformedShape bounds( + Geometry::Box(w, h, 0.01), + Transform::translation(Vector(w/2, (h/2-0.02)*(radius<0 ? -1 : 1)-radius, 0.005))); + vector shapes; + shapes.push_back(&ring); + shapes.push_back(&start_wall); + shapes.push_back(&end_wall); + shapes.push_back(&bounds); + shape = new Geometry::TransformedShape( + Geometry::Intersection::from_iterator_range(shapes.begin(), shapes.end()), + transform*Transform::translation(Vector(0, radius, 0.005))); } else - return (base.x>=0 && base.x<=length && base.y>=-width/2 && base.y<=width/2); + { + // TODO Get the track profile dimensions from somewhere + shape = new Geometry::TransformedShape( + Geometry::Box(length, 0.04, 0.01), + transform*Transform::translation(Vector(length/2, 0, 0.005))); + } } @@ -153,6 +174,9 @@ void TrackPart::Loader::finish() obj.length /= 1000; obj.pos /= 1000; + + obj.transform = Transform::translation(obj.pos)* + Transform::rotation(obj.dir, Vector(0, 0, 1)); } void TrackPart::Loader::start(float x, float y, float d)