From: Mikko Rasa Date: Mon, 20 May 2013 16:35:31 +0000 (+0300) Subject: Add a distance limit to Ray X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=24f239e418599c13a9d0bdc4942c188ccf0a8437;p=libs%2Fmath.git Add a distance limit to Ray --- diff --git a/source/geometry/hyperbox.h b/source/geometry/hyperbox.h index 10c28d5..845ca34 100644 --- a/source/geometry/hyperbox.h +++ b/source/geometry/hyperbox.h @@ -91,7 +91,7 @@ inline unsigned HyperBox::get_intersections(const Ray &ray, SurfaceP for(int j=-1; j<=1; j+=2) { T x = (T(j)*half_dim[i]-ray.get_start()[i])/ray.get_direction()[i]; - if(x<0) + if(!ray.check_limits(x)) continue; LinAl::Vector p = ray.get_start()+ray.get_direction()*x; diff --git a/source/geometry/hypersphere.h b/source/geometry/hypersphere.h index 48fdb8a..ce424e1 100644 --- a/source/geometry/hypersphere.h +++ b/source/geometry/hypersphere.h @@ -90,7 +90,7 @@ inline unsigned HyperSphere::get_intersections(const Ray &ray, Surfa for(int i=-1; i<=1; i+=2) { T x = mid+offset*i; - if(x>0 && n #include namespace Msp { @@ -12,27 +13,49 @@ class Ray private: LinAl::Vector start; LinAl::Vector direction; + T limit; public: Ray(); Ray(const LinAl::Vector &, const LinAl::Vector &); + Ray(const LinAl::Vector &, const LinAl::Vector &, T); const LinAl::Vector &get_start() const { return start; } const LinAl::Vector &get_direction() const { return direction; } + T get_limit() const { return limit; } + bool check_limits(T) const; }; template -Ray::Ray() +inline Ray::Ray(): + limit(0) { direction[0] = 1; } template -Ray::Ray(const LinAl::Vector &s, const LinAl::Vector &d): +inline Ray::Ray(const LinAl::Vector &s, const LinAl::Vector &d): start(s), - direction(normalize(d)) + direction(normalize(d)), + limit(0) { } +template +inline Ray::Ray(const LinAl::Vector &s, const LinAl::Vector &d, T l): + start(s), + direction(normalize(d)), + limit(l) +{ + if(l<0) + throw std::invalid_argument("Ray::Ray"); +} + +template +inline bool Ray::check_limits(T x) const +{ + return x>=0 && (!limit || x<=limit); +} + } // namespace Geometry } // namespace Msp diff --git a/source/geometry/transformedshape.h b/source/geometry/transformedshape.h index 34fd298..90c37b0 100644 --- a/source/geometry/transformedshape.h +++ b/source/geometry/transformedshape.h @@ -32,6 +32,9 @@ public: virtual HyperBox get_axis_aligned_bounding_box() const; virtual bool contains(const LinAl::Vector &) const; +private: + Ray make_local_ray(const Ray &) const; +public: virtual bool check_intersection(const Ray &) const; virtual unsigned get_max_ray_intersections() const { return shape->get_max_ray_intersections(); } virtual unsigned get_intersections(const Ray &, SurfacePoint *, unsigned) const; @@ -85,19 +88,25 @@ inline bool TransformedShape::contains(const LinAl::Vector &point) c return shape->contains(inverse_trans.transform(point)); } +template +inline Ray TransformedShape::make_local_ray(const Ray &ray) const +{ + LinAl::Vector local_dir = inverse_trans.transform_linear(ray.get_direction()); + float distortion = local_dir.norm(); + return Ray(inverse_trans.transform(ray.get_start()), local_dir, ray.get_limit()*distortion); +} + template inline bool TransformedShape::check_intersection(const Ray &ray) const { - Ray local_ray(inverse_trans.transform(ray.get_start()), - inverse_trans.transform_linear(ray.get_direction())); - return shape->check_intersection(local_ray); + return shape->check_intersection(make_local_ray(ray)); } template inline unsigned TransformedShape::get_intersections(const Ray &ray, SurfacePoint *points, unsigned size) const { - Ray local_ray(inverse_trans.transform(ray.get_start()), - inverse_trans.transform_linear(ray.get_direction())); + Ray local_ray = make_local_ray(ray); + unsigned count = shape->get_intersections(local_ray, points, size); if(points) {