point/vector: homog no longer takes a size parameter

This commit is contained in:
Danny Robson 2018-04-17 14:26:23 +10:00
parent 0f9fb9b515
commit 76c809f031
11 changed files with 134 additions and 93 deletions

View File

@ -47,30 +47,38 @@ util::geom::intersects (A<S,T> a, B<S,T> b)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template bool util::geom::intersects (ellipse<2,float>, util::point<2,float>);
template bool util::geom::intersects (ellipse<3,float>, util::point<3,float>);
///////////////////////////////////////////////////////////////////////////////
template <size_t DimensionV, typename ValueT>
util::point<DimensionV,ValueT>
util::geom::project (util::geom::ray<DimensionV, ValueT> lhs,
util::geom::ellipse<DimensionV, ValueT> rhs)
{
return lhs.origin + lhs.direction * distance (lhs, rhs);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// query a ray-ellipse distance by transforming spaces such that the ellipse is // query a ray-ellipse distance by transforming spaces such that the ellipse is
// a sphere // a sphere
template <> template <size_t DimensionV, typename ValueT>
float ValueT
util::geom::distance (ray<3,float> r, ellipse<3,float> e) util::geom::distance (ray<DimensionV,ValueT> r, ellipse<DimensionV,ValueT> e)
{ {
// find a transform that puts the ellipse at origin and scales it to a // find a transform that puts the ellipse at origin and scales it to a
// unit sphere. // unit sphere.
auto const from_scaled = util::scale (e.radius) * auto const from_scaled = util::translation (e.origin.template as<vector> ()) *
util::look_at (e.origin, {0,0,-1}, e.up); util::scale (e.radius);
auto const to_scaled = inverse (from_scaled); auto const to_scaled = inverse (from_scaled);
// transform the ray into this new space and query against a unit sphere // transform the ray into this new space and query against a unit sphere
auto const scaled_r = to_scaled * r; auto const scaled_r = to_scaled * r;
auto const scaled_d = distance (scaled_r, sphere3f {0, 1.f}); auto const scaled_d = distance (scaled_r, sphere<DimensionV,ValueT> {0, 1.f});
auto const scaled_p = scaled_r.at (scaled_d); auto const scaled_p = scaled_r.at (scaled_d);
// transform the result back into the original space // transform the result back into the original space
return distance (r.origin, (from_scaled * scaled_p.homog<4> ()).redim<3> ()); return distance (r.origin, (from_scaled * scaled_p.homog ()).template redim<DimensionV> ());
} }
@ -95,6 +103,13 @@ util::geom::bounds (K<S,T> k)
} }
//-----------------------------------------------------------------------------
template util::geom::aabb<2,float> util::geom::bounds (ellipse<2,float>); ///////////////////////////////////////////////////////////////////////////////
template util::geom::aabb<3,float> util::geom::bounds (ellipse<3,float>); #define INSTANTIATE_S_T(S,T) \
template bool util::geom::intersects (ellipse<S,T>, util::point<S,T>); \
template util::point<S,T> util::geom::project(ray<S,T>, ellipse<S,T>); \
template util::geom::aabb<S,T> util::geom::bounds (ellipse<S,T>);
INSTANTIATE_S_T(2,float)
INSTANTIATE_S_T(3,float)

View File

@ -39,6 +39,14 @@ namespace util::geom {
}; };
template <size_t DimensionV, typename ValueT>
point<DimensionV,ValueT>
project (
ray<DimensionV,ValueT>,
ellipse<DimensionV,ValueT>
);
/// returns the distance along a ray to the surface of an ellipse. /// returns the distance along a ray to the surface of an ellipse.
/// ///
/// returns infinity if there is no intersection /// returns infinity if there is no intersection

View File

