]> Dogcows Code - chaz/yoink/blobdiff - src/moof/line.hh
the massive refactoring effort
[chaz/yoink] / src / moof / line.hh
diff --git a/src/moof/line.hh b/src/moof/line.hh
new file mode 100644 (file)
index 0000000..b40e7cf
--- /dev/null
@@ -0,0 +1,283 @@
+
+/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+**]  All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_LINE_HH_
+#define _MOOF_LINE_HH_
+
+/**
+ * \file line.hh
+ * Classes related to line segments.
+ */
+
+#include <moof/contact.hh>
+#include <moof/drawable.hh>
+#include <moof/log.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/ray.hh>
+#include <moof/shape.hh>
+#include <moof/sphere.hh>
+#include <moof/texture.hh>
+
+
+namespace moof {
+
+
+template <int D>
+struct line : public drawable, public shape<D>
+{
+       typedef moof::vector< scalar, fixed<D> > vector;
+
+
+       vector  a;
+       vector  b;
+
+
+       line() {}
+
+       line(const vector& point1, const vector& point2) :
+               a(point1),
+               b(point2) {}
+
+
+       vector direction() const
+       {
+               return b - a;
+       }
+
+       scalar length() const
+       {
+               return direction().length();
+       }
+
+
+       bool intersect(const line& other, contact<D>& hit) const
+       {
+               scalar d = (other.b[1] - other.a[1]) * (b[0] - a[0]) -
+                                  (other.b[0] - other.a[0]) * (b[1] - a[1]);
+
+               if (d == SCALAR(0.0)) return false;                     // lines are parallel
+               // ignoring the (somewhat remote) possibility of coincidence
+
+               scalar m = ((other.b[0] - other.a[0]) * (a[1] - other.a[1]) -
+                                       (other.b[1] - other.a[1]) * (a[0] - other.a[0])) / d;
+
+               scalar n = ((b[0] - a[0]) * (b[1] - other.a[1]) -
+                                       (b[1] - a[1]) * (b[0] - other.a[0])) / d;
+
+               if (m < SCALAR(0.0) || m > SCALAR(1.0) ||       // not intersecting
+                       n < SCALAR(0.0) || n > SCALAR(1.0)) return false;
+
+               vector2 tangent = b - a;
+               vector2 normal = perp(tangent).normalize();
+
+               if (dot(normal, other.a - other.b) < SCALAR(0.0))
+               {
+                       normal = -normal;
+               }
+
+               hit.point = a + m * tangent;
+               hit.normal = normal;
+               hit.distance = (other.b - hit.point).length();
+
+               return true;
+       }
+
+       bool intersect(const sphere<D>& other, contact<D>& hit) const
+       {
+               vector surface = b - a;
+               vector toPoint = other.point - a;
+
+               scalar surfaceLength = surface.length();
+               surface.normalize();
+
+               scalar projection = dot(surface, toPoint);
+
+               if (projection < SCALAR(0.0) || projection > surfaceLength)
+               {
+                       // try endpoints
+                       
+                       if (other.intersect(a, hit))
+                       {
+                               hit.normal = -hit.normal;
+                               hit.point = a;
+                               return true;
+                       }
+                       else if (other.intersect(b, hit))
+                       {
+                               hit.normal = -hit.normal;
+                               hit.point = b;
+                               return true;
+                       }
+                       
+                       return false;
+               }
+
+               vector point = a + surface * projection;
+               vector normal = other.point - point;
+
+               scalar distance = normal.length();
+
+               if (distance > other.radius) false;             // not intersecting
+
+               normal.normalize();
+
+               hit.distance = other.radius - distance;
+               hit.point = point;
+               hit.normal = normal;
+
+               return true;
+       }
+
+
+       bool intersect_ray(const ray<2>& ray, ray<2>::contact& hit) const
+       {
+               vector2 v1 = a - ray.point;
+               scalar  a1 = signed_angle_2D(v1, b - ray.point);
+
+               //log_warning << "angle:::::::::: " << a1 << std::endl;
+
+               if (a1 == constants::pi())
+               {
+                       hit.distance = 5.4321;
+                       return true;
+               }
+               else if (a1 == SCALAR(0.0))
+               {
+                       hit.distance = 99999.0;
+                       return true;
+               }
+
+               scalar  a2 = signed_angle_2D(v1, ray.direction);
+
+               if (a2 < SCALAR(0.0) || a2 > a1) return false;
+
+               //hit.distance = 1.23456;
+               //hit.normal = vector2(0.0, 0.0);
+
+               vector2 n = (b - a).normalize();
+               scalar  z = dot(ray.point - a, n);
+               vector2 p = a + n * z;
+               hit.distance = (ray.point - p).length();
+               hit.normal = perp(a - b);
+               return true;
+
+
+               /*
+               // solve: Cx + r*Dx = Ax + s(Bx - Ax)
+               //        Cy + r*Dy = Ay + s(By - Ay)
+               // where: 0 <= s <= 1 if intersection
+               // given: A = a
+               //        B = b
+               //        C = ray.point
+               //        D = ray.direction
+
+               scalar denom = ray.direction[0] * (b[1] - a[1]) +
+                                          ray.direction[1] * (a[0] - b[0]);
+
+               // check if the ray and line are parallel
+               //if (is_equal(denom, SCALAR(0.0)))
+               if (denom == SCALAR(0.0))
+               {
+                       scalar numer = a[0] * (ray.point[1] - b[1]) +
+                                                  b[0] * (a[1] - ray.point[1]) +
+                                                  ray.point[0] * (b[1] - a[1]);
+
+                       // check if they are collinear
+                       if (is_equal(numer, SCALAR(0.0)))
+                       {
+                               hit.distance = SCALAR(0.0);
+                               hit.normal.set(0.0, 0.0);
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               scalar s = (ray.direction[0] * (ray.point[1] - a[1]) +
+                                       ray.direction[1] * (a[0] - ray.point[0])) / denom;
+
+               // check if the ray hits the segment
+               if (s < SCALAR(0.0) || s > SCALAR(1.0)) return false;
+
+               hit.distance = -(a[0] * (ray.point[1] - b[1]) +
+                                                b[0] * (a[1] - ray.point[1]) +
+                                                ray.point[0] * (b[1] - a[1])) / denom;
+
+               // check if the intersection is behind the ray
+               if (hit.distance < SCALAR(0.0)) return false;
+
+               vector normal = perp(a - b);
+               if (dot(a - ray.point, normal) < 0) hit.normal = normal;
+               else                                     hit.normal = -normal;
+               return true;
+               */
+       }
+
+
+       void draw(scalar alpha = 0.0) const
+       {
+               texture::reset_binding();
+               glBegin(GL_LINES);
+                       glVertex(a);
+                       glVertex(b);
+               glEnd();
+       }
+};
+
+
+typedef line<2>                line2;
+typedef line<3>                line3;
+
+
+template <int D, int N>
+struct polygon : public drawable, public shape<D>
+{
+       typedef moof::vector< scalar, fixed<D> > vector;
+
+       vector  points[N];
+
+       polygon() {}
+
+       bool intersect_ray(const ray<D>& ray, typename ray<D>::contact& hit)
+       {
+               return false;
+       }
+
+       void draw(scalar alpha = 0.0) const
+       {
+               texture::reset_binding();
+               glBegin(GL_POLYGON);
+               for (int i = 0; i < D; ++i)
+               {
+                       glVertex(points[0]);
+               }
+               glEnd();
+       }
+};
+
+
+typedef polygon<2,3>   triangle2;
+typedef polygon<3,3>   triangle3;
+
+
+template <int D>
+bool intersect(const line<D>& line, const sphere<D>& sphere,
+                          contact<D>& hit)
+{
+       return false;
+}
+
+
+} // namespace moof
+
+#endif // _MOOF_LINE_HH_
+
This page took 0.021326 seconds and 4 git commands to generate.