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
// a sphere
template <>
float
util::geom::distance (ray<3,float> r, ellipse<3,float> e)
template <size_t DimensionV, typename ValueT>
ValueT
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
// unit sphere.
auto const from_scaled = util::scale (e.radius) *
util::look_at (e.origin, {0,0,-1}, e.up);
auto const from_scaled = util::translation (e.origin.template as<vector> ()) *
util::scale (e.radius);
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_d = distance (scaled_r, sphere<DimensionV,ValueT> {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> ());
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 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>
std::ostream&

View File

@ -50,8 +50,15 @@ namespace util::geom {
///////////////////////////////////////////////////////////////////////////
ray3f
operator* (matrix4f, ray3f);
template <size_t S, typename T>
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 },
}};
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 <typename T>
util::matrix4<T>
util::translation (util::vector<3,T> v)
{
return { {
{ 1.f, 0.f, 0.f, v.x },
{ 0.f, 1.f, 0.f, v.y },
{ 0.f, 0.f, 1.f, v.z },
{ 0.f, 0.f, 0.f, 1.f },
} };
}
template util::matrix4f util::translation (util::vector3f);
//template <typename T>
//util::matrix4<T>
//util::translation (util::vector<3,T> v)
//{
// return { {
// { 1.f, 0.f, 0.f, v.x },
// { 0.f, 1.f, 0.f, v.y },
// { 0.f, 0.f, 1.f, v.z },
// { 0.f, 0.f, 0.f, 1.f },
// } };
//}
//
//
//template util::matrix4f util::translation (util::vector3f);
//-----------------------------------------------------------------------------
#if 0
template <typename T>
util::matrix4<T>
util::scale (T mag)
@ -257,22 +258,23 @@ util::scale (T mag)
}
template util::matrix4f util::scale(float);
#endif
//-----------------------------------------------------------------------------
template <typename T>
util::matrix4<T>
util::scale (util::vector<3,T> v)
{
return { {
{ v.x, 0.f, 0.f, 0.f },
{ 0.f, v.y, 0.f, 0.f },
{ 0.f, 0.f, v.z, 0.f },
{ 0.f, 0.f, 0.f, 1.f }
} };
}
//template <typename T>
//util::matrix4<T>
//util::scale (util::vector<3,T> v)
//{
// return { {
// { v.x, 0.f, 0.f, 0.f },
// { 0.f, v.y, 0.f, 0.f },
// { 0.f, 0.f, v.z, 0.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
operator* (const VectorT &rhs) const
{
VectorT out;
for (std::size_t r = 0; r < Rows; ++r)
out[r] = dot (rhs, values[r]);
return out;
if constexpr (VectorT::elements + 1 == Cols) {
return (
*this * rhs.homog ()
).template redim<VectorT::elements> ();
} else {
VectorT out;
for (std::size_t r = 0; r < Rows; ++r)
out[r] = dot (rhs, values[r]);
return out;
}
}
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);
// Affine matrices
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 <size_t S, typename T>
matrix<S+1,S+1,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<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>
bool

View File

@ -50,26 +50,10 @@ namespace util {
/// expand point to use homogenous coordinates of a higher dimension.
/// ie, fill with (0,..,0,1)
template <size_t D = 4>
point<D,T>
point<S+1,T>
homog (void) const
{
static_assert (D > S, "homog will not overwrite data");
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;
return this->template redim<S+1> (1);
}
///////////////////////////////////////////////////////////////////////

View File

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

View File

@ -29,6 +29,13 @@ main ()
.distance = .5f,
.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
{
const point2f p (3, 4);
const point4f q = p.homog<4> ();
const point3f p (3, 4, 5);
const point4f q = p.homog ();
tap.expect (
equal (q.x, 3.f) &&
equal (q.y, 4.f) &&
equal (q.z, 0.f) &&
equal (q.z, 5.f) &&
equal (q.w, 1.f),
"homogenous redim"

View File

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