// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#include <gp_Pln.hxx>
-#include <Standard_ShortReal.hxx>
-
#include <Graphic3d_Camera.hxx>
+
+#include <gp_Pln.hxx>
+#include <gp_QuaternionNLerp.hxx>
+#include <gp_QuaternionSLerp.hxx>
#include <Graphic3d_Vec4.hxx>
#include <Graphic3d_WorldViewProjState.hxx>
-
+#include <NCollection_Sequence.hxx>
+#include <Standard_ShortReal.hxx>
#include <Standard_Atomic.hxx>
#include <Standard_Assert.hxx>
-#include <NCollection_Sequence.hxx>
-
-
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Camera,Standard_Transient)
namespace
// atomic state counter
static volatile Standard_Integer THE_STATE_COUNTER = 0;
- // minimum camera distance
- static const Standard_Real MIN_DISTANCE = Pow (0.1, ShortRealDigits() - 2);
-
// z-range tolerance compatible with for floating point.
static Standard_Real zEpsilon()
{
Standard_Real aLogRadix = Log10 (anAbsValue) / Log10 (FLT_RADIX);
Standard_Real aExp = Floor (aLogRadix);
return FLT_EPSILON * Pow (FLT_RADIX, aExp);
- };
-};
+ }
+
+ //! Convert camera definition to Ax3
+ gp_Ax3 cameraToAx3 (const Graphic3d_Camera& theCamera)
+ {
+ const gp_Dir aBackDir = -theCamera.Direction();
+ const gp_Dir anXAxis (theCamera.Up().Crossed (aBackDir));
+ const gp_Dir anYAxis (aBackDir .Crossed (anXAxis));
+ const gp_Dir aZAxis (anXAxis .Crossed (anYAxis));
+ return gp_Ax3 (gp_Pnt (0.0, 0.0, 0.0), aZAxis, anXAxis);
+ }
+}
// =======================================================================
// function : Graphic3d_Camera
// =======================================================================
Graphic3d_Camera::Graphic3d_Camera()
: myUp (0.0, 1.0, 0.0),
+ myDirection (0.0, 0.0, 1.0),
myEye (0.0, 0.0, -1500.0),
- myCenter (0.0, 0.0, 0.0),
+ myDistance (1500.0),
myAxialScale (1.0, 1.0, 1.0),
myProjType (Projection_Orthographic),
myFOVy (45.0),
+ myFOVyTan (Tan (DTR_HALF * 45.0)),
myZNear (DEFAULT_ZNEAR),
myZFar (DEFAULT_ZFAR),
myAspect (1.0),
// purpose :
// =======================================================================
Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
+: myUp (0.0, 1.0, 0.0),
+ myDirection (0.0, 0.0, 1.0),
+ myEye (0.0, 0.0, -1500.0),
+ myDistance (1500.0),
+ myAxialScale (1.0, 1.0, 1.0),
+ myProjType (Projection_Orthographic),
+ myFOVy (45.0),
+ myFOVyTan (Tan (DTR_HALF * 45.0)),
+ myZNear (DEFAULT_ZNEAR),
+ myZFar (DEFAULT_ZFAR),
+ myAspect (1.0),
+ myScale (1000.0),
+ myZFocus (1.0),
+ myZFocusType (FocusType_Relative),
+ myIOD (0.05),
+ myIODType (IODType_Relative)
{
myWorldViewProjState.Initialize (this);
SetZFocus (theOtherCamera->ZFocusType(), theOtherCamera->ZFocus());
SetIOD (theOtherCamera->GetIODType(), theOtherCamera->IOD());
SetProjectionType (theOtherCamera->ProjectionType());
+ SetTile (theOtherCamera->myTile);
}
// =======================================================================
// =======================================================================
void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
{
- SetUp (theOtherCamera->Up());
- SetEye (theOtherCamera->Eye());
- SetCenter (theOtherCamera->Center());
+ if (!myEye.IsEqual (theOtherCamera->Eye(), 0.0)
+ || !myUp.IsEqual (theOtherCamera->Up(), 0.0)
+ || !myDirection.IsEqual (theOtherCamera->Direction(), 0.0)
+ || myDistance != theOtherCamera->Distance())
+ {
+ myEye = theOtherCamera->Eye();
+ myUp = theOtherCamera->Up();
+ myDirection = theOtherCamera->Direction();
+ myDistance = theOtherCamera->Distance();
+ InvalidateOrientation();
+ }
SetAxialScale (theOtherCamera->AxialScale());
}
CopyOrientationData (theOther);
}
+// =======================================================================
+// function : MoveEyeTo
+// purpose :
+// =======================================================================
+void Graphic3d_Camera::MoveEyeTo (const gp_Pnt& theEye)
+{
+ if (myEye.IsEqual (theEye, 0.0))
+ {
+ return;
+ }
+
+ myEye = theEye;
+ InvalidateOrientation();
+}
+
+// =======================================================================
+// function : SetEyeAndCenter
+// purpose :
+// =======================================================================
+void Graphic3d_Camera::SetEyeAndCenter (const gp_Pnt& theEye,
+ const gp_Pnt& theCenter)
+{
+ if (Eye() .IsEqual (theEye, 0.0)
+ && Center().IsEqual (theCenter, 0.0))
+ {
+ return;
+ }
+
+ myEye = theEye;
+ myDistance = theEye.Distance (theCenter);
+ if (myDistance > gp::Resolution())
+ {
+ myDirection = gp_Dir (theCenter.XYZ() - theEye.XYZ());
+ }
+ InvalidateOrientation();
+}
+
// =======================================================================
// function : SetEye
// purpose :
return;
}
+ const gp_Pnt aCenter = Center();
myEye = theEye;
+ myDistance = myEye.Distance (aCenter);
+ if (myDistance > gp::Resolution())
+ {
+ myDirection = gp_Dir (aCenter.XYZ() - myEye.XYZ());
+ }
InvalidateOrientation();
}
// =======================================================================
void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
{
- if (Center().IsEqual (theCenter, 0.0))
+ const Standard_Real aDistance = myEye.Distance (theCenter);
+ if (myDistance == aDistance)
{
return;
}
- myCenter = theCenter;
+ myDistance = aDistance;
+ if (myDistance > gp::Resolution())
+ {
+ myDirection = gp_Dir (theCenter.XYZ() - myEye.XYZ());
+ }
InvalidateOrientation();
}
// =======================================================================
void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
{
- if (Distance() == theDistance)
+ if (myDistance == theDistance)
{
return;
}
- gp_Vec aCenter2Eye (Direction());
- aCenter2Eye.Reverse();
-
- // Camera should have non-zero distance.
- aCenter2Eye.Scale (Max (theDistance, MIN_DISTANCE));
- SetEye (Center().Translated (aCenter2Eye));
+ const gp_Pnt aCenter = Center();
+ myDistance = theDistance;
+ myEye = aCenter.XYZ() - myDirection.XYZ() * myDistance;
+ InvalidateOrientation();
}
// =======================================================================
-// function : Distance
+// function : SetDirectionFromEye
// purpose :
// =======================================================================
-Standard_Real Graphic3d_Camera::Distance() const
+void Graphic3d_Camera::SetDirectionFromEye (const gp_Dir& theDir)
{
- return myEye.Distance (myCenter);
+ if (myDirection.IsEqual (theDir, 0.0))
+ {
+ return;
+ }
+
+ myDirection = theDir;
+ InvalidateOrientation();
}
// =======================================================================
// =======================================================================
void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
{
- if (Direction().IsEqual (theDir, 0.0))
+ if (myDirection.IsEqual (theDir, 0.0))
{
return;
}
- gp_Vec aScaledDir (theDir);
- aScaledDir.Scale (Distance());
- aScaledDir.Reverse();
- SetEye (Center().Translated (aScaledDir));
-}
-
-// =======================================================================
-// function : Direction
-// purpose :
-// =======================================================================
-gp_Dir Graphic3d_Camera::Direction() const
-{
- return gp_Dir (gp_Vec (myEye, myCenter));
+ const gp_Pnt aCenter = Center();
+ myDirection = theDir;
+ myEye = aCenter.XYZ() - theDir.XYZ() * myDistance;
+ InvalidateOrientation();
}
// =======================================================================
case Projection_MonoLeftEye :
case Projection_MonoRightEye :
{
- Standard_Real aDistance = theScale * 0.5 / Tan(myFOVy * M_PI / 360.0);
+ Standard_Real aDistance = theScale * 0.5 / myFOVyTan;
SetDistance (aDistance);
}
// case Projection_MonoLeftEye :
// case Projection_MonoRightEye :
default :
- return Distance() * 2.0 * Tan (myFOVy * M_PI / 360.0);
+ return Distance() * 2.0 * myFOVyTan;
}
}
}
myFOVy = theFOVy;
+ myFOVyTan = Tan(DTR_HALF * myFOVy);
InvalidateProjection();
}
InvalidateProjection();
}
+// =======================================================================
+// function : SetTile
+// purpose :
+// =======================================================================
+void Graphic3d_Camera::SetTile (const Graphic3d_CameraTile& theTile)
+{
+ if (myTile == theTile)
+ {
+ return;
+ }
+
+ myTile = theTile;
+ InvalidateProjection();
+}
+
// =======================================================================
// function : OrthogonalizeUp
// purpose :
return;
}
- SetUp (myUp.Transformed (theTrsf));
- SetEye (myEye.Transformed (theTrsf));
- SetCenter (myCenter.Transformed (theTrsf));
+ myUp .Transform (theTrsf);
+ myDirection.Transform (theTrsf);
+ myEye.Transform (theTrsf);
+ InvalidateOrientation();
}
// =======================================================================
// function : ViewDimensions
// purpose :
// =======================================================================
-gp_XYZ Graphic3d_Camera::ViewDimensions() const
+gp_XYZ Graphic3d_Camera::ViewDimensions (const Standard_Real theZValue) const
{
// view plane dimensions
- Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
+ Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * theZValue * myFOVyTan);
Standard_Real aSizeX, aSizeY;
if (myAspect > 1.0)
{
theNear = gp_Pln (Eye().Translated (aProjection * ZNear()), aProjection);
theFar = gp_Pln (Eye().Translated (aProjection * ZFar()), -aProjection);
- Standard_Real aHScaleHor = Scale() * 0.5 * Aspect();
- Standard_Real aHScaleVer = Scale() * 0.5;
+ Standard_Real aHScaleHor = 0.0, aHScaleVer = 0.0;
+ if (Aspect() >= 1.0)
+ {
+ aHScaleHor = Scale() * 0.5 * Aspect();
+ aHScaleVer = Scale() * 0.5;
+ }
+ else
+ {
+ aHScaleHor = Scale() * 0.5;
+ aHScaleVer = Scale() * 0.5 / Aspect();
+ }
gp_Pnt aPntLeft = Center().Translated (aHScaleHor * -aSide);
gp_Pnt aPntRight = Center().Translated (aHScaleHor * aSide);
// =======================================================================
const Graphic3d_Mat4d& Graphic3d_Camera::OrientationMatrix() const
{
- return *UpdateOrientation (myMatricesD).Orientation;
+ return UpdateOrientation (myMatricesD).Orientation;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4& Graphic3d_Camera::OrientationMatrixF() const
{
- return *UpdateOrientation (myMatricesF).Orientation;
+ return UpdateOrientation (myMatricesF).Orientation;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionMatrix() const
{
- return *UpdateProjection (myMatricesD).MProjection;
+ return UpdateProjection (myMatricesD).MProjection;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4& Graphic3d_Camera::ProjectionMatrixF() const
{
- return *UpdateProjection (myMatricesF).MProjection;
+ return UpdateProjection (myMatricesF).MProjection;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoLeft() const
{
- return *UpdateProjection (myMatricesD).LProjection;
+ return UpdateProjection (myMatricesD).LProjection;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoLeftF() const
{
- return *UpdateProjection (myMatricesF).LProjection;
+ return UpdateProjection (myMatricesF).LProjection;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoRight() const
{
- return *UpdateProjection (myMatricesD).RProjection;
+ return UpdateProjection (myMatricesD).RProjection;
}
// =======================================================================
// =======================================================================
const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoRightF() const
{
- return *UpdateProjection (myMatricesF).RProjection;
+ return UpdateProjection (myMatricesF).RProjection;
}
// =======================================================================
}
else
{
- aDXHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
- aDYHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
+ aDXHalf = aZNear * Elem_t (myFOVyTan);
+ aDYHalf = aZNear * Elem_t (myFOVyTan);
}
if (anAspect > 1.0)
? static_cast<Elem_t> (myZFocus * Distance())
: static_cast<Elem_t> (myZFocus);
+ if (myTile.IsValid())
+ {
+ const Elem_t aDXFull = Elem_t(2) * aDXHalf;
+ const Elem_t aDYFull = Elem_t(2) * aDYHalf;
+ const Graphic3d_Vec2i anOffset = myTile.OffsetLowerLeft();
+ aLeft = -aDXHalf + aDXFull * static_cast<Elem_t> (anOffset.x()) / static_cast<Elem_t> (myTile.TotalSize.x());
+ aRight = -aDXHalf + aDXFull * static_cast<Elem_t> (anOffset.x() + myTile.TileSize.x()) / static_cast<Elem_t> (myTile.TotalSize.x());
+ aBot = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y()) / static_cast<Elem_t> (myTile.TotalSize.y());
+ aTop = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y() + myTile.TileSize.y()) / static_cast<Elem_t> (myTile.TotalSize.y());
+ }
+
switch (myProjType)
{
case Projection_Orthographic :
- OrthoProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
+ OrthoProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, theMatrices.MProjection);
break;
case Projection_Perspective :
- PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
+ PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, theMatrices.MProjection);
break;
case Projection_MonoLeftEye :
{
StereoEyeProj (aLeft, aRight, aBot, aTop,
aZNear, aZFar, aIOD, aFocus,
- Standard_True, *theMatrices.MProjection);
- *theMatrices.LProjection = *theMatrices.MProjection;
+ Standard_True, theMatrices.MProjection);
+ theMatrices.LProjection = theMatrices.MProjection;
break;
}
{
StereoEyeProj (aLeft, aRight, aBot, aTop,
aZNear, aZFar, aIOD, aFocus,
- Standard_False, *theMatrices.MProjection);
- *theMatrices.RProjection = *theMatrices.MProjection;
+ Standard_False, theMatrices.MProjection);
+ theMatrices.RProjection = theMatrices.MProjection;
break;
}
case Projection_Stereo :
{
- PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
+ PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, theMatrices.MProjection);
StereoEyeProj (aLeft, aRight, aBot, aTop,
aZNear, aZFar, aIOD, aFocus,
Standard_True,
- *theMatrices.LProjection);
+ theMatrices.LProjection);
StereoEyeProj (aLeft, aRight, aBot, aTop,
aZNear, aZFar, aIOD, aFocus,
Standard_False,
- *theMatrices.RProjection);
+ theMatrices.RProjection);
break;
}
}
static_cast<Elem_t> (myEye.Y()),
static_cast<Elem_t> (myEye.Z()));
- NCollection_Vec3<Elem_t> aCenter (static_cast<Elem_t> (myCenter.X()),
- static_cast<Elem_t> (myCenter.Y()),
- static_cast<Elem_t> (myCenter.Z()));
+ NCollection_Vec3<Elem_t> aViewDir (static_cast<Elem_t> (myDirection.X()),
+ static_cast<Elem_t> (myDirection.Y()),
+ static_cast<Elem_t> (myDirection.Z()));
NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
static_cast<Elem_t> (myUp.Y()),
static_cast<Elem_t> (myAxialScale.Y()),
static_cast<Elem_t> (myAxialScale.Z()));
- LookOrientation (anEye, aCenter, anUp, anAxialScale, *theMatrices.Orientation);
+ LookOrientation (anEye, aViewDir, anUp, anAxialScale, theMatrices.Orientation);
return theMatrices; // for inline accessors
}
// =======================================================================
template <typename Elem_t>
void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
- const NCollection_Vec3<Elem_t>& theLookAt,
+ const NCollection_Vec3<Elem_t>& theFwdDir,
const NCollection_Vec3<Elem_t>& theUpDir,
const NCollection_Vec3<Elem_t>& theAxialScale,
NCollection_Mat4<Elem_t>& theOutMx)
{
- NCollection_Vec3<Elem_t> aForward = theLookAt - theEye;
+ NCollection_Vec3<Elem_t> aForward = theFwdDir;
aForward.Normalize();
// side = forward x up
Standard_Real aDistance = aCamPln.Distance (aMeasurePnt);
// Check if the camera is intruded into the scene.
- if (aCamDir.IsOpposite (gp_Vec (aCamEye, aMeasurePnt), M_PI * 0.5))
+ gp_Vec aVecToMeasurePnt (aCamEye, aMeasurePnt);
+ if (aVecToMeasurePnt.Magnitude() > gp::Resolution()
+ && aCamDir.IsOpposite (aVecToMeasurePnt, M_PI * 0.5))
{
aDistance *= -1;
}
{
// Clip zNear according to the minimum value matching the quality.
aZNear = aZNearMin;
+ if (aZFar < aZNear)
+ {
+ aZFar = aZNear;
+ }
}
else
{
{
aZNear = zEpsilon();
}
+ Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
}
theZNear = aZNear;
theZFar = aZFar;
+ Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
return true;
}
+
+//=============================================================================
+//function : Interpolate
+//purpose :
+//=============================================================================
+template<>
+Standard_EXPORT void NCollection_Lerp<Handle(Graphic3d_Camera)>::Interpolate (const double theT,
+ Handle(Graphic3d_Camera)& theCamera) const
+{
+ if (Abs (theT - 1.0) < Precision::Confusion())
+ {
+ // just copy end-point transformation
+ theCamera->Copy (myEnd);
+ return;
+ }
+
+ theCamera->Copy (myStart);
+ if (Abs (theT - 0.0) < Precision::Confusion())
+ {
+ return;
+ }
+
+ // apply rotation
+ {
+ gp_Ax3 aCamStart = cameraToAx3 (*myStart);
+ gp_Ax3 aCamEnd = cameraToAx3 (*myEnd);
+ gp_Trsf aTrsfStart, aTrsfEnd;
+ aTrsfStart.SetTransformation (aCamStart, gp::XOY());
+ aTrsfEnd .SetTransformation (aCamEnd, gp::XOY());
+
+ gp_Quaternion aRotStart = aTrsfStart.GetRotation();
+ gp_Quaternion aRotEnd = aTrsfEnd .GetRotation();
+ gp_Quaternion aRotDelta = aRotEnd * aRotStart.Inverted();
+ gp_Quaternion aRot = gp_QuaternionNLerp::Interpolate (gp_Quaternion(), aRotDelta, theT);
+ gp_Trsf aTrsfRot;
+ aTrsfRot.SetRotation (aRot);
+ theCamera->Transform (aTrsfRot);
+ }
+
+ // apply translation
+ {
+ gp_XYZ aCenter = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Center().XYZ(), myEnd->Center().XYZ(), theT);
+ gp_XYZ anEye = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Eye().XYZ(), myEnd->Eye().XYZ(), theT);
+ gp_XYZ anAnchor = aCenter;
+ Standard_Real aKc = 0.0;
+
+ const Standard_Real aDeltaCenter = myStart->Center().Distance (myEnd->Center());
+ const Standard_Real aDeltaEye = myStart->Eye() .Distance (myEnd->Eye());
+ if (aDeltaEye <= gp::Resolution())
+ {
+ anAnchor = anEye;
+ aKc = 1.0;
+ }
+ else if (aDeltaCenter > gp::Resolution())
+ {
+ aKc = aDeltaCenter / (aDeltaCenter + aDeltaEye);
+
+ const gp_XYZ anAnchorStart = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Center().XYZ(), myStart->Eye().XYZ(), aKc);
+ const gp_XYZ anAnchorEnd = NCollection_Lerp<gp_XYZ>::Interpolate (myEnd ->Center().XYZ(), myEnd ->Eye().XYZ(), aKc);
+ anAnchor = NCollection_Lerp<gp_XYZ>::Interpolate (anAnchorStart, anAnchorEnd, theT);
+ }
+
+ const gp_Vec aDirEyeToCenter = theCamera->Direction();
+ const Standard_Real aDistEyeCenterStart = myStart->Eye().Distance (myStart->Center());
+ const Standard_Real aDistEyeCenterEnd = myEnd ->Eye().Distance (myEnd ->Center());
+ const Standard_Real aDistEyeCenter = NCollection_Lerp<Standard_Real>::Interpolate (aDistEyeCenterStart, aDistEyeCenterEnd, theT);
+ aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc;
+ anEye = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc);
+
+ theCamera->SetEyeAndCenter (anEye, aCenter);
+ }
+
+ // apply scaling
+ if (Abs(myStart->Scale() - myEnd->Scale()) > Precision::Confusion()
+ && myStart->IsOrthographic())
+ {
+ const Standard_Real aScale = NCollection_Lerp<Standard_Real>::Interpolate (myStart->Scale(), myEnd->Scale(), theT);
+ theCamera->SetScale (aScale);
+ }
+}
+
+//=======================================================================
+//function : FrustumPoints
+//purpose :
+//=======================================================================
+void Graphic3d_Camera::FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePoints,
+ const Graphic3d_Mat4d& theModelWorld) const
+{
+ if (thePoints.Length() != FrustumVerticesNB)
+ {
+ thePoints.Resize (0, FrustumVerticesNB, Standard_False);
+ }
+
+ const Graphic3d_Mat4d& aProjectionMat = ProjectionMatrix();
+ const Graphic3d_Mat4d aWorldViewMat = OrientationMatrix() * theModelWorld;
+
+ Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0;
+ Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0;
+ Standard_Real aNear = 0.0, aFar = 0.0;
+ if (!IsOrthographic())
+ {
+ // handle perspective projection
+ aNear = aProjectionMat.GetValue (2, 3) / (-1.0 + aProjectionMat.GetValue (2, 2));
+ aFar = aProjectionMat.GetValue (2, 3) / ( 1.0 + aProjectionMat.GetValue (2, 2));
+ // Near plane
+ nLeft = aNear * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0);
+ nRight = aNear * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0);
+ nTop = aNear * (aProjectionMat.GetValue (1, 2) + 1.0) / aProjectionMat.GetValue (1, 1);
+ nBottom = aNear * (aProjectionMat.GetValue (1, 2) - 1.0) / aProjectionMat.GetValue (1, 1);
+ // Far plane
+ fLeft = aFar * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0);
+ fRight = aFar * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0);
+ fTop = aFar * (aProjectionMat.GetValue (1, 2) + 1.0) / aProjectionMat.GetValue (1, 1);
+ fBottom = aFar * (aProjectionMat.GetValue (1, 2) - 1.0) / aProjectionMat.GetValue (1, 1);
+ }
+ else
+ {
+ // handle orthographic projection
+ aNear = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) + 1.0);
+ aFar = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) - 1.0);
+ // Near plane
+ nLeft = ( 1.0 + aProjectionMat.GetValue (0, 3)) / (-aProjectionMat.GetValue (0, 0));
+ fLeft = nLeft;
+ nRight = ( 1.0 - aProjectionMat.GetValue (0, 3)) / aProjectionMat.GetValue (0, 0);
+ fRight = nRight;
+ nTop = ( 1.0 - aProjectionMat.GetValue (1, 3)) / aProjectionMat.GetValue (1, 1);
+ fTop = nTop;
+ nBottom = (-1.0 - aProjectionMat.GetValue (1, 3)) / aProjectionMat.GetValue (1, 1);
+ fBottom = nBottom;
+ }
+
+ Graphic3d_Vec4d aLeftTopNear (nLeft, nTop, -aNear, 1.0), aRightBottomFar (fRight, fBottom, -aFar, 1.0);
+ Graphic3d_Vec4d aLeftBottomNear (nLeft, nBottom, -aNear, 1.0), aRightTopFar (fRight, fTop, -aFar, 1.0);
+ Graphic3d_Vec4d aRightBottomNear (nRight, nBottom, -aNear, 1.0), aLeftTopFar (fLeft, fTop, -aFar, 1.0);
+ Graphic3d_Vec4d aRightTopNear (nRight, nTop, -aNear, 1.0), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0);
+
+ Graphic3d_Mat4d anInvWorldView;
+ aWorldViewMat.Inverted (anInvWorldView);
+
+ Graphic3d_Vec4d aTmpPnt;
+ aTmpPnt = anInvWorldView * aLeftTopNear;
+ thePoints.SetValue (FrustumVert_LeftTopNear, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aRightBottomFar;
+ thePoints.SetValue (FrustumVert_RightBottomFar, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aLeftBottomNear;
+ thePoints.SetValue (FrustumVert_LeftBottomNear, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aRightTopFar;
+ thePoints.SetValue (FrustumVert_RightTopFar, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aRightBottomNear;
+ thePoints.SetValue (FrustumVert_RightBottomNear, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aLeftTopFar;
+ thePoints.SetValue (FrustumVert_LeftTopFar, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aRightTopNear;
+ thePoints.SetValue (FrustumVert_RightTopNear, aTmpPnt.xyz() / aTmpPnt.w());
+ aTmpPnt = anInvWorldView * aLeftBottomFar;
+ thePoints.SetValue (FrustumVert_LeftBottomFar, aTmpPnt.xyz() / aTmpPnt.w());
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Graphic3d_Camera::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myUp)
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myDirection)
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myEye)
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDistance)
+}