Skip to content

Commit

Permalink
Add Matrix4.[set]perspectiveOffCenterFov()
Browse files Browse the repository at this point in the history
This allows to directly specify the four angles between the frustum
planes and the line perpendicular to the near/far frustum planes.
  • Loading branch information
httpdigest committed Jan 11, 2022
1 parent 6e81e81 commit 21db7f0
Show file tree
Hide file tree
Showing 4 changed files with 509 additions and 7 deletions.
178 changes: 175 additions & 3 deletions src/org/joml/Matrix4d.java
Original file line number Diff line number Diff line change
Expand Up @@ -12110,7 +12110,7 @@ public Matrix4d perspective(double fovy, double aspect, double zNear, double zFa

/**
* Apply a symmetric perspective projection frustum transformation using for a right-handed coordinate system
* the given NDC z range to this matrix.
* using the given NDC z range to this matrix.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>P</code> the perspective projection matrix,
* then the new matrix will be <code>M * P</code>. So when transforming a
Expand Down Expand Up @@ -12293,7 +12293,7 @@ public Matrix4d perspectiveRect(double width, double height, double zNear, doubl

/**
* Apply a symmetric perspective projection frustum transformation using for a right-handed coordinate system
* the given NDC z range to this matrix.
* using the given NDC z range to this matrix.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>P</code> the perspective projection matrix,
* then the new matrix will be <code>M * P</code>. So when transforming a
Expand Down Expand Up @@ -12503,7 +12503,7 @@ public Matrix4d perspectiveOffCenter(double fovy, double offAngleX, double offAn

/**
* Apply an asymmetric off-center perspective projection frustum transformation using for a right-handed coordinate system
* the given NDC z range to this matrix.
* using the given NDC z range to this matrix.
* <p>
* The given angles <code>offAngleX</code> and <code>offAngleY</code> are the horizontal and vertical angles between
* the line of sight and the line given by the center of the near and far frustum planes. So, when <code>offAngleY</code>
Expand Down Expand Up @@ -12586,6 +12586,101 @@ public Matrix4d perspectiveOffCenter(double fovy, double offAngleX, double offAn
return perspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, this);
}

/**
* Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system
* using the given NDC z range to this matrix.
* <p>
* The given angles <code>angleLeft</code> and <code>angleRight</code> are the horizontal angles between
* the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* The angles <code>angleDown</code> and <code>angleUp</code> are the vertical angles between
* the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>P</code> the perspective projection matrix,
* then the new matrix will be <code>M * P</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * P * v</code>,
* the perspective projection will be applied first!
* <p>
* In order to set the matrix to a perspective frustum transformation without post-multiplying,
* use {@link #setPerspectiveOffCenterFov(double, double, double, double, double, double, boolean) setPerspectiveOffCenterFov}.
*
* @see #setPerspectiveOffCenterFov(double, double, double, double, double, double, boolean)
*
* @param angleLeft
* the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleRight
* the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes
* @param angleDown
* the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleUp
* the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes
* @param zNear
* near clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity.
* In that case, <code>zFar</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zFar
* far clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity.
* In that case, <code>zNear</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zZeroToOne
* whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code>
* or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code>
* @return this
*/
public Matrix4d perspectiveOffCenterFov(double angleLeft, double angleRight, double angleDown, double angleUp, double zNear, double zFar, boolean zZeroToOne) {
return perspectiveOffCenterFov(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, zZeroToOne, this);
}
public Matrix4d perspectiveOffCenterFov(double angleLeft, double angleRight, double angleDown, double angleUp, double zNear, double zFar, boolean zZeroToOne, Matrix4d dest) {
return frustum(Math.tan(angleLeft), Math.tan(angleRight), Math.tan(angleDown), Math.tan(angleUp), zNear, zFar, zZeroToOne, dest);
}

/**
* Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system
* using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix.
* <p>
* The given angles <code>angleLeft</code> and <code>angleRight</code> are the horizontal angles between
* the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* The angles <code>angleDown</code> and <code>angleUp</code> are the vertical angles between
* the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>P</code> the perspective projection matrix,
* then the new matrix will be <code>M * P</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * P * v</code>,
* the perspective projection will be applied first!
* <p>
* In order to set the matrix to a perspective frustum transformation without post-multiplying,
* use {@link #setPerspectiveOffCenterFov(double, double, double, double, double, double) setPerspectiveOffCenterFov}.
*
* @see #setPerspectiveOffCenterFov(double, double, double, double, double, double)
*
* @param angleLeft
* the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleRight
* the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes
* @param angleDown
* the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleUp
* the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes
* @param zNear
* near clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity.
* In that case, <code>zFar</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zFar
* far clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity.
* In that case, <code>zNear</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @return this
*/
public Matrix4d perspectiveOffCenterFov(double angleLeft, double angleRight, double angleDown, double angleUp, double zNear, double zFar) {
return perspectiveOffCenterFov(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, this);
}
public Matrix4d perspectiveOffCenterFov(double angleLeft, double angleRight, double angleDown, double angleUp, double zNear, double zFar, Matrix4d dest) {
return frustum(Math.tan(angleLeft), Math.tan(angleRight), Math.tan(angleDown), Math.tan(angleUp), zNear, zFar, dest);
}

/**
* Set this matrix to be a symmetric perspective projection frustum transformation for a right-handed coordinate system
* using the given NDC z range.
Expand Down Expand Up @@ -12855,6 +12950,83 @@ public Matrix4d setPerspectiveOffCenter(double fovy, double offAngleX, double of
return this;
}

/**
* Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed
* coordinate system using OpenGL's NDC z range of <code>[-1..+1]</code>.
* <p>
* The given angles <code>angleLeft</code> and <code>angleRight</code> are the horizontal angles between
* the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* The angles <code>angleDown</code> and <code>angleUp</code> are the vertical angles between
* the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* <p>
* In order to apply the perspective projection transformation to an existing transformation,
* use {@link #perspectiveOffCenterFov(double, double, double, double, double, double) perspectiveOffCenterFov()}.
*
* @see #perspectiveOffCenterFov(double, double, double, double, double, double)
*
* @param fovy
* the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI})
* @param offAngleX
* the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes
* @param offAngleY
* the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes
* @param aspect
* the aspect ratio (i.e. width / height; must be greater than zero)
* @param zNear
* near clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity.
* In that case, <code>zFar</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zFar
* far clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity.
* In that case, <code>zNear</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @return this
*/
public Matrix4d setPerspectiveOffCenterFov(double fovy, double offAngleX, double offAngleY,
double aspect, double zNear, double zFar) {
return setPerspectiveOffCenterFov(fovy, offAngleX, offAngleY, aspect, zNear, zFar, false);
}
/**
* Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system
* using the given NDC z range.
* <p>
* The given angles <code>angleLeft</code> and <code>angleRight</code> are the horizontal angles between
* the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* The angles <code>angleDown</code> and <code>angleUp</code> are the vertical angles between
* the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes.
* <p>
* In order to apply the perspective projection transformation to an existing transformation,
* use {@link #perspectiveOffCenterFov(double, double, double, double, double, double, boolean) perspectiveOffCenterFov()}.
*
* @see #perspectiveOffCenterFov(double, double, double, double, double, double, boolean)
*
* @param angleLeft
* the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleRight
* the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes
* @param angleDown
* the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes.
* For a symmetric frustum, this value is negative.
* @param angleUp
* the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes
* @param zNear
* near clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity.
* In that case, <code>zFar</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zFar
* far clipping plane distance. This value must be greater than zero.
* If the special value {@link Double#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity.
* In that case, <code>zNear</code> may not also be {@link Double#POSITIVE_INFINITY}.
* @param zZeroToOne
* whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code>
* or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code>
* @return this
*/
public Matrix4d setPerspectiveOffCenterFov(double angleLeft, double angleRight, double angleDown, double angleUp, double zNear, double zFar, boolean zZeroToOne) {
return setFrustum(Math.tan(angleLeft), Math.tan(angleRight), Math.tan(angleDown), Math.tan(angleUp), zNear, zFar, zZeroToOne);
}

/**
* Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system
* using the given NDC z range to this matrix and store the result in <code>dest</code>.
Expand Down
Loading

0 comments on commit 21db7f0

Please sign in to comment.