@ -44,19 +44,6 @@ ray<S,T>::at (T t) const
} }
///////////////////////////////////////////////////////////////////////////////
util::geom::ray3f
util::geom::operator* (util::matrix4f lhs, ray3f rhs)
{
return {
(lhs * rhs.origin.homog<4> ()).redim<3> (),
normalised (
(lhs * rhs.direction.homog<4> ()).redim<3> ()
)
};
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t S, typename T>
std::ostream& std::ostream&

View File

@ -50,8 +50,15 @@ namespace util::geom {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
ray3f template <size_t S, typename T>
operator* (matrix4f, ray3f); ray<S,T>
operator* (matrix<S+1,S+1,T> lhs, ray<S,T> rhs)
{
return {
lhs * rhs.origin,
normalised (lhs * rhs.direction)
};
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@ -225,30 +225,31 @@ util::look_at (const util::point<3,T> eye,
{ 0, 0, 0, 1 }, { 0, 0, 0, 1 },
}}; }};
return rot * util::translation<T> (0-eye); return rot * util::translation (0-eye);
} }
template util::matrix4f util::look_at (util::point3f, util::point3f, util::vector3f); template util::matrix4f util::look_at (util::point3f, util::point3f, util::vector3f);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename T> //template <typename T>
util::matrix4<T> //util::matrix4<T>
util::translation (util::vector<3,T> v) //util::translation (util::vector<3,T> v)
{ //{
return { { // return { {
{ 1.f, 0.f, 0.f, v.x }, // { 1.f, 0.f, 0.f, v.x },
{ 0.f, 1.f, 0.f, v.y }, // { 0.f, 1.f, 0.f, v.y },
{ 0.f, 0.f, 1.f, v.z }, // { 0.f, 0.f, 1.f, v.z },
{ 0.f, 0.f, 0.f, 1.f }, // { 0.f, 0.f, 0.f, 1.f },
} }; // } };
} //}
//
//
template util::matrix4f util::translation (util::vector3f); //template util::matrix4f util::translation (util::vector3f);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if 0
template <typename T> template <typename T>
util::matrix4<T> util::matrix4<T>
util::scale (T mag) util::scale (T mag)
@ -257,22 +258,23 @@ util::scale (T mag)
} }
template util::matrix4f util::scale(float); template util::matrix4f util::scale(float);
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename T> //template <typename T>
util::matrix4<T> //util::matrix4<T>
util::scale (util::vector<3,T> v) //util::scale (util::vector<3,T> v)
{ //{
return { { // return { {
{ v.x, 0.f, 0.f, 0.f }, // { v.x, 0.f, 0.f, 0.f },
{ 0.f, v.y, 0.f, 0.f }, // { 0.f, v.y, 0.f, 0.f },
{ 0.f, 0.f, v.z, 0.f }, // { 0.f, 0.f, v.z, 0.f },
{ 0.f, 0.f, 0.f, 1.f } // { 0.f, 0.f, 0.f, 1.f }
} }; // } };
} //}
template util::matrix4f util::scale(util::vector3f); //template util::matrix4f util::scale(util::vector3f);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -172,12 +172,16 @@ namespace util {
auto auto
operator* (const VectorT &rhs) const operator* (const VectorT &rhs) const
{ {
VectorT out; if constexpr (VectorT::elements + 1 == Cols) {
return (
for (std::size_t r = 0; r < Rows; ++r) *this * rhs.homog ()
out[r] = dot (rhs, values[r]); ).template redim<VectorT::elements> ();
} else {
return out; VectorT out;
for (std::size_t r = 0; r < Rows; ++r)
out[r] = dot (rhs, values[r]);
return out;
}
} }
bool is_affine (void) const; bool is_affine (void) const;
@ -222,11 +226,39 @@ namespace util {
template <typename T> matrix<4,4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up); template <typename T> matrix<4,4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up);
// Affine matrices // Affine matrices
template <typename T> matrix<4,4,T> translation (vector<3,T>); template <size_t S, typename T>
template <typename T> matrix<4,4,T> scale (vector<3,T>); matrix<S+1,S+1,T>
template <typename T> matrix<4,4,T> scale (T); translation (vector<S,T> offset)
{
matrix<S+1,S+1,T> res {};
for (size_t i = 0; i != S; ++i) {
res[i][i] = 1;
res[i][S] = offset[i];
}
res[S][S] = 1;
return res;
}
template <size_t S, typename T>
matrix<S+1,S+1,T>
scale (vector<S,T> factor)
{
matrix<S+1,S+1,T> res {};
for (size_t i = 0; i != S; ++i)
res[i][i] = factor[i];
res[S][S] = 1;
return res;
}
//template <typename T> matrix<4,4,T> translation (vector<3,T>);
//template <typename T> matrix<4,4,T> scale (vector<3,T>);
//template <typename T> matrix<4,4,T> scale (T);
template <typename T> matrix<4,4,T> rotation (T angle, vector<3,T> about); template <typename T> matrix<4,4,T> rotation (T angle, vector<3,T> about);
//template <typename T> matrix<3,3,T> translation (vector<2,T>);
//template <typename T> matrix<3,3,T> scale (vector<2,T>);
template <size_t Rows, size_t Cols, typename ValueT> template <size_t Rows, size_t Cols, typename ValueT>
bool bool

