]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trackpart.cpp
Make use of the geometry part of libmspmath
[r2c2.git] / source / libr2c2 / trackpart.cpp
index d8dac075e68701dfc45d8dc3204d315335dd1d5b..b12ea7278da28ce984e1ad156fb0cb3064f8e1b7 100644 (file)
@@ -1,4 +1,11 @@
 #include <cmath>
+#include <msp/geometry/box.h>
+#include <msp/geometry/circle.h>
+#include <msp/geometry/extrudedshape.h>
+#include <msp/geometry/halfspace.h>
+#include <msp/geometry/intersection.h>
+#include <msp/geometry/negation.h>
+#include <msp/geometry/transformedshape.h>
 #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)
@@ -106,29 +119,43 @@ TrackPart *TrackPart::get_link(unsigned i) const
        return links[i];
 }
 
-bool TrackPart::collide_ray(const Vector &start, const Vector &ray, float width) const
+void TrackPart::create_shape()
 {
-       Transform trans = Transform::rotation(dir, Vector(0, 0, -1));
-       Vector local_start = trans.transform(start);
-       Vector local_ray = trans.transform_linear(ray);
-
-       float d = -local_start.z/local_ray.z;
-       if(d<0)
-               return false;
-
-       Vector base = local_start+d*local_ray;
-
+       Transform trans = Transform::translation(pos)*
+               Transform::rotation(dir, LinAl::Vector<float, 3>(0, 0, 1));
        if(radius)
        {
-               base.y -= radius;
-               if(radius<0)
-                       base.y = -base.y;
-               float r = base.norm()-abs(radius);
-               float a = atan2(base.x, -base.y);
-               return (a>=0 && a<=length && r>=-width/2 && r<=width/2);
+               Geometry::ExtrudedShape<float, 3> ring(
+                       Geometry::Intersection<float, 2>(
+                               Geometry::Circle<float>(abs(radius)+0.02),
+                               Geometry::Negation<float, 2>(Geometry::Circle<float>(abs(radius)-0.02))),
+                       0.01);
+               Geometry::HalfSpace<float, 3> start_wall(Vector(-1, 0, 0));
+               Geometry::HalfSpace<float, 3> 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<float, 3> bounds(
+                       Geometry::Box<float>(w, h, 0.01),
+                       Transform::translation(Vector(w/2, (h/2-0.02)*(radius<0 ? -1 : 1)-radius, 0.005)));
+               vector<const Shape *> shapes;
+               shapes.push_back(&ring);
+               shapes.push_back(&start_wall);
+               shapes.push_back(&end_wall);
+               shapes.push_back(&bounds);
+               shape = new Geometry::TransformedShape<float, 3>(
+                       Geometry::Intersection<float, 3>::from_iterator_range(shapes.begin(), shapes.end()),
+                       trans*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<float, 3>(
+                       Geometry::Box<float>(length, 0.04, 0.01),
+                       trans*Transform::translation(Vector(length/2, 0, 0.005)));
+       }
 }