Browse Source

Math: add near/far plane distance queries to Matrix4.

Strange, I thought it could be extracted the same way for both
orthographic and perspective projection...
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
0d31f7461b
  1. 4
      doc/changelog.dox
  2. 111
      src/Magnum/Math/Matrix4.h
  3. 24
      src/Magnum/Math/Test/Matrix4Test.cpp

4
doc/changelog.dox

@ -218,6 +218,10 @@ See also:
match the classic `glOrtho()` and `gluOrtho2D()` APIs, complementing
@ref Math::Matrix4::perspectiveProjection(const Vector2<T>&, const Vector2<T>&, T, T)
that got added in 2019.10
- New @ref Math::Matrix4::orthographicProjectionNear() const,
@ref Math::Matrix4::orthographicProjectionFar() const,
@ref Math::Matrix4::perspectiveProjectionNear() const and
@ref Math::Matrix4::perspectiveProjectionFar() const queries
- Added @ref Math::Intersection::rayRange() (see [mosra/magnum#484](https://github.com/mosra/magnum/pull/484))
- Added @ref Math::RectangularMatrix::RectangularMatrix(IdentityInitT, T)
constructor as it might be useful to create non-square identity matrices as

111
src/Magnum/Math/Matrix4.h

@ -336,7 +336,10 @@ template<class T> class Matrix4: public Matrix4x4<T> {
* If you need an off-center projection (as with the classic
* @m_class{m-doc-external} [glOrtho()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml)
* function), use @ref orthographicProjection(const Vector2<T>&, const Vector2<T>&, T, T).
* @see @ref perspectiveProjection(), @ref Matrix3::projection()
* @see @ref perspectiveProjection(),
* @ref orthographicProjectionNear() const,
* @ref orthographicProjectionFar() const,
* @ref Matrix3::projection()
*/
static Matrix4<T> orthographicProjection(const Vector2<T>& size, T near, T far);
@ -365,6 +368,8 @@ template<class T> class Matrix4: public Matrix4x4<T> {
* @ref orthographicProjection(const Vector2<T>&, T, T).
*
* @see @ref perspectiveProjection(),
* @ref orthographicProjectionNear() const,
* @ref orthographicProjectionFar() const,
* @ref Matrix3::projection(const Vector2<T>&, const Vector2<T>&)
* @m_keywords{glOrtho()}
*/
@ -398,8 +403,10 @@ template<class T> class Matrix4: public Matrix4x4<T> {
* @ref perspectiveProjection(const Vector2<T>&, const Vector2<T>&, T, T)
* instead.
* @see @ref perspectiveProjection(Rad<T>, T, T, T),
* @ref orthographicProjection(), @ref Matrix3::projection(),
* @ref Constants::inf()
* @ref orthographicProjection(),
* @ref perspectiveProjectionNear() const,
* @ref perspectiveProjectionFar() const,
* @ref Matrix3::projection(), @ref Constants::inf()
*/
static Matrix4<T> perspectiveProjection(const Vector2<T>& size, T near, T far);
@ -443,8 +450,10 @@ template<class T> class Matrix4: public Matrix4x4<T> {
* If you need an off-center projection (as with the classic
* @m_class{m-doc-external} [glFrustum()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml)
* function), use @ref perspectiveProjection(const Vector2<T>&, const Vector2<T>&, T, T).
* @see @ref orthographicProjection(), @ref Matrix3::projection(),
* @ref Constants::inf()
* @see @ref orthographicProjection(),
* @ref perspectiveProjectionNear() const,
* @ref perspectiveProjectionFar() const,
* @ref Matrix3::projection(), @ref Constants::inf()
* @m_keywords{gluPerspective()}
*/
static Matrix4<T> perspectiveProjection(Rad<T> fov, T aspectRatio, T near, T far) {
@ -486,6 +495,8 @@ template<class T> class Matrix4: public Matrix4x4<T> {
*
* @see @ref perspectiveProjection(Rad<T> fov, T, T, T),
* @ref orthographicProjection(const Vector2<T>&, const Vector2<T>&, T, T),
* @ref perspectiveProjectionNear() const,
* @ref perspectiveProjectionFar() const,
* @ref Matrix3::projection(), @ref Constants::inf()
* @m_keywords{glFrustum()}
*/
@ -1032,6 +1043,96 @@ template<class T> class Matrix4: public Matrix4x4<T> {
Vector3<T>& translation() { return (*this)[3].xyz(); }
constexpr Vector3<T> translation() const { return (*this)[3].xyz(); } /**< @overload */
/**
* @brief Distance to near plane of an orthographic projection matrix
* @m_since_latest
*
* Assuming a matrix @f$ \boldsymbol{A} @f$ constructed with
* @ref orthographicProjection(), returns the distance to its near
* plane: @f[
* \frac{\boldsymbol{A}_{3,2} + 1}{\boldsymbol{A}_{2,2}} =
* \frac{\frac{n + f}{n - f} + 1}{\frac{2}{n - f}} =
* \frac{\frac{n + f + n - f}{n - f}}{\frac{2}{n - f}} =
* \frac{2n}{2} = n
* @f]
* @see @ref orthographicProjectionFar() const,
* @ref perspectiveProjectionNear() const
*/
Float orthographicProjectionNear() const {
return ((*this)[3][2] + T(1))/(*this)[2][2];
}
/**
* @brief Distance to far plane of an orthographic projection matrix
* @m_since_latest
*
* Assuming a matrix @f$ \boldsymbol{A} @f$ constructed with
* @ref orthographicProjection(), returns the distance to its far
* plane: @f[
* \frac{\boldsymbol{A}_{3,2} - 1}{\boldsymbol{A}_{2,2}} =
* \frac{\frac{n + f}{n - f} - 1}{\frac{2}{n - f}} =
* \frac{\frac{n + f - n + f}{n - f}}{\frac{2}{n - f}} =
* \frac{2f}{2} = f
* @f]
* @see @ref orthographicProjectionNear() const,
* @ref perspectiveProjectionFar() const
*/
Float orthographicProjectionFar() const {
return ((*this)[3][2] - T(1))/(*this)[2][2];
}
/**
* @brief Distance to near plane of a perspective projection matrix
* @m_since_latest
*
* Assuming a matrix @f$ \boldsymbol{A} @f$ constructed with
* @ref perspectiveProjection(), returns the distance to its near
* plane: @f[
* \frac{\boldsymbol{A}_{3,2}}{\boldsymbol{A}_{2,2} - 1} =
* \frac{\frac{2nf}{n - f}}{\frac{n + f}{n - f} - 1} =
* \frac{\frac{2nf}{n - f}}{\frac{n + f - n + f}{n - f}} =
* \frac{2nf}{2f} = n
* @f]
*
* The same equation works for a perspective projection with an
* infinite far plane: @f[
* \frac{\boldsymbol{A}_{3,2}}{\boldsymbol{A}_{2,2} - 1} =
* \frac{-2n}{-1 - 1} =
* \frac{-2n}{-2} = n
* @f]
* @see @ref perspectiveProjectionFar() const,
* @ref orthographicProjectionNear() const
*/
Float perspectiveProjectionNear() const {
return (*this)[3][2]/((*this)[2][2] - T(1));
}
/**
* @brief Distance to far plane of a perspective projection matrix
* @m_since_latest
*
* Assuming a matrix @f$ \boldsymbol{A} @f$ constructed with
* @ref perspectiveProjection() with a positive far value, returns the
* distance to its far plane: @f[
* \left\lvert \frac{\boldsymbol{A}_{3,2}}{\boldsymbol{A}_{2,2} + 1}\right\rvert =
* \left\lvert \frac{\frac{2nf}{n - f}}{\frac{n + f}{n - f} + 1}\right\rvert =
* \left\lvert \frac{\frac{2nf}{n - f}}{\frac{n + f + n - f}{n - f}}\right\rvert =
* \left\lvert \frac{2nf}{2n} \right\rvert = f
* @f]
*
* The same equation works for a perspective projection with an
* infinite far plane: @f[
* \left\lvert \frac{\boldsymbol{A}_{3,2}}{\boldsymbol{A}_{2,2} + 1} \right\rvert =
* \left\lvert \frac{-2n}{-1 + 1} \right\rvert =
* \left\lvert \frac{-2n}{0} \right\rvert = \infty
* @f]
* @see @ref perspectiveProjectionNear() const,
* @ref orthographicProjectionFar() const
*/
Float perspectiveProjectionFar() const {
return std::abs((*this)[3][2]/((*this)[2][2] + T(1)));
}
/**
* @brief Inverted rigid transformation matrix
*

24
src/Magnum/Math/Test/Matrix4Test.cpp

@ -112,6 +112,9 @@ struct Matrix4Test: Corrade::TestSuite::Tester {
void uniformScalingPartNotUniform();
void normalMatrixPart();
void vectorParts();
void orthographicProjectionParts();
void perspectiveProjectionParts();
void perspectiveProjectionInfiniteFarParts();
void invertedRigid();
void invertedRigidNotRigid();
void transform();
@ -183,6 +186,9 @@ Matrix4Test::Matrix4Test() {
&Matrix4Test::uniformScalingPartNotUniform,
&Matrix4Test::normalMatrixPart,
&Matrix4Test::vectorParts,
&Matrix4Test::orthographicProjectionParts,
&Matrix4Test::perspectiveProjectionParts,
&Matrix4Test::perspectiveProjectionInfiniteFarParts,
&Matrix4Test::invertedRigid,
&Matrix4Test::invertedRigidNotRigid,
&Matrix4Test::transform,
@ -1018,6 +1024,24 @@ void Matrix4Test::vectorParts() {
CORRADE_COMPARE(translation, Vector3(-5.0f, 12.0f, 0.5f));
}
void Matrix4Test::orthographicProjectionParts() {
Matrix4 projection = Matrix4::orthographicProjection({5.0f, 4.0f}, 1.0f, 9.0f);
CORRADE_COMPARE(projection.orthographicProjectionNear(), 1.0f);
CORRADE_COMPARE(projection.orthographicProjectionFar(), 9.0f);
}
void Matrix4Test::perspectiveProjectionParts() {
Matrix4 projection = Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, 100.0f);
CORRADE_COMPARE(projection.perspectiveProjectionNear(), 32.0f);
CORRADE_COMPARE(projection.perspectiveProjectionFar(), 100.0f);
}
void Matrix4Test::perspectiveProjectionInfiniteFarParts() {
Matrix4 projection = Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, Constants::inf());
CORRADE_COMPARE(projection.perspectiveProjectionNear(), 32.0f);
CORRADE_COMPARE(projection.perspectiveProjectionFar(), Constants::inf());
}
void Matrix4Test::invertedRigid() {
Matrix4 actual = Matrix4::rotation(-74.0_degf, Vector3(-1.0f, 0.5f, 2.0f).normalized())*
Matrix4::reflection(Vector3(0.5f, -2.0f, 2.0f).normalized())*

Loading…
Cancel
Save