1) Added method Graphic3d_Camera::FrustumPoints() returning corner points of camera frustum.
2) Refactored methods OpenGl_BVHTreeSelector::isFullOut(...) and OpenGl_BVHTreeSelector::CacheClipPtsProjections()
3) Changed computation algorithm of frustum planes (build them by corner points)
4) Added interactive object AIS_CameraFrustum to draw camera frustum.
5) Extended Draw command "vcamera" with option displaying camera frustum.
--- /dev/null
+// Created on: 2018-12-12
+// Created by: Olga SURYANINOVA
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_CameraFrustum.hxx>
+
+#include <AIS_DisplayMode.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Prs3d_LineAspect.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <Select3D_SensitiveGroup.hxx>
+#include <Select3D_SensitivePrimitiveArray.hxx>
+#include <Select3D_SensitiveSegment.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(AIS_CameraFrustum, AIS_InteractiveObject)
+
+namespace
+{
+ static const Standard_ShortReal THE_DEFAULT_TRANSPARENCY = 0.7f;
+ static const Quantity_Color THE_DEFAULT_COLOR = Quantity_NOC_WHITE;
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_CameraFrustum::AIS_CameraFrustum()
+: myPoints (0, Graphic3d_Camera::FrustumVerticesNB)
+{
+ myDrawer->SetLineAspect (new Prs3d_LineAspect (THE_DEFAULT_COLOR, Aspect_TOL_SOLID, 1.0));
+
+ Handle(Prs3d_ShadingAspect) aShadingAspect = new Prs3d_ShadingAspect();
+ aShadingAspect->SetMaterial (Graphic3d_NOM_PLASTIC);
+ aShadingAspect->Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Blend);
+ aShadingAspect->SetTransparency (THE_DEFAULT_TRANSPARENCY);
+ aShadingAspect->SetColor (THE_DEFAULT_COLOR);
+ myDrawer->SetShadingAspect (aShadingAspect);
+
+ myDrawer->SetTransparency (THE_DEFAULT_TRANSPARENCY);
+ SetDisplayMode (AIS_Shaded);
+}
+
+//=======================================================================
+//function : AcceptDisplayMode
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_CameraFrustum::AcceptDisplayMode (const Standard_Integer theMode) const
+{
+ return theMode == AIS_Shaded || theMode == AIS_WireFrame;
+}
+
+//=======================================================================
+//function : SetCameraFrustum
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::SetCameraFrustum (const Handle(Graphic3d_Camera)& theCamera)
+{
+ if (theCamera.IsNull())
+ {
+ return;
+ }
+
+ theCamera->FrustumPoints (myPoints);
+
+ fillTriangles();
+ fillBorders();
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : SetColor
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::SetColor (const Quantity_Color& theColor)
+{
+ AIS_InteractiveObject::SetColor (theColor);
+ myDrawer->ShadingAspect()->SetColor (theColor);
+ myDrawer->LineAspect()->SetColor (theColor);
+}
+
+//=======================================================================
+//function : UnsetColor
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::UnsetColor()
+{
+ if (!HasColor())
+ {
+ return;
+ }
+
+ AIS_InteractiveObject::UnsetColor();
+
+ myDrawer->ShadingAspect()->SetColor (THE_DEFAULT_COLOR);
+ myDrawer->LineAspect()->SetColor (THE_DEFAULT_COLOR);
+}
+
+//=======================================================================
+//function : UnsetColor
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::UnsetTransparency()
+{
+ myDrawer->ShadingAspect()->SetTransparency (0.0f);
+ myDrawer->SetTransparency (0.0f);
+}
+
+//=======================================================================
+//function : fillTriangles
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::fillTriangles()
+{
+ if (myTriangles.IsNull())
+ {
+ const Standard_Integer aPlaneTriangleVertsNb = 2 * 3;
+ const Standard_Integer aPlanesNb = 3 * 2;
+
+ myTriangles = new Graphic3d_ArrayOfTriangles (Graphic3d_Camera::FrustumVerticesNB, aPlaneTriangleVertsNb * aPlanesNb);
+ myTriangles->SetVertice (Graphic3d_Camera::FrustumVerticesNB, gp_Pnt (0.0, 0.0, 0.0));
+
+ // Triangles go in order (clockwise vertices traversing for correct normal):
+ // (0, 2, 1), (3, 1, 2)
+ const Standard_Integer aLookup1_clockwise[] = { 0, 1, 0, 1, 0, 1 };
+ const Standard_Integer aLookup2_clockwise[] = { 0, 0, 1, 1, 1, 0 };
+ // Triangles go in order (counterclockwise vertices traversing for correct normal):
+ // (1, 2, 0), (2, 1, 3)
+ const Standard_Integer aLookup1_anticlockwise[] = { 0, 1, 0, 1, 0, 1 };
+ const Standard_Integer aLookup2_anticlockwise[] = { 1, 0, 0, 0, 1, 1 };
+ Standard_Integer aShifts[] = { 0, 0, 0 };
+
+ // Planes go in order:
+ // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
+ for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
+ {
+ for (Standard_Integer i = 0; i < 2; ++i)
+ {
+ for (Standard_Integer aPntIter = 0; aPntIter < aPlaneTriangleVertsNb; ++aPntIter)
+ {
+ aShifts[aFaceIdx] = i;
+ if (i == 0)
+ {
+ aShifts[(aFaceIdx + 1) % 3] = aLookup1_clockwise[aPntIter];
+ aShifts[(aFaceIdx + 2) % 3] = aLookup2_clockwise[aPntIter];
+ }
+ else
+ {
+ aShifts[(aFaceIdx + 1) % 3] = aLookup1_anticlockwise[aPntIter];
+ aShifts[(aFaceIdx + 2) % 3] = aLookup2_anticlockwise[aPntIter];
+ }
+
+ Standard_Integer anIndex = aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2];
+ myTriangles->AddEdge (anIndex + 1);
+ }
+ }
+ }
+ }
+
+ for (Standard_Integer aPointIter = 0; aPointIter < Graphic3d_Camera::FrustumVerticesNB; ++aPointIter)
+ {
+ const Graphic3d_Vec3d aPnt = myPoints[aPointIter];
+ myTriangles->SetVertice (aPointIter + 1, gp_Pnt (aPnt.x(), aPnt.y(), aPnt.z()));
+ }
+}
+
+//=======================================================================
+//function : fillBorders
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::fillBorders()
+{
+ if (myBorders.IsNull())
+ {
+ const Standard_Integer aPlaneSegmVertsNb = 2 * 4;
+ const Standard_Integer aPlanesNb = 3 * 2;
+ myBorders = new Graphic3d_ArrayOfSegments (Graphic3d_Camera::FrustumVerticesNB, aPlaneSegmVertsNb * aPlanesNb);
+ myBorders->SetVertice (Graphic3d_Camera::FrustumVerticesNB, gp_Pnt (0.0, 0.0, 0.0));
+
+ // Segments go in order:
+ // (0, 2), (2, 3), (3, 1), (1, 0)
+ const Standard_Integer aLookup1[] = { 0, 1, 1, 1, 1, 0, 0, 0 };
+ const Standard_Integer aLookup2[] = { 0, 0, 0, 1, 1, 1, 1, 0 };
+ Standard_Integer aShifts[] = { 0, 0, 0 };
+
+ // Planes go in order:
+ // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
+ for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
+ {
+ for (Standard_Integer i = 0; i < 2; ++i)
+ {
+ for (Standard_Integer aSegmVertIter = 0; aSegmVertIter < aPlaneSegmVertsNb; ++aSegmVertIter)
+ {
+ aShifts[aFaceIdx] = i;
+ aShifts[(aFaceIdx + 1) % 3] = aLookup1[aSegmVertIter];
+ aShifts[(aFaceIdx + 2) % 3] = aLookup2[aSegmVertIter];
+
+ Standard_Integer anIndex = aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2];
+ myBorders->AddEdge (anIndex + 1);
+ }
+ }
+ }
+ }
+
+ for (Standard_Integer aPointIter = 0; aPointIter < Graphic3d_Camera::FrustumVerticesNB; ++aPointIter)
+ {
+ const Graphic3d_Vec3d aPnt = myPoints[aPointIter];
+ myBorders->SetVertice (aPointIter + 1, gp_Pnt (aPnt.x(), aPnt.y(), aPnt.z()));
+ }
+}
+
+//=======================================================================
+//function : Compute
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ thePrs->SetInfiniteState (true);
+ if (myTriangles.IsNull())
+ {
+ return;
+ }
+
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ switch (theMode)
+ {
+ case AIS_Shaded:
+ {
+ aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+ aGroup->AddPrimitiveArray (myTriangles);
+ }
+ Standard_FALLTHROUGH
+ case AIS_WireFrame:
+ {
+ aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
+ aGroup->AddPrimitiveArray (myBorders);
+ break;
+ }
+ }
+}
+
+//=======================================================================
+//function : ComputeSelection
+//purpose :
+//=======================================================================
+void AIS_CameraFrustum::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Standard_Integer theMode)
+{
+ Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
+ switch (theMode)
+ {
+ case SelectionMode_Edges:
+ {
+ Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (anOwner);
+ for (Standard_Integer anIter = 1; anIter <= myBorders->EdgeNumber(); anIter += 2)
+ {
+ aSensitiveEntity->Add (new Select3D_SensitiveSegment (anOwner, myBorders->Vertice (myBorders->Edge (anIter)), myBorders->Vertice(myBorders->Edge (anIter + 1))));
+ }
+ theSelection->Add (aSensitiveEntity);
+ break;
+ }
+ case SelectionMode_Volume:
+ {
+ Handle(Select3D_SensitivePrimitiveArray) aSelArray = new Select3D_SensitivePrimitiveArray (anOwner);
+ aSelArray->InitTriangulation (myTriangles->Attributes(), myTriangles->Indices(), TopLoc_Location());
+ theSelection->Add (aSelArray);
+ break;
+ }
+ }
+}
--- /dev/null
+// Created on: 2018-12-12
+// Created by: Olga SURYANINOVA
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_CameraFrustum_HeaderFile
+#define _AIS_CameraFrustum_HeaderFile
+
+#include <AIS_InteractiveObject.hxx>
+
+class Graphic3d_ArrayOfSegments;
+class Graphic3d_ArrayOfTriangles;
+
+//! Presentation for drawing camera frustum.
+//! Default configuration is built with filling and some transparency.
+class AIS_CameraFrustum : public AIS_InteractiveObject
+{
+ DEFINE_STANDARD_RTTIEXT(AIS_CameraFrustum, AIS_InteractiveObject)
+public:
+
+ //! Selection modes supported by this object
+ enum SelectionMode
+ {
+ SelectionMode_Edges = 0, //!< detect by edges (default)
+ SelectionMode_Volume = 1, //!< detect by volume
+ };
+
+public:
+
+ //! Constructs camera frustum with default configuration.
+ Standard_EXPORT AIS_CameraFrustum();
+
+ //! Sets camera frustum.
+ Standard_EXPORT void SetCameraFrustum (const Handle(Graphic3d_Camera)& theCamera);
+
+ //! Setup custom color.
+ Standard_EXPORT virtual void SetColor (const Quantity_Color& theColor) Standard_OVERRIDE;
+
+ //! Restore default color.
+ Standard_EXPORT virtual void UnsetColor() Standard_OVERRIDE;
+
+ //! Restore transparency setting.
+ Standard_EXPORT virtual void UnsetTransparency() Standard_OVERRIDE;
+
+ //! Return true if specified display mode is supported.
+ Standard_EXPORT virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE;
+
+protected:
+
+ //! Computes presentation of camera frustum.
+ Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode) Standard_OVERRIDE;
+
+ //! Compute selection.
+ Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Standard_Integer theMode) Standard_OVERRIDE;
+
+private:
+
+ //! Fills triangles primitive array for camera frustum filling.
+ void fillTriangles();
+
+ //! Fills polylines primitive array for camera frustum borders.
+ void fillBorders();
+
+protected:
+
+ NCollection_Array1<Graphic3d_Vec3d> myPoints; //!< Array of points
+ Handle(Graphic3d_ArrayOfTriangles) myTriangles; //!< Triangles for camera frustum filling
+ Handle(Graphic3d_ArrayOfSegments) myBorders; //!< Segments for camera frustum borders
+
+};
+
+#endif // _AIS_CameraFrustum_HeaderFile
AIS_BadEdgeFilter.hxx
AIS_C0RegularityFilter.cxx
AIS_C0RegularityFilter.hxx
+AIS_CameraFrustum.cxx
+AIS_CameraFrustum.hxx
AIS_Chamf2dDimension.cxx
AIS_Chamf2dDimension.hxx
AIS_Chamf2dDimension.lxx
theCamera->SetScale (aScale);
}
}
+
+//=======================================================================
+//function : FrustumPoints
+//purpose :
+//=======================================================================
+void Graphic3d_Camera::FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePoints) const
+{
+ if (thePoints.Length() != FrustumVerticesNB)
+ {
+ thePoints.Resize (0, FrustumVerticesNB, Standard_False);
+ }
+
+ const Graphic3d_Mat4d& aProjectionMat = ProjectionMatrix();
+ const Graphic3d_Mat4d& aWorldViewMat = OrientationMatrix();
+
+ 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());
+}
#include <Graphic3d_Vec3.hxx>
#include <Graphic3d_WorldViewProjState.hxx>
#include <NCollection_Lerp.hxx>
+#include <NCollection_Array1.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
const NCollection_Vec3<Elem_t>& theAxialScale,
NCollection_Mat4<Elem_t>& theOutMx);
+public:
+
+ //! Enumerates vertices of view volume.
+ enum
+ {
+ FrustumVert_LeftBottomNear,
+ FrustumVert_LeftBottomFar,
+ FrustumVert_LeftTopNear,
+ FrustumVert_LeftTopFar,
+ FrustumVert_RightBottomNear,
+ FrustumVert_RightBottomFar,
+ FrustumVert_RightTopNear,
+ FrustumVert_RightTopFar,
+ FrustumVerticesNB
+ };
+
+ //! Fill array of current view frustum corners.
+ //! The size of this array is equal to FrustumVerticesNB.
+ //! The order of vertices is as defined in FrustumVert_* enumeration.
+ Standard_EXPORT void FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePoints) const;
+
private:
gp_Dir myUp; //!< Camera up direction vector.
// purpose :
// =======================================================================
OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
-: myIsProjectionParallel (Standard_True),
+: myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB),
+ myIsProjectionParallel (Standard_True),
myCamScale (1.0),
myPixelSize (1.0)
{
? theCamera->Scale()
: 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance()
- 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 (!myIsProjectionParallel)
- {
- // handle perspective projection
- aNear = myProjectionMat.GetValue (2, 3) / (- 1.0 + myProjectionMat.GetValue (2, 2));
- aFar = myProjectionMat.GetValue (2, 3) / ( 1.0 + myProjectionMat.GetValue (2, 2));
- // Near plane
- nLeft = aNear * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
- nRight = aNear * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
- nTop = aNear * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
- nBottom = aNear * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
- // Far plane
- fLeft = aFar * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
- fRight = aFar * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
- fTop = aFar * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
- fBottom = aFar * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
- }
- else
- {
- // handle orthographic projection
- aNear = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) + 1.0);
- aFar = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) - 1.0);
- // Near plane
- nLeft = ( 1.0 + myProjectionMat.GetValue (0, 3)) / (-myProjectionMat.GetValue (0, 0));
- fLeft = nLeft;
- nRight = ( 1.0 - myProjectionMat.GetValue (0, 3)) / myProjectionMat.GetValue (0, 0);
- fRight = nRight;
- nTop = ( 1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
- fTop = nTop;
- nBottom = (-1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
- fBottom = nBottom;
- }
+ // Compute frustum points
+ theCamera->FrustumPoints (myClipVerts);
+
+ // Compute frustum planes
+ // Vertices go in order:
+ // 0, 2, 1
+ const Standard_Integer aLookup1[] = { 0, 1, 0 };
+ const Standard_Integer aLookup2[] = { 0, 0, 1 };
+ Standard_Integer aShifts[] = { 0, 0, 0 };
- OpenGl_Vec4d aLeftTopNear (nLeft, nTop, -aNear, 1.0), aRightBottomFar (fRight, fBottom, -aFar, 1.0);
- OpenGl_Vec4d aLeftBottomNear (nLeft, nBottom, -aNear, 1.0), aRightTopFar (fRight, fTop, -aFar, 1.0);
- OpenGl_Vec4d aRightBottomNear (nRight, nBottom, -aNear, 1.0), aLeftTopFar (fLeft, fTop, -aFar, 1.0);
- OpenGl_Vec4d aRightTopNear (nRight, nTop, -aNear, 1.0), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0);
-
- const OpenGl_Mat4d aViewProj = myProjectionMat * myWorldViewMat;
- OpenGl_Mat4d anInvWorldView;
- myWorldViewMat.Inverted (anInvWorldView);
-
- myClipVerts[ClipVert_LeftTopNear] = anInvWorldView * aLeftTopNear;
- myClipVerts[ClipVert_RightBottomFar] = anInvWorldView * aRightBottomFar;
- myClipVerts[ClipVert_LeftBottomNear] = anInvWorldView * aLeftBottomNear;
- myClipVerts[ClipVert_RightTopFar] = anInvWorldView * aRightTopFar;
- myClipVerts[ClipVert_RightBottomNear] = anInvWorldView * aRightBottomNear;
- myClipVerts[ClipVert_LeftTopFar] = anInvWorldView * aLeftTopFar;
- myClipVerts[ClipVert_RightTopNear] = anInvWorldView * aRightTopNear;
- myClipVerts[ClipVert_LeftBottomFar] = anInvWorldView * aLeftBottomFar;
-
- // UNNORMALIZED!
- myClipPlanes[Plane_Left] = aViewProj.GetRow (3) + aViewProj.GetRow (0);
- myClipPlanes[Plane_Right] = aViewProj.GetRow (3) - aViewProj.GetRow (0);
- myClipPlanes[Plane_Top] = aViewProj.GetRow (3) - aViewProj.GetRow (1);
- myClipPlanes[Plane_Bottom] = aViewProj.GetRow (3) + aViewProj.GetRow (1);
- myClipPlanes[Plane_Near] = aViewProj.GetRow (3) + aViewProj.GetRow (2);
- myClipPlanes[Plane_Far] = aViewProj.GetRow (3) - aViewProj.GetRow (2);
-
- gp_Pnt aPtCenter = theCamera->Center();
- OpenGl_Vec4d aCenter (aPtCenter.X(), aPtCenter.Y(), aPtCenter.Z(), 1.0);
-
- for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter)
+ // Planes go in order:
+ // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
+ for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
{
- OpenGl_Vec4d anEq = myClipPlanes[aPlaneIter];
- if (SignedPlanePointDistance (anEq, aCenter) > 0)
+ for (Standard_Integer i = 0; i < 2; ++i)
{
- anEq *= -1.0;
- myClipPlanes[aPlaneIter] = anEq;
- }
+ OpenGl_Vec3d aPlanePnts[3];
+ for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter)
+ {
+ aShifts[aFaceIdx] = i;
+ aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter];
+ aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter];
+
+ aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]];
+ }
+
+ myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0];
+ myClipPlanes[aFaceIdx * 2 + i].Normal =
+ OpenGl_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0],
+ aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f);
+ }
}
}
// =======================================================================
void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
{
+ // project frustum onto its own normals
const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
- for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
+ for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
{
- const OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
- for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
+ for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter)
{
- Standard_Real aProjection = aPlane.x() * myClipVerts[aCornerIter].x()
- + aPlane.y() * myClipVerts[aCornerIter].y()
- + aPlane.z() * myClipVerts[aCornerIter].z();
+ Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal);
aMaxProj = Max (aProjection, aMaxProj);
aMinProj = Min (aProjection, aMinProj);
}
myMinClipProjectionPts[aPlaneIter] = aMinProj;
}
+ // project frustum onto main axes
+ OpenGl_Vec3d anAxes[] = { OpenGl_Vec3d (1.0, 0.0, 0.0),
+ OpenGl_Vec3d (0.0, 1.0, 0.0),
+ OpenGl_Vec3d (0.0, 0.0, 1.0) };
for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
{
Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
- for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
+ for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter)
{
- Standard_Real aProjection = aDim == 0
- ? myClipVerts[aCornerIter].x()
- : (aDim == 1
- ? myClipVerts[aCornerIter].y()
- : myClipVerts[aCornerIter].z());
+ Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]);
aMaxProj = Max (aProjection, aMaxProj);
aMinProj = Min (aProjection, aMinProj);
}
//! Empty constructor.
CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {}
};
+
+ //! Auxiliary structure representing 3D plane.
+ struct Plane
+ {
+ //! Creates default plane.
+ Plane()
+ : Origin (0.0, 0.0, 0.0),
+ Normal (0.0, 0.0, 1.0) {}
+
+ //! Creates plane with specific parameters.
+ Plane (const OpenGl_Vec3d& theOrigin,
+ const OpenGl_Vec3d& theNormal)
+ : Origin (theOrigin),
+ Normal (theNormal) {}
+
+ OpenGl_Vec3d Origin;
+ OpenGl_Vec3d Normal;
+ };
+
public:
//! Creates an empty selector object with parallel projection type by default.
// /
// E2
- // E0 test
+ // E0 test (x axis)
if (theMinPt.x() > myMaxOrthoProjectionPts[0]
|| theMaxPt.x() < myMinOrthoProjectionPts[0])
{
return true;
}
- // E1 test
+ // E1 test (y axis)
if (theMinPt.y() > myMaxOrthoProjectionPts[1]
|| theMaxPt.y() < myMinOrthoProjectionPts[1])
{
return true;
}
- // E2 test
+ // E2 test (z axis)
if (theMinPt.z() > myMaxOrthoProjectionPts[2]
|| theMaxPt.z() < myMinOrthoProjectionPts[2])
{
return true;
}
- Standard_Real aBoxProjMax = 0.0, aBoxProjMin = 0.0;
const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
- for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
+ for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
{
- OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
- aBoxProjMax = (aPlane.x() > 0.0 ? (aPlane.x() * theMaxPt.x()) : aPlane.x() * theMinPt.x())
- + (aPlane.y() > 0.0 ? (aPlane.y() * theMaxPt.y()) : aPlane.y() * theMinPt.y())
- + (aPlane.z() > 0.0 ? (aPlane.z() * theMaxPt.z()) : aPlane.z() * theMinPt.z());
- if (aBoxProjMax > myMinClipProjectionPts[aPlaneIter]
- && aBoxProjMax < myMaxClipProjectionPts[aPlaneIter])
+ // frustum normals
+ const OpenGl_Vec3d anAxis = myClipPlanes[aPlaneIter].Normal;
+
+ const OpenGl_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPt.x() : theMinPt.x(),
+ anAxis.y() > 0.0 ? theMaxPt.y() : theMinPt.y(),
+ anAxis.z() > 0.0 ? theMaxPt.z() : theMinPt.z());
+ Standard_Real aPnt0 = aPVertex.Dot (anAxis);
+
+ if (aPnt0 >= myMinClipProjectionPts[aPlaneIter]
+ && aPnt0 <= myMaxClipProjectionPts[aPlaneIter])
{
continue;
}
-
- aBoxProjMin = (aPlane.x() < 0.0 ? aPlane.x() * theMaxPt.x() : aPlane.x() * theMinPt.x())
- + (aPlane.y() < 0.0 ? aPlane.y() * theMaxPt.y() : aPlane.y() * theMinPt.y())
- + (aPlane.z() < 0.0 ? aPlane.z() * theMaxPt.z() : aPlane.z() * theMinPt.z());
- if (aBoxProjMin > myMaxClipProjectionPts[aPlaneIter]
- || aBoxProjMax < myMinClipProjectionPts[aPlaneIter])
+
+ const OpenGl_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPt.x() : theMaxPt.x(),
+ anAxis.y() > 0.0 ? theMinPt.y() : theMaxPt.y(),
+ anAxis.z() > 0.0 ? theMinPt.z() : theMaxPt.z());
+ Standard_Real aPnt1 = aNVertex.Dot (anAxis);
+
+ const Standard_Real aMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1;
+ const Standard_Real aMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1;
+
+ if (aMin > myMaxClipProjectionPts[aPlaneIter]
+ || aMax < myMinClipProjectionPts[aPlaneIter])
{
return true;
}
//! Enumerates planes of view volume.
enum
{
- Plane_Top,
- Plane_Bottom,
Plane_Left,
Plane_Right,
+ Plane_Bottom,
+ Plane_Top,
Plane_Near,
Plane_Far,
PlanesNB
};
- //! Enumerates vertices of view volume.
- enum
- {
- ClipVert_LeftTopNear,
- ClipVert_LeftBottomNear,
- ClipVert_RightTopNear,
- ClipVert_RightBottomNear,
- ClipVert_LeftTopFar,
- ClipVert_LeftBottomFar,
- ClipVert_RightTopFar,
- ClipVert_RightBottomFar,
- ClipVerticesNB
- };
-
protected:
- OpenGl_Vec4d myClipPlanes[PlanesNB]; //!< Plane equations
- OpenGl_Vec4d myClipVerts[ClipVerticesNB]; //!< Vertices
+ Plane myClipPlanes[PlanesNB]; //!< Planes
+ NCollection_Array1<OpenGl_Vec3d> myClipVerts; //!< Vertices
Handle(Graphic3d_Camera) myCamera; //!< camera definition
// for caching clip points projections onto viewing area normals once per traverse
- // ORDER: TOP, BOTTOM, LEFT, RIGHT, NEAR, FAR
+ // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals
Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals
#include <AIS_Animation.hxx>
#include <AIS_AnimationCamera.hxx>
#include <AIS_AnimationObject.hxx>
+#include <AIS_CameraFrustum.hxx>
#include <AIS_ColorScale.hxx>
#include <AIS_Manipulator.hxx>
#include <AIS_RubberBand.hxx>
return 0;
}
+ TCollection_AsciiString aPrsName;
for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
{
Standard_CString anArg = theArgVec[anArgIter];
}
theDI << aCamera->FOVy() << " ";
}
+ else if (aPrsName.IsEmpty()
+ && !anArgCase.StartsWith ("-"))
+ {
+ aPrsName = anArg;
+ }
else
{
std::cout << "Error: unknown argument '" << anArg << "'\n";
}
}
- aView->AutoZFit();
- aView->Redraw();
+ if (aPrsName.IsEmpty()
+ || theArgsNb > 2)
+ {
+ aView->AutoZFit();
+ aView->Redraw();
+ }
+
+ if (!aPrsName.IsEmpty())
+ {
+ Handle(AIS_CameraFrustum) aCameraFrustum;
+ if (GetMapOfAIS().IsBound2 (aPrsName))
+ {
+ // find existing object
+ aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
+ if (aCameraFrustum.IsNull())
+ {
+ std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
+ return 1;
+ }
+ }
+
+ if (aCameraFrustum.IsNull())
+ {
+ aCameraFrustum = new AIS_CameraFrustum();
+ }
+ else
+ {
+ // not include displayed object of old camera frustum in the new one.
+ ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
+ aView->ZFitAll();
+ }
+ aCameraFrustum->SetCameraFrustum (aView->Camera());
+
+ ViewerTest::Display (aPrsName, aCameraFrustum);
+ }
return 0;
}
"vnbselected"
"\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
theCommands.Add ("vcamera",
- "vcamera [-ortho] [-projtype]"
+ "vcamera [PrsName] [-ortho] [-projtype]"
"\n\t\t: [-persp]"
"\n\t\t: [-fovy [Angle]] [-distance [Distance]]"
"\n\t\t: [-stereo] [-leftEye] [-rightEye]"
"\n\t\t: [-iod [Distance]] [-iodType [absolute|relative]]"
"\n\t\t: [-zfocus [Value]] [-zfocusType [absolute|relative]]"
- "\n\t\t: Manage camera parameters."
+ "\n\t\t: Manages camera parameters."
+ "\n\t\t: Displays frustum when presntation name PrsName is specified."
"\n\t\t: Prints current value when option called without argument."
"\n\t\t: Orthographic camera:"
"\n\t\t: -ortho activate orthographic projection"
--- /dev/null
+puts "============="
+puts "0030412: Visualization, TKV3d - add presentation of camera frustum"
+puts "============="
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+
+vfront
+vcamera -persp
+
+set THE_NB_BOXES 5
+puts "Creating [expr $THE_NB_BOXES * $THE_NB_BOXES * $THE_NB_BOXES] boxes..."
+for {set i 0} {$i < $THE_NB_BOXES} {incr i} {
+ for {set j 0} {$j < $THE_NB_BOXES} {incr j} {
+ for {set k 0} {$k < $THE_NB_BOXES} {incr k} {
+ box b$i$j$k 3.*$i 3.*$j 3.*$k 1 1 1
+ vdisplay -noupdate -dispMode 1 b$i$j$k
+ }
+ }
+}
+
+vfit
+vzoom 1.5
+vcamera cam
+
+vright
+vfit
+vdump $::imagedir/${::casename}_cam_right.png
+
+vaxo
+vfit
+vdump $::imagedir/${::casename}_cam_axo.png
\ No newline at end of file