X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fcml%2Fmathlib%2Fprojection.h;fp=src%2Fcml%2Fmathlib%2Fprojection.h;h=7996851b1690e4031bc764b649e47cddb6831560;hp=0000000000000000000000000000000000000000;hb=6b0a0d0efafe34d48ab344fca3b479553bd4e62c;hpb=85783316365181491a3e3c0c63659972477cebba diff --git a/src/cml/mathlib/projection.h b/src/cml/mathlib/projection.h new file mode 100644 index 0000000..7996851 --- /dev/null +++ b/src/cml/mathlib/projection.h @@ -0,0 +1,142 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + */ + +#ifndef projection_h +#define projection_h + +#include +#include + +/* Functions for projection and 'unprojection' of points in 3D. */ + +namespace cml { + +namespace detail { + +template < typename E > void +divide_by_w(vector< E,fixed<4> >& v) { + v *= E(1) / v[3]; +} + +} // namespace detail + +/* Project a point to screen space using the given model, view, projection, + * and viewport matrices. The z value of the returned point is a depth value + * in the range specified by the viewport matrix. + */ + +template +vector< typename VecT::value_type, fixed<3> > project_point( + const MatT_1& model, + const MatT_2& view, + const MatT_3& projection, + const MatT_4& viewport, + const VecT& p) +{ + return project_point( + detail::matrix_concat_transforms_4x4(model,view), + projection, + viewport, + p + ); +} + +/* Project a point to screen space using the given modelview, projection, and + * viewport matrices. The z value of the returned point is a depth value in + * the range specified by the viewport matrix. + */ + +template < class MatT_1, class MatT_2, class MatT_3, class VecT > +vector< typename VecT::value_type, fixed<3> > project_point( + const MatT_1& modelview, + const MatT_2& projection, + const MatT_3& viewport, + const VecT& p) +{ + typedef vector< typename VecT::value_type, fixed<3> > vector3_type; + typedef vector< typename VecT::value_type, fixed<4> > vector4_type; + typedef typename vector3_type::value_type value_type; + + detail::CheckVec3(p); + + vector4_type result = transform_vector_4D( + detail::matrix_concat_transforms_4x4( + modelview, + detail::matrix_concat_transforms_4x4( + projection, + viewport + ) + ), + vector4_type(p[0],p[1],p[2],value_type(1)) + ); + detail::divide_by_w(result); + return vector3_type(result[0],result[1],result[2]); +} + +/* 'Unproject' a point from screen space using the given model, view, + * projection, and viewport matrices. The z value of the input point is a + * depth value in the range specified by the viewport matrix. + */ + +template +vector< typename VecT::value_type, fixed<3> > unproject_point( + const MatT_1& model, + const MatT_2& view, + const MatT_3& projection, + const MatT_4& viewport, + const VecT& p) +{ + return unproject_point( + detail::matrix_concat_transforms_4x4(model,view), + projection, + viewport, + p + ); +} + +/* 'Unproject' a point from screen space using the given modelview, + * projection, and viewport matrices. The z value of the input point is a + * depth value in the range specified by the viewport matrix. + */ + +template < class MatT_1, class MatT_2, class MatT_3, class VecT > +vector< typename VecT::value_type, fixed<3> > unproject_point( + const MatT_1& modelview, + const MatT_2& projection, + const MatT_3& viewport, + const VecT& p) +{ + typedef vector< typename VecT::value_type, fixed<3> > vector3_type; + typedef vector< typename VecT::value_type, fixed<4> > vector4_type; + typedef typename vector3_type::value_type value_type; + + detail::CheckVec3(p); + + vector4_type result = transform_vector_4D( + inverse( + detail::matrix_concat_transforms_4x4( + modelview, + detail::matrix_concat_transforms_4x4( + projection, + viewport + ) + ) + ), + vector4_type(p[0],p[1],p[2],value_type(1)) + ); + detail::divide_by_w(result); + return vector3_type(result[0],result[1],result[2]); +} + +} // namespace cml + +#endif