forked from Mirrorlandia_minetest/irrlicht
Add lens shift support for the camera and the perspective projection functions
As Blender docs describe it so nicely: Using lens shift is equivalent to rendering an image with a larger FOV and cropping it off-center. This can be quite useful for architecture renderings, but I guess also has it's use in other situations. Note: Didn't make the ICameraSceneNode functions pure virtual so users don't have to update their cameras for this Also some change in serialization - same as in other places by now, do use existing values as defaults values when they are not found instead of resetting them to 0. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6565 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
parent
567f8688e2
commit
d4f6d8c17b
@ -1,6 +1,7 @@
|
||||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
|
||||
- Add lens shift support for the camera and the perspective projection functions
|
||||
- TGA loader no longer reduces 24&32 bit TGA's with palettes to 16 bit. Thanks @erlehmann for report: https://irrlicht.sourceforge.io/forum/viewtopic.php?t=52925
|
||||
- Fix compile error with OS X 10.10 SDK, bug #463. Thanks @Ryan Schmidt for report and patch.
|
||||
- Optimize quaternion::rotationFromTo. Thanks @Robert Eisele for patch and proof (https://raw.org/proof/quaternion-from-two-vectors)
|
||||
|
@ -120,6 +120,13 @@ namespace scene
|
||||
/** \return The field of view of the camera in radians. */
|
||||
virtual f32 getFOV() const =0;
|
||||
|
||||
//! Get the horizontal and vertical lens/projection plane shift
|
||||
/** \return Project plane offset */
|
||||
virtual core::vector2df getLensShift() const
|
||||
{
|
||||
return core::vector2df(0.f, 0.f);
|
||||
}
|
||||
|
||||
//! Sets the value of the near clipping plane. (default: 1.0f)
|
||||
/** Also changes projection matrix and resets IsOrthogonal flag.
|
||||
\param zn: New z near value. */
|
||||
@ -140,6 +147,16 @@ namespace scene
|
||||
\param fovy: New field of view in radians. */
|
||||
virtual void setFOV(f32 fovy) =0;
|
||||
|
||||
//! Set the horizontal and vertical lens/projection plane shift
|
||||
/** Like rendering a larger field of view and then cropping
|
||||
it off-center. Allows for things like 2-point perspective.
|
||||
\param shift: Offset by which the projection plane is moved.
|
||||
If you move by 1 or -1 it will move the center by half a screen.
|
||||
Positive X go to the left and positive Y go down.
|
||||
By default it will be 0,0 */
|
||||
virtual void setLensShift(const core::vector2df& shift)
|
||||
{}
|
||||
|
||||
//! Get the view frustum.
|
||||
/** \return The current view frustum. */
|
||||
virtual const SViewFrustum* getViewFrustum() const =0;
|
||||
|
@ -311,26 +311,28 @@ namespace core
|
||||
\param zNear: Distance to near plane
|
||||
\param zFar: Distance to far plane
|
||||
param zClipFromZero: Clipping of z can be projected from 0 to w when true (D3D style) and from -w to w when false (OGL style)
|
||||
\param zSign: 1 for left-handed projection matrix, -1 for right-handed projection matrix */
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFov(T sx, T sy, T zNear, T zFar, bool zClipFromZero, T zSign);
|
||||
\param zSign: 1 for left-handed projection matrix, -1 for right-handed projection matrix
|
||||
\param shiftX: Shift projection plane of camera left/right
|
||||
\param shiftY: Shift projection plane of camera up/down */
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFov(T sx, T sy, T zNear, T zFar, bool zClipFromZero, T zSign, T shiftX, T shiftY);
|
||||
|
||||
//! Builds a right-handed perspective projection matrix based on a field of view
|
||||
//\param zClipFromZero: Clipping of z can be projected from 0 to w when true (D3D style) and from -w to w when false (OGL style).
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadiansY, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true);
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadiansY, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true, f32 shiftX=0.f, f32 shiftY=0.f);
|
||||
|
||||
//! Builds a left-handed perspective projection matrix based on a field of view
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadiansY, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true);
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadiansY, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true, f32 shiftX=0.f, f32 shiftY=0.f);
|
||||
|
||||
//! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadiansY, f32 aspectRatio, f32 zNear, f32 epsilon=0);
|
||||
|
||||
//! Builds a right-handed perspective projection matrix.
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true);
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true, f32 shiftX=0.f, f32 shiftY=0.f);
|
||||
|
||||
//! Builds a left-handed perspective projection matrix.
|
||||
//\param widthOfViewVolume: width of clipped near frustum plane
|
||||
//\param heightOfViewVolume: height of clipped near frustum plane
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true);
|
||||
CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true, f32 shiftX=0.f, f32 shiftY=0.f);
|
||||
|
||||
//! Builds a left-handed orthogonal projection matrix.
|
||||
//\param zClipFromZero: Clipping of z can be projected from 0 to 1 when true (D3D style) and from -1 to 1 when false (OGL style).
|
||||
@ -1583,7 +1585,7 @@ namespace core
|
||||
|
||||
// Builds a perspective projection matrix
|
||||
template <class T>
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFov(T sx, T sy, T zNear, T zFar, bool zClipFromZero, T zSign)
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFov(T sx, T sy, T zNear, T zFar, bool zClipFromZero, T zSign, T shiftX, T shiftY)
|
||||
{
|
||||
IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
|
||||
M[0] = sx;
|
||||
@ -1596,8 +1598,8 @@ namespace core
|
||||
M[6] = 0;
|
||||
M[7] = 0;
|
||||
|
||||
M[8] = 0;
|
||||
M[9] = 0;
|
||||
M[8] = shiftX;
|
||||
M[9] = shiftY;
|
||||
//M[10] below
|
||||
M[11] = zSign;
|
||||
|
||||
@ -1626,23 +1628,23 @@ namespace core
|
||||
// Builds a right-handed perspective projection matrix based on a field of view
|
||||
template <class T>
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
|
||||
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero)
|
||||
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero, f32 shiftX, f32 shiftY)
|
||||
{
|
||||
const f64 sy = reciprocal(tan(fieldOfViewRadians*0.5));
|
||||
IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
|
||||
const T sx = static_cast<T>(sy / aspectRatio);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, static_cast<T>(sy), zNear, zFar, zClipFromZero, (T)-1);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, static_cast<T>(sy), zNear, zFar, zClipFromZero, (T)-1, shiftX, shiftY);
|
||||
}
|
||||
|
||||
// Builds a left-handed perspective projection matrix based on a field of view
|
||||
template <class T>
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
|
||||
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero)
|
||||
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero, f32 shiftX, f32 shiftY)
|
||||
{
|
||||
const f64 sy = reciprocal(tan(fieldOfViewRadians*0.5));
|
||||
IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
|
||||
const T sx = static_cast<T>(sy / aspectRatio);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, static_cast<T>(sy), zNear, zFar, zClipFromZero, (T)1);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, static_cast<T>(sy), zNear, zFar, zClipFromZero, (T)1, shiftX, shiftY);
|
||||
}
|
||||
|
||||
// Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
|
||||
@ -1775,26 +1777,26 @@ namespace core
|
||||
// Builds a right-handed perspective projection matrix.
|
||||
template <class T>
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
|
||||
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero)
|
||||
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero, f32 shiftX, f32 shiftY)
|
||||
{
|
||||
IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
|
||||
IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
|
||||
const T sx = (T)(2*zNear/widthOfViewVolume);
|
||||
const T sy = (T)(2*zNear/heightOfViewVolume);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, sy, zNear, zFar, zClipFromZero, (T)-1);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, sy, zNear, zFar, zClipFromZero, (T)-1, shiftX, shiftY);
|
||||
}
|
||||
|
||||
// Builds a left-handed perspective projection matrix.
|
||||
template <class T>
|
||||
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
|
||||
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero)
|
||||
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero, f32 shiftX, f32 shiftY)
|
||||
{
|
||||
IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
|
||||
IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
|
||||
const T sx = (T)(2*zNear/widthOfViewVolume);
|
||||
const T sy = (T)(2*zNear/heightOfViewVolume);
|
||||
|
||||
return buildProjectionMatrixPerspectiveFov(sx, sy, zNear, zFar, zClipFromZero, (T)1);
|
||||
return buildProjectionMatrixPerspectiveFov(sx, sy, zNear, zFar, zClipFromZero, (T)1, shiftX, shiftY);
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,6 +201,11 @@ f32 CCameraSceneNode::getFOV() const
|
||||
return Fovy;
|
||||
}
|
||||
|
||||
core::vector2df CCameraSceneNode::getLensShift() const
|
||||
{
|
||||
return LensShift;
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setNearValue(f32 f)
|
||||
{
|
||||
@ -231,10 +236,15 @@ void CCameraSceneNode::setFOV(f32 f)
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
void CCameraSceneNode::setLensShift(const core::vector2df& shift)
|
||||
{
|
||||
LensShift = shift;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
void CCameraSceneNode::recalculateProjectionMatrix()
|
||||
{
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar, HasD3DStyleProjectionMatrix);
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar, HasD3DStyleProjectionMatrix, LensShift.X, LensShift.Y);
|
||||
IsOrthogonal = false;
|
||||
}
|
||||
|
||||
@ -330,6 +340,7 @@ void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR
|
||||
out->addFloat("Aspect", Aspect);
|
||||
out->addFloat("ZNear", ZNear);
|
||||
out->addFloat("ZFar", ZFar);
|
||||
out->addVector2d("LensShift", LensShift);
|
||||
out->addBool("Binding", TargetAndRotationAreBound);
|
||||
out->addBool("ReceiveInput", InputReceiverEnabled);
|
||||
}
|
||||
@ -339,15 +350,15 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute
|
||||
{
|
||||
ICameraSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Target = in->getAttributeAsVector3d("Target");
|
||||
UpVector = in->getAttributeAsVector3d("UpVector");
|
||||
Fovy = in->getAttributeAsFloat("Fovy");
|
||||
Aspect = in->getAttributeAsFloat("Aspect");
|
||||
ZNear = in->getAttributeAsFloat("ZNear");
|
||||
ZFar = in->getAttributeAsFloat("ZFar");
|
||||
TargetAndRotationAreBound = in->getAttributeAsBool("Binding");
|
||||
if ( in->findAttribute("ReceiveInput") )
|
||||
InputReceiverEnabled = in->getAttributeAsBool("ReceiveInput");
|
||||
Target = in->getAttributeAsVector3d("Target", Target);
|
||||
UpVector = in->getAttributeAsVector3d("UpVector", UpVector);
|
||||
Fovy = in->getAttributeAsFloat("Fovy", Fovy);
|
||||
Aspect = in->getAttributeAsFloat("Aspect", Aspect);
|
||||
ZNear = in->getAttributeAsFloat("ZNear", ZNear);
|
||||
ZFar = in->getAttributeAsFloat("ZFar", ZFar);
|
||||
LensShift = in->getAttributeAsVector2d("LensShift", LensShift);
|
||||
TargetAndRotationAreBound = in->getAttributeAsBool("Binding", TargetAndRotationAreBound);
|
||||
InputReceiverEnabled = in->getAttributeAsBool("ReceiveInput", InputReceiverEnabled);
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
|
@ -95,6 +95,9 @@ namespace scene
|
||||
//! \return Field of view of the camera
|
||||
virtual f32 getFOV() const IRR_OVERRIDE;
|
||||
|
||||
//! Get the horizontal and vertical lens/projection plane shift
|
||||
virtual core::vector2df getLensShift() const IRR_OVERRIDE;
|
||||
|
||||
//! Sets the value of the near clipping plane. (default: 1.0f)
|
||||
virtual void setNearValue(f32 zn) IRR_OVERRIDE;
|
||||
|
||||
@ -107,6 +110,9 @@ namespace scene
|
||||
//! Sets the field of view (Default: PI / 3.5f)
|
||||
virtual void setFOV(f32 fovy) IRR_OVERRIDE;
|
||||
|
||||
//! Set the horizontal and vertical lens/projection plane shift
|
||||
virtual void setLensShift(const core::vector2df& shift) IRR_OVERRIDE;
|
||||
|
||||
//! PreRender event
|
||||
virtual void OnRegisterSceneNode() IRR_OVERRIDE;
|
||||
|
||||
@ -162,6 +168,7 @@ namespace scene
|
||||
f32 Aspect; // Aspect ratio.
|
||||
f32 ZNear; // value of the near view-plane.
|
||||
f32 ZFar; // Z-value of the far view-plane.
|
||||
core::vector2df LensShift; // For rendering off-center
|
||||
|
||||
SViewFrustum ViewArea;
|
||||
core::matrix4 Affector;
|
||||
|
Loading…
Reference in New Issue
Block a user