diff --git a/geom/ellipse.cpp b/geom/ellipse.cpp index 530339cd..3fcb0418 100644 --- a/geom/ellipse.cpp +++ b/geom/ellipse.cpp @@ -14,10 +14,15 @@ * Copyright 2015-2017 Danny Robson */ -#include "./ellipse.hpp" +#include "ellipse.hpp" -#include "./ops.hpp" -#include "./aabb.hpp" +#include "ops.hpp" +#include "aabb.hpp" +#include "ray.hpp" +#include "sphere.hpp" +#include "point.hpp" + +#include "../matrix.hpp" using util::geom::ellipse; @@ -46,6 +51,29 @@ template bool util::geom::intersects (ellipse<2,float>, util::point<2,float>); template bool util::geom::intersects (ellipse<3,float>, util::point<3,float>); +/////////////////////////////////////////////////////////////////////////////// +// query a ray-ellipse distance by transforming spaces such that the ellipse is +// a sphere +template <> +float +util::geom::distance (ray<3,float> r, ellipse<3,float> e) +{ + // find a transform that puts the ellipse at origin and scales it to a + // unit sphere. + auto const from_scaled = util::scale (e.radius) * + util::look_at (e.origin, {0,0,-1}, e.up); + auto const to_scaled = inverse (from_scaled); + + // transform the ray into this new space and query against a unit sphere + auto const scaled_r = to_scaled * r; + auto const scaled_d = distance (scaled_r, sphere3f {0, 1.f}); + auto const scaled_p = scaled_r.at (scaled_d); + + // transform the result back into the original space + return distance (r.origin, (from_scaled * scaled_p.homog<4> ()).redim<3> ()); +} + + /////////////////////////////////////////////////////////////////////////////// template static util::geom::aabb diff --git a/geom/ellipse.hpp b/geom/ellipse.hpp index 874cfb63..7ea3367b 100644 --- a/geom/ellipse.hpp +++ b/geom/ellipse.hpp @@ -19,6 +19,8 @@ #include +#include "fwd.hpp" + #include "../point.hpp" #include "../vector.hpp" @@ -26,9 +28,28 @@ namespace util::geom { /////////////////////////////////////////////////////////////////////////// template struct ellipse { + // the centre point of the ellipsoid util::point origin; + + // the distance from the centre along each axis to the shape's edge util::vector radius; + + // the orientation of up for the shape + util::vector up; }; + + + /// returns the distance along a ray to the surface of an ellipse. + /// + /// returns infinity if there is no intersection + template + ValueT + distance ( + ray, + ellipse + ); + + using ellipse3f = ellipse<3,float>; }