View File

@ -50,26 +50,10 @@ namespace util {
/// expand point to use homogenous coordinates of a higher dimension. /// expand point to use homogenous coordinates of a higher dimension.
/// ie, fill with (0,..,0,1) /// ie, fill with (0,..,0,1)
template <size_t D = 4> point<S+1,T>
point<D,T>
homog (void) const homog (void) const
{ {
static_assert (D > S, "homog will not overwrite data"); return this->template redim<S+1> (1);
point<D,T> out;
// Copy the existing data
auto c = std::copy (this->begin (),
this->end (),
out.begin ());
// Fill until the second last element with zeros
auto f = std::fill_n (c, D - S - 1, T{0});
// Last element should be one
*f = T{1};
return out;
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////

View File

@ -20,8 +20,8 @@ test_matrix_identities (util::TAP::logger &tap)
util::point3f p { 1, 2, 3 }; util::point3f p { 1, 2, 3 };
auto m = util::translation (0-p); auto m = util::translation (0-p);
auto x = m * p.homog<4> (); auto x = m * p;
tap.expect_eq (x, util::point4f {0,0,0,1}, "trivial translation to origin"); tap.expect_eq (x, util::point3f {0}, "trivial translation to origin");
} }
{ {
@ -29,7 +29,7 @@ test_matrix_identities (util::TAP::logger &tap)
auto m = util::rotation<float> (1, { 1, 0, 0 }) * auto m = util::rotation<float> (1, { 1, 0, 0 }) *
util::rotation<float> (1, { 0, 1, 0 }) * util::rotation<float> (1, { 0, 1, 0 }) *
util::rotation<float> (1, { 0, 0, 1 }); util::rotation<float> (1, { 0, 0, 1 });
auto x = m * p.homog<4> (); auto x = m * p.homog ();
tap.expect_eq (x, util::point4f {0,0,0,1}, "trivial rotation at origin"); tap.expect_eq (x, util::point4f {0,0,0,1}, "trivial rotation at origin");
} }
@ -39,7 +39,7 @@ test_matrix_identities (util::TAP::logger &tap)
util::point3f tgt { 0, 0, 0 }; util::point3f tgt { 0, 0, 0 };
auto m = util::look_at (eye, tgt, UP); auto m = util::look_at (eye, tgt, UP);
auto x = m * eye.homog<4> (); auto x = m * eye.homog ();
tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation"); tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation");
} }
@ -48,7 +48,7 @@ test_matrix_identities (util::TAP::logger &tap)
util::point3f tgt { 4, 5, 6 }; util::point3f tgt { 4, 5, 6 };
auto m = util::look_at (eye, tgt, UP); auto m = util::look_at (eye, tgt, UP);
auto x = m * eye.homog<4> (); auto x = m * eye.homog ();
tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation with target"); tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation with target");
} }
} }

View File

@ -29,6 +29,13 @@ main ()
.distance = .5f, .distance = .5f,
.message = "ellipse on origin, extended on z, ray along z", .message = "ellipse on origin, extended on z, ray along z",
}, },
{
.shape = { .origin = 1, .radius = 1, .up = { 0, 1, 0 } },
.caster = { .origin = {1,1,3}, .direction = {0,0,-1} },
.distance = 1.f,
.message = "ellipse at 1,1,1, ray along -z",
}
}; };

View File

@ -65,13 +65,13 @@ main (void)
// redim to 4-dimension homogenous coords // redim to 4-dimension homogenous coords
{ {
const point2f p (3, 4); const point3f p (3, 4, 5);
const point4f q = p.homog<4> (); const point4f q = p.homog ();
tap.expect ( tap.expect (
equal (q.x, 3.f) && equal (q.x, 3.f) &&
equal (q.y, 4.f) && equal (q.y, 4.f) &&
equal (q.z, 0.f) && equal (q.z, 5.f) &&
equal (q.w, 1.f), equal (q.w, 1.f),
"homogenous redim" "homogenous redim"

View File

@ -46,11 +46,10 @@ namespace util {
} }
// representations // representations
template <size_t D = 4> vector<S+1,T>
vector<D,T> homog (void) const homog (void) const
{ {
static_assert (D > S, "reducing size loses data"); return (*this).template redim<S+1> (0.f);
return (*this).template redim<D> (0.f);
} }
// constants // constants