From: apl Date: Mon, 27 Jul 2015 15:01:34 +0000 (+0300) Subject: 0026344: Visualization - provide a support of zoom persistent selection X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2FCR0-ipdm_CR26344;p=occt-copy.git 0026344: Visualization - provide a support of zoom persistent selection 1) New Graphic3d_TransformPers structure for defining parameters and algorithm methods, featuring: a) application of transformation to projection and world view matrices; b) computation of model-world transformation of persistent object; c) computation of transformed bounding box of persistent object. 2) Transform persistence algorithm does not make any changes to model-world transformation of object (deals with projection and world view matrices only), thus making possible to employ local transformation in a usual way. 3) Support of BVH selection for transform persistent objects (pan, rotate, zoom, trihedron persistence only). 4) Support efficient frustum culling for transform persistent objects (pan, rotate, zoom, trihedron persistence only). 5) Support of z-fitting algorithm for world-view space transform persistent objects (rotate, zoom persistence only). 6) Rewrite usage of transform persistence structures and utilities classes: a) Replaced Graphic3d_CTransPers, TEL_TRANSFORM_PERSISTENCE by Graphic3d_TransformPers; b) Move functions from OpenGl_Utils.hxx to Graphic3d_TransformUtils.hxx; c) Extract matrix stack class from OpenGl_Utils.hxx to OpenGl_MatrixStack.hxx; 7) New class Graphic3d_WorldViewProjState to keep track of projection, world view matrices changes for a camera. 8) New test case bugs/vis/bug26344. 9) Renamed method Graphic3d_Camera::ModelViewState of to ::WorldViewState for consistency. --- diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 14f6e9624c..a1151c28c1 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -40,7 +40,6 @@ Graphic3d.edl Graphic3d_CMPLRS.edl Graphic3d_WOKSteps.edl Graphic3d_TransModeFlags.hxx -Graphic3d_CTransPersStruct.hxx Graphic3d_NListOfHAsciiString.hxx Graphic3d_AspectText3d.cxx Graphic3d_PtrFrameBuffer.hxx @@ -65,3 +64,6 @@ Graphic3d_Camera.cxx Graphic3d_Camera.hxx Graphic3d_RenderingParams.hxx Graphic3d_NMapOfTransient.hxx +Graphic3d_TransformPers.hxx +Graphic3d_TransformUtils.hxx +Graphic3d_WorldViewProjState.hxx diff --git a/src/Graphic3d/Graphic3d.cdl b/src/Graphic3d/Graphic3d.cdl index 7ed61e290b..9765832017 100644 --- a/src/Graphic3d/Graphic3d.cdl +++ b/src/Graphic3d/Graphic3d.cdl @@ -406,12 +406,11 @@ is imported transient class ClipPlane; ---Category: Imported types - imported CTexture; - imported CTransPersStruct; imported TransModeFlags; - + imported TransformPers; + imported transient class MarkerImage; imported transient class Camera; diff --git a/src/Graphic3d/Graphic3d_CStructure.cxx b/src/Graphic3d/Graphic3d_CStructure.cxx index 36343c0c66..25aafd937c 100644 --- a/src/Graphic3d/Graphic3d_CStructure.cxx +++ b/src/Graphic3d/Graphic3d_CStructure.cxx @@ -59,10 +59,4 @@ Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureMana ContextFillArea.IsSet = 0, ContextMarker.IsSet = 0, ContextText.IsSet = 0; - - TransformPersistence.IsSet = 0; - TransformPersistence.Flag = Graphic3d_TMF_None; - TransformPersistence.Point.x = 0.0; - TransformPersistence.Point.y = 0.0; - TransformPersistence.Point.z = 0.0; } diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index a16b45c9d4..b85b620a22 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -147,7 +148,7 @@ public: unsigned IsMutable : 1; unsigned Is2dText : 1; - CALL_DEF_TRANSFORM_PERSISTENCE TransformPersistence; + Graphic3d_TransformPers TransformPersistence; protected: diff --git a/src/Graphic3d/Graphic3d_CTransPersStruct.hxx b/src/Graphic3d/Graphic3d_CTransPersStruct.hxx deleted file mode 100644 index b7bb0f4ebb..0000000000 --- a/src/Graphic3d/Graphic3d_CTransPersStruct.hxx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 1999-2014 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. - -/*============================================================================*/ -/*==== Titel: Graphic3d_CTransPersStruct.hxx */ -/*==== Role : */ -/*==== */ -/*==== Implementation: This is a primitive type implemented with typedef */ -/*============================================================================*/ - -#ifndef _Graphic3d_CTransPersStruct_HeaderFile -#define _Graphic3d_CTransPersStruct_HeaderFile - -#include -typedef CALL_DEF_TRANSFORM_PERSISTENCE Graphic3d_CTransPersStruct; - -#endif /*_Graphic3d_CTransPersStruct_HeaderFile*/ diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index 8184f2eec7..aa6e6f1b56 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -16,8 +16,9 @@ #include #include -#include #include +#include +#include #include #include @@ -63,8 +64,9 @@ Graphic3d_Camera::Graphic3d_Camera() myIOD (0.05), myIODType (IODType_Relative) { - myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); - myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); + myWorldViewProjState.Initialize ((Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER), + (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER), + this); } // ======================================================================= @@ -73,6 +75,8 @@ Graphic3d_Camera::Graphic3d_Camera() // ======================================================================= Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther) { + myWorldViewProjState.Initialize (this); + Copy (theOther); } @@ -82,17 +86,18 @@ Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther) // ======================================================================= void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera) { - myFOVy = theOtherCamera->myFOVy; - myZNear = theOtherCamera->myZNear; - myZFar = theOtherCamera->myZFar; - myAspect = theOtherCamera->myAspect; - myScale = theOtherCamera->myScale; - myZFocus = theOtherCamera->myZFocus; - myZFocusType = theOtherCamera->myZFocusType; - myIOD = theOtherCamera->myIOD; - myIODType = theOtherCamera->myIODType; - myProjType = theOtherCamera->myProjType; - myProjectionState = theOtherCamera->myProjectionState; + myFOVy = theOtherCamera->myFOVy; + myZNear = theOtherCamera->myZNear; + myZFar = theOtherCamera->myZFar; + myAspect = theOtherCamera->myAspect; + myScale = theOtherCamera->myScale; + myZFocus = theOtherCamera->myZFocus; + myZFocusType = theOtherCamera->myZFocusType; + myIOD = theOtherCamera->myIOD; + myIODType = theOtherCamera->myIODType; + myProjType = theOtherCamera->myProjType; + + myWorldViewProjState.ProjectionState() = theOtherCamera->ProjectionState(); InvalidateProjection(); } @@ -103,11 +108,12 @@ void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOther // ======================================================================= void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera) { - myUp = theOtherCamera->myUp; - myEye = theOtherCamera->myEye; - myCenter = theOtherCamera->myCenter; - myAxialScale = theOtherCamera->myAxialScale; - myOrientationState = theOtherCamera->myOrientationState; + myUp = theOtherCamera->myUp; + myEye = theOtherCamera->myEye; + myCenter = theOtherCamera->myCenter; + myAxialScale = theOtherCamera->myAxialScale; + + myWorldViewProjState.WorldViewState() = theOtherCamera->WorldViewState(); InvalidateOrientation(); } @@ -811,7 +817,7 @@ void Graphic3d_Camera::InvalidateProjection() { myMatricesD.ResetProjection(); myMatricesF.ResetProjection(); - myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); + myWorldViewProjState.ProjectionState() = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); } // ======================================================================= @@ -822,7 +828,7 @@ void Graphic3d_Camera::InvalidateOrientation() { myMatricesD.ResetOrientation(); myMatricesF.ResetOrientation(); - myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); + myWorldViewProjState.WorldViewState() = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER); } // ======================================================================= diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index 56620af801..d371e0eb13 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -31,6 +32,7 @@ #include //! Forward declaration +class Graphic3d_WorldViewProjState; class Handle(Graphic3d_Camera); //! Camera class provides object-oriented approach to setting up projection @@ -437,16 +439,22 @@ public: //! @name Camera modification state public: + //! @return projection modification state of the camera. + const Graphic3d_WorldViewProjState& WorldViewProjState() const + { + return myWorldViewProjState; + } + //! Returns modification state of camera projection matrix Standard_Size ProjectionState() const { - return myProjectionState; + return myWorldViewProjState.ProjectionState(); } - //! Returns modification state of camera model-view matrix - Standard_Size ModelViewState() const + //! Returns modification state of camera world view transformation matrix. + Standard_Size WorldViewState() const { - return myOrientationState; + return myWorldViewProjState.WorldViewState(); } //! @name Lazily-computed orientation and projection matrices derived from camera parameters @@ -614,8 +622,7 @@ private: mutable TransformMatrices myMatricesD; mutable TransformMatrices myMatricesF; - mutable Standard_Size myProjectionState; - mutable Standard_Size myOrientationState; + mutable Graphic3d_WorldViewProjState myWorldViewProjState; public: diff --git a/src/Graphic3d/Graphic3d_Structure.cdl b/src/Graphic3d/Graphic3d_Structure.cdl index 1710ac2e79..c433126766 100644 --- a/src/Graphic3d/Graphic3d_Structure.cdl +++ b/src/Graphic3d/Graphic3d_Structure.cdl @@ -63,6 +63,7 @@ uses IndexedMapOfAddress from Graphic3d, StructureManager from Graphic3d, StructureManagerPtr from Graphic3d, + TransformPers from Graphic3d, TypeOfComposition from Graphic3d, TypeOfConnection from Graphic3d, TypeOfPrimitive from Graphic3d, @@ -774,6 +775,11 @@ is ---Purpose: Get the current point of relative modelling transform persistence is static; + TransformPersistence(me) returns TransformPers from Graphic3d is static; + ---Purpose: @return transform persistence of the presentable object. + ---C++: inline + ---C++: return const& + SetMutable ( me : mutable; theIsMutable : Boolean from Standard ) is static; diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index db64f66463..bb64c12b8b 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -122,7 +122,7 @@ void Graphic3d_Structure::CalculateBoundBox() { Graphic3d_BndBox4d aBox; addTransformed (aBox, Standard_True); - if (aBox.IsValid() && myCStructure->TransformPersistence.Flag == 0) + if (aBox.IsValid()) { Graphic3d_Vec4 aMinPt (RealToShortReal (aBox.CornerMin().x()), RealToShortReal (aBox.CornerMin().y()), @@ -1707,14 +1707,10 @@ void Graphic3d_Structure::SetTransformPersistence (const Graphic3d_TransModeFlag { if (IsDeleted()) return; - myCStructure->TransformPersistence.Flag = theFlag; - myCStructure->TransformPersistence.Point.x = float (thePoint.X()); - myCStructure->TransformPersistence.Point.y = float (thePoint.Y()); - myCStructure->TransformPersistence.Point.z = float (thePoint.Z()); - myCStructure->UpdateAspects(); - CalculateBoundBox(); - - myCStructure->TransformPersistence.IsSet = 1; + myCStructure->TransformPersistence.Flags = theFlag; + myCStructure->TransformPersistence.Point.x() = thePoint.X(); + myCStructure->TransformPersistence.Point.y() = thePoint.Y(); + myCStructure->TransformPersistence.Point.z() = thePoint.Z(); } //============================================================================= @@ -1723,7 +1719,7 @@ void Graphic3d_Structure::SetTransformPersistence (const Graphic3d_TransModeFlag //============================================================================= Graphic3d_TransModeFlags Graphic3d_Structure::TransformPersistenceMode() const { - return myCStructure->TransformPersistence.Flag; + return myCStructure->TransformPersistence.Flags; } //============================================================================= @@ -1733,9 +1729,9 @@ Graphic3d_TransModeFlags Graphic3d_Structure::TransformPersistenceMode() const gp_Pnt Graphic3d_Structure::TransformPersistencePoint() const { gp_Pnt aPnt (0.0, 0.0, 0.0); - aPnt.SetX (myCStructure->TransformPersistence.Point.x); - aPnt.SetY (myCStructure->TransformPersistence.Point.y); - aPnt.SetZ (myCStructure->TransformPersistence.Point.z); + aPnt.SetX (myCStructure->TransformPersistence.Point.x()); + aPnt.SetY (myCStructure->TransformPersistence.Point.y()); + aPnt.SetZ (myCStructure->TransformPersistence.Point.z()); return aPnt; } diff --git a/src/Graphic3d/Graphic3d_Structure.lxx b/src/Graphic3d/Graphic3d_Structure.lxx index 86e9061877..7fd5ec20b0 100644 --- a/src/Graphic3d/Graphic3d_Structure.lxx +++ b/src/Graphic3d/Graphic3d_Structure.lxx @@ -21,3 +21,12 @@ inline const Handle(Graphic3d_CStructure)& Graphic3d_Structure::CStructure() con { return myCStructure; } + +// ======================================================================= +// function : TransformPersistence +// purpose : +// ======================================================================= +inline const Graphic3d_TransformPers& Graphic3d_Structure::TransformPersistence() const +{ + return myCStructure->TransformPersistence; +} diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx new file mode 100644 index 0000000000..4f5d6ba625 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -0,0 +1,357 @@ +// Created on: 2015-06-18 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 _Graphic3d_TransformPers_HeaderFile +#define _Graphic3d_TransformPers_HeaderFile + +#include +#include +#include +#include +#include +#include + +//! Class for keeping and computing transformation persistence. +class Graphic3d_TransformPers +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Default constructor. + Graphic3d_TransformPers() + : Flags (Graphic3d_TMF_None), + Point (0.0, 0.0, 0.0) {} + + //! Transformation persistence mode flags. + Graphic3d_TransModeFlags Flags; + + //! Reference point for transformation. + Graphic3d_Vec3d Point; + +public: + + //! Apply transformation to bounding box of presentation. + //! @param theProjection [in] the projection transformation matrix. + //! @param theWorldView [in] the world view transformation matrix. + //! @param theViewportWidth [in] the width of viewport (for 2d persistence). + //! @param theViewportHeight [in] the height of viewport (for 2d persistence). + //! @param theBoundingBox [in/out] the bounding box to transform. + template + void Apply (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + Bnd_Box& theBoundingBox) const; + + //! Apply transformation to bounding box of presentation + //! @param theProjection [in] the projection transformation matrix. + //! @param theWorldView [in] the world view transformation matrix. + //! @param theViewportWidth [in] the width of viewport (for 2d persistence). + //! @param theViewportHeight [in] the height of viewport (for 2d persistence). + //! @param theBoundingBox [in/out] the bounding box to transform. + template + void Apply (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + BVH_Box& theBoundingBox) const; + + //! Compute transformation. + //! Computed matrix can be applied to model world transformation + //! of an object to implement effect of transformation persistence. + //! @param theProjection [in] the projection transformation matrix. + //! @param theWorldView [in] the world view transformation matrix. + //! @param theViewportWidth [in] the width of viewport (for 2d persistence). + //! @param theViewportHeight [in] the height of viewport (for 2d persistence). + //! @return transformation matrix to be applied to model world transformation of an object. + template + NCollection_Mat4 Compute (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) const; + + template + void Apply (NCollection_Mat4& theProjection, + NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) const; +}; + +// ======================================================================= +// function : Apply +// purpose : Apply transformation to world view and projection matrices. +// ======================================================================= +template +void Graphic3d_TransformPers::Apply (NCollection_Mat4& theProjection, + NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) const +{ + if (!Flags) + { + return; + } + + if (Flags & Graphic3d_TMF_2d) + { + T aLeft = -static_cast (theViewportWidth / 2); + T aRight = static_cast (theViewportWidth / 2); + T aBottom = -static_cast (theViewportHeight / 2); + T aTop = static_cast (theViewportHeight / 2); + T aGap = static_cast (Point.z()); + if (Point.x() > 0) + { + aLeft -= static_cast (theViewportWidth / 2) - aGap; + aRight -= static_cast (theViewportWidth / 2) - aGap; + } + else if (Point.x() < 0) + { + aLeft += static_cast (theViewportWidth / 2) - aGap; + aRight += static_cast (theViewportWidth / 2) - aGap; + } + if (Point.y() > 0) + { + aBottom -= static_cast (theViewportHeight / 2) - aGap; + aTop -= static_cast (theViewportHeight / 2) - aGap; + } + else if (Point.y() < 0) + { + aBottom += static_cast (theViewportHeight / 2) - aGap; + aTop += static_cast (theViewportHeight / 2) - aGap; + } + if (Flags == Graphic3d_TMF_2d_IsTopDown) + { + const T aTemp = aTop; + aTop = aBottom; + aBottom = aTemp; + } + + Graphic3d_TransformUtils::Ortho2D (theProjection, aLeft, aRight, aBottom, aTop); + + theWorldView.InitIdentity(); + } + else + { + // Compute reference point for transformation in untransformed projection space. + NCollection_Vec4 aRefPoint (static_cast (Point.x()), + static_cast (Point.y()), + static_cast (Point.z()), + static_cast (1.0)); + NCollection_Vec4 aRefPointProj; + if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers) + { + aRefPointProj = theProjection * (theWorldView * aRefPoint); + aRefPointProj /= aRefPointProj.w(); + } + + // Prevent zooming. + if ((Flags & Graphic3d_TMF_ZoomPers) || (Flags == Graphic3d_TMF_TriedronPers)) + { + // Compute fixed-zoom multiplier. Actually function works ugly with TelPerspective! + const T aDet2 = static_cast (0.002) / Max (theProjection.GetValue (1, 1), theProjection.GetValue (0, 0)); + theProjection.ChangeValue (0, 0) *= aDet2; + theProjection.ChangeValue (1, 1) *= aDet2; + theProjection.ChangeValue (2, 2) *= aDet2; + } + + // Prevent translation by nullifying translation component. + if ((Flags & Graphic3d_TMF_PanPers) || Flags == Graphic3d_TMF_TriedronPers) + { + theWorldView .SetValue (0, 3, static_cast (0.0)); + theWorldView .SetValue (1, 3, static_cast (0.0)); + theWorldView .SetValue (2, 3, static_cast (0.0)); + theProjection.SetValue (0, 3, static_cast (0.0)); + theProjection.SetValue (1, 3, static_cast (0.0)); + theProjection.SetValue (2, 3, static_cast (0.0)); + } + + // Prevent scaling-on-axis. + if (Flags & Graphic3d_TMF_ZoomPers) + { + NCollection_Vec3 aVecX = theWorldView.GetColumn (0).xyz(); + NCollection_Vec3 aVecY = theWorldView.GetColumn (1).xyz(); + NCollection_Vec3 aVecZ = theWorldView.GetColumn (2).xyz(); + T aScaleX = aVecX.Modulus(); + T aScaleY = aVecY.Modulus(); + T aScaleZ = aVecZ.Modulus(); + for (Standard_Integer anI = 0; anI < 3; ++anI) + { + theWorldView.ChangeValue (0, anI) /= aScaleX; + theWorldView.ChangeValue (1, anI) /= aScaleY; + theWorldView.ChangeValue (2, anI) /= aScaleZ; + } + } + + // Prevent rotation by nullifying rotation component. + if (Flags & Graphic3d_TMF_RotatePers) + { + theWorldView.SetValue (0, 0, static_cast (1.0)); + theWorldView.SetValue (1, 0, static_cast (0.0)); + theWorldView.SetValue (2, 0, static_cast (0.0)); + + theWorldView.SetValue (0, 1, static_cast (0.0)); + theWorldView.SetValue (1, 1, static_cast (1.0)); + theWorldView.SetValue (2, 1, static_cast (0.0)); + + theWorldView.SetValue (0, 2, static_cast (0.0)); + theWorldView.SetValue (1, 2, static_cast (0.0)); + theWorldView.SetValue (2, 2, static_cast (1.0)); + } + + if (Flags == Graphic3d_TMF_TriedronPers) + { + if (Point.x() != 0.0 && Point.y() != 0.0) + { + NCollection_Mat4 anUnviewMat; + + if (!(theProjection).Inverted (anUnviewMat)) + { + Standard_ProgramError::Raise ("Graphic3d_TransformPers::Apply, can not inverse projection matrix."); + } + + NCollection_Vec4 aProjMax (static_cast ( 1.0), static_cast ( 1.0), static_cast (0.0), static_cast (1.0)); + NCollection_Vec4 aProjMin (static_cast (-1.0), static_cast (-1.0), static_cast (0.0), static_cast (1.0)); + NCollection_Vec4 aViewMax = anUnviewMat * aProjMax; + NCollection_Vec4 aViewMin = anUnviewMat * aProjMin; + + aViewMax /= aViewMax.w(); + aViewMin /= aViewMin.w(); + + T aMoveX = static_cast (0.5) * (aViewMax.x() - aViewMin.x() - static_cast (Point.z())); + T aMoveY = static_cast (0.5) * (aViewMax.y() - aViewMin.y() - static_cast (Point.z())); + + aMoveX = (Point.x() > 0.0) ? aMoveX : -aMoveX; + aMoveY = (Point.y() > 0.0) ? aMoveY : -aMoveY; + + Graphic3d_TransformUtils::Translate (theProjection, aMoveX, aMoveY, static_cast (0.0)); + } + } + else if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers) + { + NCollection_Mat4 anUnviewMat; + + if (!(theProjection * theWorldView).Inverted (anUnviewMat)) + { + Standard_ProgramError::Raise ("Graphic3d_TransformPers::Apply, can not inverse world view projection matrix."); + } + + // Move to reference point location in transformed view projection space. + aRefPoint = anUnviewMat * aRefPointProj; + aRefPoint /= aRefPoint.w(); + + Graphic3d_TransformUtils::Translate (theWorldView, aRefPoint.x(), aRefPoint.y(), aRefPoint.z()); + } + } +} + +// ======================================================================= +// function : Apply +// purpose : Apply transformation to bounding box of presentation. +// ======================================================================= +template +void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + Bnd_Box& theBoundingBox) const +{ + T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + + theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + + typename BVH_Box::BVH_VecNt aMin (aXmin, aYmin, aZmin, static_cast (1.0)); + typename BVH_Box::BVH_VecNt aMax (aXmax, aYmax, aZmax, static_cast (1.0)); + BVH_Box aBBox (aMin, aMax); + + Apply (theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox); + + theBoundingBox = Bnd_Box(); + theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(), + aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z()); +} + +// ======================================================================= +// function : Apply +// purpose : Apply transformation to bounding box of presentation. +// ======================================================================= +template +void Graphic3d_TransformPers::Apply (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + BVH_Box& theBoundingBox) const +{ + NCollection_Mat4 aTPers = Compute (theProjection, theWorldView, theViewportWidth, theViewportHeight); + + if (aTPers.IsIdentity()) + { + return; + } + + const typename BVH_Box::BVH_VecNt& aMin = theBoundingBox.CornerMin(); + const typename BVH_Box::BVH_VecNt& aMax = theBoundingBox.CornerMax(); + + typename BVH_Box::BVH_VecNt anArrayOfCorners[8]; + anArrayOfCorners[0] = typename BVH_Box::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast (1.0)); + anArrayOfCorners[1] = typename BVH_Box::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast (1.0)); + anArrayOfCorners[2] = typename BVH_Box::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast (1.0)); + anArrayOfCorners[3] = typename BVH_Box::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast (1.0)); + anArrayOfCorners[4] = typename BVH_Box::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast (1.0)); + anArrayOfCorners[5] = typename BVH_Box::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast (1.0)); + anArrayOfCorners[6] = typename BVH_Box::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast (1.0)); + anArrayOfCorners[7] = typename BVH_Box::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast (1.0)); + + theBoundingBox.Clear(); + for (Standard_Integer anIt = 0; anIt < 8; ++anIt) + { + typename BVH_Box::BVH_VecNt& aCorner = anArrayOfCorners[anIt]; + aCorner = aTPers * aCorner; + aCorner /= aCorner.w(); + theBoundingBox.Add (aCorner); + } +} + +// ======================================================================= +// function : Compute +// purpose : Compute transformation. +// ======================================================================= +template +NCollection_Mat4 Graphic3d_TransformPers::Compute (const NCollection_Mat4& theProjection, + const NCollection_Mat4& theWorldView, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) const +{ + if (Flags == Graphic3d_TMF_None) + { + return NCollection_Mat4(); + } + + NCollection_Mat4 anUnviewMat; + + if (!(theProjection * theWorldView).Inverted (anUnviewMat)) + { + return NCollection_Mat4(); + } + + NCollection_Mat4 aProjection (theProjection); + NCollection_Mat4 aWorldView (theWorldView); + + Apply (aProjection, aWorldView, theViewportWidth, theViewportHeight); + + return anUnviewMat * (aProjection * aWorldView); +} + +#endif // _Graphic3d_TransformPers_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TransformUtils.hxx b/src/Graphic3d/Graphic3d_TransformUtils.hxx new file mode 100644 index 0000000000..f2f4c7c391 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TransformUtils.hxx @@ -0,0 +1,452 @@ +// Created on: 2015-06-18 +// Copyright (c) 2015 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 _Graphic3d_TransformUtils_HeaderFile +#define _Graphic3d_TransformUtils_HeaderFile + +#include +#include // M_PI + +//! Helper class that implements transformation matrix functionality. +namespace Graphic3d_TransformUtils +{ + template struct MatrixType {}; + + template<> struct MatrixType { typedef Graphic3d_Mat4d Mat4; }; + + template<> struct MatrixType { typedef Graphic3d_Mat4 Mat4; }; + + template struct VectorType {}; + + template<> struct VectorType { + typedef Graphic3d_Vec2d Vec2; + typedef Graphic3d_Vec3d Vec3; + typedef Graphic3d_Vec4d Vec4; + }; + + template<> struct VectorType { + typedef Graphic3d_Vec2 Vec2; + typedef Graphic3d_Vec3 Vec3; + typedef Graphic3d_Vec4 Vec4; + }; + + //! Constructs a 3D orthographic projection matrix. + template + static void Ortho (typename MatrixType::Mat4& theOut, + const T theLeft, + const T theRight, + const T theBottom, + const T theTop, + const T theZNear, + const T theZFar); + + //! Constructs a 2D orthographic projection matrix. + template + static void Ortho2D (typename MatrixType::Mat4& theOut, + const T theLeft, + const T theRight, + const T theBottom, + const T theTop); + + //! Maps object coordinates to window coordinates. + template + static Standard_Boolean Project (const T theObjX, + const T theObjY, + const T theObjZ, + const typename MatrixType::Mat4& theModViewMat, + const typename MatrixType::Mat4& theProjectMat, + const Standard_Integer theViewport[4], + T& theWinX, + T& theWinY, + T& theWinZ); + + //! Maps window coordinates to object coordinates. + template + static Standard_Boolean UnProject (const T theWinX, + const T theWinY, + const T theWinZ, + const typename MatrixType::Mat4& theModViewMat, + const typename MatrixType::Mat4& theProjectMat, + const Standard_Integer theViewport[4], + T& theObjX, + T& theObjY, + T& theObjZ); + + //! Constructs a 4x4 rotation matrix. + template + static void ConstructRotate (typename MatrixType::Mat4& theOut, + T theA, + T theX, + T theY, + T theZ); + + //! Constructs a 4x4 rotation matrix. + template + static void Rotate (typename MatrixType::Mat4& theOut, + T theA, + T theX, + T theY, + T theZ); + + //! Constructs a 4x4 scaling matrix. + template + static void Scale (typename MatrixType::Mat4& theOut, + T theX, + T theY, + T theZ); + + //! Constructs a 4x4 translation matrix. + template + static void Translate (typename MatrixType::Mat4& theOut, + T theX, + T theY, + T theZ); +} + +// ======================================================================= +// function : Rotate +// purpose : Constructs a 4x4 rotation matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::Rotate (typename MatrixType::Mat4& theOut, + T theA, + T theX, + T theY, + T theZ) +{ + typename MatrixType::Mat4 aMat; + ConstructRotate (aMat, theA, theX, theY, theZ); + theOut = theOut * aMat; +} + +// ======================================================================= +// function : Translate +// purpose : Constructs a 4x4 translation matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::Translate (typename MatrixType::Mat4& theOut, + T theX, + T theY, + T theZ) +{ + theOut.ChangeValue (0, 3) = theOut.GetValue (0, 0) * theX + + theOut.GetValue (0, 1) * theY + + theOut.GetValue (0, 2) * theZ + + theOut.GetValue (0, 3); + + theOut.ChangeValue (1, 3) = theOut.GetValue (1, 0) * theX + + theOut.GetValue (1, 1) * theY + + theOut.GetValue (1, 2) * theZ + + theOut.GetValue (1, 3); + + theOut.ChangeValue (2, 3) = theOut.GetValue (2, 0) * theX + + theOut.GetValue (2, 1) * theY + + theOut.GetValue (2, 2) * theZ + + theOut.GetValue (2, 3); + + theOut.ChangeValue (3, 3) = theOut.GetValue (3, 0) * theX + + theOut.GetValue (3, 1) * theY + + theOut.GetValue (3, 2) * theZ + + theOut.GetValue (3, 3); +} + +// ======================================================================= +// function : Scale +// purpose : Constructs a 4x4 scaling matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::Scale (typename MatrixType::Mat4& theOut, + T theX, + T theY, + T theZ) +{ + theOut.ChangeValue (0, 0) *= theX; + theOut.ChangeValue (1, 0) *= theX; + theOut.ChangeValue (2, 0) *= theX; + theOut.ChangeValue (3, 0) *= theX; + + theOut.ChangeValue (0, 1) *= theY; + theOut.ChangeValue (1, 1) *= theY; + theOut.ChangeValue (2, 1) *= theY; + theOut.ChangeValue (3, 1) *= theY; + + theOut.ChangeValue (0, 2) *= theZ; + theOut.ChangeValue (1, 2) *= theZ; + theOut.ChangeValue (2, 2) *= theZ; + theOut.ChangeValue (3, 2) *= theZ; +} + +// ======================================================================= +// function : ConstructRotate +// purpose : Constructs a 4x4 rotation matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::ConstructRotate (typename MatrixType::Mat4& theOut, + T theA, + T theX, + T theY, + T theZ) +{ + const T aSin = std::sin (theA * static_cast (M_PI / 180.0)); + const T aCos = std::cos (theA * static_cast (M_PI / 180.0)); + + const Standard_Boolean isOnlyX = (theX != static_cast (0.0)) + && (theY == static_cast (0.0)) + && (theZ == static_cast (0.0)); + + const Standard_Boolean isOnlyY = (theX == static_cast (0.0)) + && (theY != static_cast (0.0)) + && (theZ == static_cast (0.0)); + + const Standard_Boolean isOnlyZ = (theX == static_cast (0.0)) + && (theY == static_cast (0.0)) + && (theZ != static_cast (0.0)); + + if (isOnlyX) // Rotation only around X. + { + theOut.SetValue (1, 1, aCos); + theOut.SetValue (2, 2, aCos); + + if (theX < static_cast (0.0)) + { + theOut.SetValue (1, 2, aSin); + theOut.SetValue (2, 1, -aSin); + } + else + { + theOut.SetValue (1, 2, -aSin); + theOut.SetValue (2, 1, aSin); + } + + return; + } + else if (isOnlyY) // Rotation only around Y. + { + theOut.SetValue (0, 0, aCos); + theOut.SetValue (2, 2, aCos); + + if (theY < static_cast (0.0)) + { + theOut.SetValue (0, 2, -aSin); + theOut.SetValue (2, 0, aSin); + } + else + { + theOut.SetValue (0, 2, aSin); + theOut.SetValue (2, 0, -aSin); + } + + return; + } + else if (isOnlyZ) // Rotation only around Z. + { + theOut.SetValue (0, 0, aCos); + theOut.SetValue (1, 1, aCos); + + if (theZ < static_cast (0.0)) + { + theOut.SetValue (0, 1, aSin); + theOut.SetValue (1, 0, -aSin); + } + else + { + theOut.SetValue (0, 1, -aSin); + theOut.SetValue (1, 0, aSin); + } + + return; + } + + T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ); + + if (aNorm <= static_cast (1.0e-4)) + { + return; // Negligible rotation. + } + + aNorm = static_cast (1.0) / aNorm; + + theX *= aNorm; + theY *= aNorm; + theZ *= aNorm; + + const T aXX = theX * theX; + const T aYY = theY * theY; + const T aZZ = theZ * theZ; + const T aXY = theX * theY; + const T aYZ = theY * theZ; + const T aZX = theZ * theX; + const T aSinX = theX * aSin; + const T aSinY = theY * aSin; + const T aSinZ = theZ * aSin; + + const T aOneMinusCos = static_cast (1.0) - aCos; + + theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos); + theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ); + theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY); + + theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ); + theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos); + theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX); + + theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY); + theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX); + theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos); +} + +// ======================================================================= +// function : Ortho +// purpose : Constructs a 3D orthographic projection matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::Ortho (typename MatrixType::Mat4& theOut, + const T theLeft, + const T theRight, + const T theBottom, + const T theTop, + const T theZNear, + const T theZFar) +{ + theOut.InitIdentity(); + + T* aData = theOut.ChangeData(); + + const T anInvDx = static_cast (1.0) / (theRight - theLeft); + const T anInvDy = static_cast (1.0) / (theTop - theBottom); + const T anInvDz = static_cast (1.0) / (theZFar - theZNear); + + aData[0] = static_cast ( 2.0) * anInvDx; + aData[5] = static_cast ( 2.0) * anInvDy; + aData[10] = static_cast (-2.0) * anInvDz; + + aData[12] = -(theRight + theLeft) * anInvDx; + aData[13] = -(theTop + theBottom) * anInvDy; + aData[14] = -(theZFar + theZNear) * anInvDz; +} + +// ======================================================================= +// function : Ortho2D +// purpose : Constructs a 2D orthographic projection matrix +// ======================================================================= +template +void Graphic3d_TransformUtils::Ortho2D (typename MatrixType::Mat4& theOut, + const T theLeft, + const T theRight, + const T theBottom, + const T theTop) +{ + Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast (-1.0), static_cast (1.0)); +} + +// ======================================================================= +// function : Project +// purpose : Maps object coordinates to window coordinates +// ======================================================================= +template +static Standard_Boolean Graphic3d_TransformUtils::Project (const T theObjX, + const T theObjY, + const T theObjZ, + const typename MatrixType::Mat4& theModViewMat, + const typename MatrixType::Mat4& theProjectMat, + const Standard_Integer theViewport[4], + T& theWinX, + T& theWinY, + T& theWinZ) +{ + typename VectorType::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast (1.0)); + + typename VectorType::Vec4 anOut = theProjectMat * (theModViewMat * anIn); + + if (anOut.w() == static_cast (0.0)) + { + return Standard_False; + } + + anOut.w() = static_cast (1.0) / anOut.w(); + + anOut.x() *= anOut.w(); + anOut.y() *= anOut.w(); + anOut.z() *= anOut.w(); + + // Map x, y and z to range 0-1. + anOut.x() = anOut.x() * static_cast (0.5) + static_cast (0.5); + anOut.y() = anOut.y() * static_cast (0.5) + static_cast (0.5); + anOut.z() = anOut.z() * static_cast (0.5) + static_cast (0.5); + + // Map x,y to viewport. + anOut.x() = anOut.x() * theViewport[2] + theViewport[0]; + anOut.y() = anOut.y() * theViewport[3] + theViewport[1]; + + theWinX = anOut.x(); + theWinY = anOut.y(); + theWinZ = anOut.z(); + + return Standard_True; +} + +// ======================================================================= +// function : UnProject +// purpose : Maps window coordinates to object coordinates +// ======================================================================= +template +static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T theWinX, + const T theWinY, + const T theWinZ, + const typename MatrixType::Mat4& theModViewMat, + const typename MatrixType::Mat4& theProjectMat, + const Standard_Integer theViewport[4], + T& theObjX, + T& theObjY, + T& theObjZ) +{ + typename MatrixType::Mat4 anUnviewMat; + + if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat)) + { + return Standard_False; + } + + typename VectorType::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast (1.0)); + + // Map x and y from window coordinates. + anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2]; + anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3]; + + // Map to range -1 to 1. + anIn.x() = anIn.x() * static_cast (2.0) - static_cast (1.0); + anIn.y() = anIn.y() * static_cast (2.0) - static_cast (1.0); + anIn.z() = anIn.z() * static_cast (2.0) - static_cast (1.0); + + typename VectorType::Vec4 anOut = anUnviewMat * anIn; + + if (anOut.w() == static_cast (0.0)) + { + return Standard_False; + } + + anOut.w() = static_cast (1.0) / anOut.w(); + + anOut.x() *= anOut.w(); + anOut.y() *= anOut.w(); + anOut.z() *= anOut.w(); + + theObjX = anOut.x(); + theObjY = anOut.y(); + theObjZ = anOut.z(); + + return Standard_True; +} + +#endif // _Graphic3d_TransformUtils_HeaderFile diff --git a/src/Graphic3d/Graphic3d_WorldViewProjState.hxx b/src/Graphic3d/Graphic3d_WorldViewProjState.hxx new file mode 100644 index 0000000000..03713cb8da --- /dev/null +++ b/src/Graphic3d/Graphic3d_WorldViewProjState.hxx @@ -0,0 +1,161 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 _Graphic3d_WorldViewProjState_HeaderFile +#define _Graphic3d_WorldViewProjState_HeaderFile + +#include +#include + +//! Helper class for keeping reference on world-view-projection state. +//! Helpful for synchronizing state of WVP dependent data structures. +class Graphic3d_WorldViewProjState +{ +public: + + //! Default constructor. + Graphic3d_WorldViewProjState() + { + Reset(); + } + + //! Constructor for custom projector type. + //! @param theProjectionState [in] the projection state. + //! @param theWorldViewState [in] the world view state. + //! @param theCamera [in] the pointer to the class supplying projection and + //! world view matrices (camera). + Graphic3d_WorldViewProjState (const Standard_Size theProjectionState, + const Standard_Size theWorldViewState, + const Standard_Transient* theCamera = NULL) + { + Initialize (theProjectionState, theWorldViewState, theCamera); + } + +public: + + //! Check state validity. + //! @return true if state is set. + Standard_Boolean IsValid() + { + return myIsValid; + } + + //! Invalidate world view projection state. + void Reset() + { + myIsValid = Standard_False; + myCamera = NULL; + myProjectionState = 0; + myWorldViewState = 0; + } + + //! Initialize world view projection state. + void Initialize (const Standard_Size theProjectionState, + const Standard_Size theWorldViewState, + const Standard_Transient* theCamera = NULL) + { + myIsValid = Standard_True; + myCamera = const_cast (theCamera); + myProjectionState = theProjectionState; + myWorldViewState = theWorldViewState; + } + + //! Initialize world view projection state. + void Initialize (const Standard_Transient* theCamera = NULL) + { + myIsValid = Standard_True; + myCamera = const_cast (theCamera); + myProjectionState = 0; + myWorldViewState = 0; + } + +public: + + //! @return projection state counter. + Standard_Size& ProjectionState() + { + return myProjectionState; + } + + //! @return world view state counter. + Standard_Size& WorldViewState() + { + return myWorldViewState; + } + +public: + + //! Compare projection with other state. + //! @return true when the projection of the given camera state differs from this one. + Standard_Boolean IsProjectionChanged (const Graphic3d_WorldViewProjState& theState) + { + return myIsValid != theState.myIsValid + || myCamera != theState.myCamera + || myProjectionState != theState.myProjectionState; + } + + //! Compare world view transformation with other state. + //! @return true when the orientation of the given camera state differs from this one. + Standard_Boolean IsWorldViewChanged (const Graphic3d_WorldViewProjState& theState) + { + return myIsValid != theState.myIsValid + || myCamera != theState.myCamera + || myWorldViewState != theState.myWorldViewState; + } + + //! Compare with other world view projection state. + //! @return true when the projection of the given camera state differs from this one. + Standard_Boolean IsChanged (const Graphic3d_WorldViewProjState& theState) + { + return *this != theState; + } + +public: + + //! Compare with other world view projection state. + //! @return true if the other projection state is different to this one. + bool operator != (const Graphic3d_WorldViewProjState& theOther) const + { + return !(*this == theOther); + } + + //! Compare with other world view projection state. + //! @return true if the other projection state is equal to this one. + bool operator == (const Graphic3d_WorldViewProjState& theOther) const + { + return myIsValid == theOther.myIsValid + && myCamera == theOther.myCamera + && myProjectionState == theOther.myProjectionState + && myWorldViewState == theOther.myWorldViewState; + } + + //! Copy world view projection state. + void operator = (const Graphic3d_WorldViewProjState& theOther) + { + myIsValid = theOther.myIsValid; + myCamera = theOther.myCamera; + myProjectionState = theOther.myProjectionState; + myWorldViewState = theOther.myWorldViewState; + } + +private: + + Standard_Boolean myIsValid; + Standard_Transient* myCamera; + Standard_Size myProjectionState; + Standard_Size myWorldViewState; +}; + +#endif diff --git a/src/InterfaceGraphic/InterfaceGraphic_telem.hxx b/src/InterfaceGraphic/InterfaceGraphic_telem.hxx index db4acbf09f..0f4c3ddb19 100644 --- a/src/InterfaceGraphic/InterfaceGraphic_telem.hxx +++ b/src/InterfaceGraphic/InterfaceGraphic_telem.hxx @@ -85,14 +85,4 @@ struct TEL_POFFSET_PARAM }; typedef TEL_POFFSET_PARAM* tel_poffset_param; -struct TEL_TRANSFORM_PERSISTENCE -{ - int mode; - float pointX; - float pointY; - float pointZ; - DEFINE_STANDARD_ALLOC -}; -typedef TEL_TRANSFORM_PERSISTENCE* tel_transform_persistence; - #endif /* INTERFACEGRAPHIC_TELEM_H */ diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index de9014dd12..0d0742eabd 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -70,7 +70,6 @@ OpenGl_Resource.hxx OpenGl_Resource.cxx OpenGl_telem_util.hxx OpenGl_telem_util.cxx -OpenGl_transform_persistence.hxx OpenGl_Font.hxx OpenGl_Font.cxx OpenGl_tgl_funcs.hxx @@ -152,11 +151,13 @@ OpenGl_BVHTreeSelector.hxx OpenGl_BVHTreeSelector.cxx OpenGl_BVHClipPrimitiveSet.cxx OpenGl_BVHClipPrimitiveSet.hxx +OpenGl_BVHClipPrimitiveTrsfPersSet.cxx +OpenGl_BVHClipPrimitiveTrsfPersSet.hxx OpenGl_ArbTexBindless.hxx Handle_OpenGl_Sampler.hxx OpenGl_Sampler.hxx OpenGl_Sampler.cxx -OpenGl_Utils.hxx +OpenGl_MatrixState.hxx OpenGl_Quadric.hxx OpenGl_Quadric.cxx OpenGl_Cylinder.hxx diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx index cda8413d10..a9eb4c759a 100644 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx @@ -41,7 +41,7 @@ Standard_Integer OpenGl_BVHClipPrimitiveSet::Size() const // ======================================================================= Graphic3d_BndBox4f OpenGl_BVHClipPrimitiveSet::Box (const Standard_Integer theIdx) const { - return myStructs (theIdx + 1)->BoundingBox(); + return myStructs.FindKey (theIdx + 1)->BoundingBox(); } // ======================================================================= @@ -51,12 +51,10 @@ Graphic3d_BndBox4f OpenGl_BVHClipPrimitiveSet::Box (const Standard_Integer theId Standard_ShortReal OpenGl_BVHClipPrimitiveSet::Center (const Standard_Integer theIdx, const Standard_Integer theAxis) const { - Graphic3d_BndBox4f aBndBox = myStructs (theIdx + 1)->BoundingBox(); - Standard_ShortReal aCenter = theAxis == 0 ? (aBndBox.CornerMin().x() + aBndBox.CornerMax().x()) * 0.5f - : (theAxis == 1 ? (aBndBox.CornerMin().y() + aBndBox.CornerMax().y()) * 0.5f - : (theAxis == 2 ? (aBndBox.CornerMin().z() + aBndBox.CornerMax().z()) * 0.5f - : (aBndBox.CornerMin().w() + aBndBox.CornerMax().w()) * 0.5f)); - return aCenter; + Graphic3d_BndBox4f aBndBox = myStructs.FindKey (theIdx + 1)->BoundingBox(); + + return (aBndBox.CornerMin()[theAxis] + + aBndBox.CornerMax()[theAxis]) * 0.5f; } // ======================================================================= @@ -68,57 +66,47 @@ void OpenGl_BVHClipPrimitiveSet::Swap (const Standard_Integer theIdx1, { const OpenGl_Structure* aStruct1 = myStructs (theIdx1 + 1); const OpenGl_Structure* aStruct2 = myStructs (theIdx2 + 1); - myStructs.ChangeValue (theIdx1 + 1) = aStruct2; - myStructs.ChangeValue (theIdx2 + 1) = aStruct1; + myStructs.Substitute (theIdx2 + 1, NULL); + myStructs.Substitute (theIdx1 + 1, aStruct2); + myStructs.Substitute (theIdx2 + 1, aStruct1); } // ======================================================================= -// function : Assign +// function : Add // purpose : // ======================================================================= -void OpenGl_BVHClipPrimitiveSet::Assign (const OpenGl_ArrayOfStructure& theStructs) +Standard_Boolean OpenGl_BVHClipPrimitiveSet::Add (const OpenGl_Structure* theStruct) { - myStructs.Clear(); + const Standard_Integer aSize = myStructs.Size(); - const Standard_Integer aNbPriorities = theStructs.Length(); - for (Standard_Integer aPriorityIdx = 0; aPriorityIdx < aNbPriorities; ++aPriorityIdx) + if (myStructs.Add (theStruct) > aSize) // new structure? { - for (OpenGl_SequenceOfStructure::Iterator aStructIter (theStructs (aPriorityIdx)); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - if (!aStruct->IsAlwaysRendered()) - myStructs.Append (aStruct); - } - } + MarkDirty(); - MarkDirty(); -} + return Standard_True; + } -// ======================================================================= -// function : Add -// purpose : -// ======================================================================= -void OpenGl_BVHClipPrimitiveSet::Add (const OpenGl_Structure* theStruct) -{ - myStructs.Append (theStruct); - MarkDirty(); + return Standard_False; } // ======================================================================= // function : Remove // purpose : // ======================================================================= -void OpenGl_BVHClipPrimitiveSet::Remove (const OpenGl_Structure* theStruct) +Standard_Boolean OpenGl_BVHClipPrimitiveSet::Remove (const OpenGl_Structure* theStruct) { - for (Standard_Integer anIdx = 1; anIdx <= myStructs.Size(); ++anIdx) + const Standard_Integer anIndex = myStructs.FindIndex (theStruct); + + if (anIndex != 0) { - if (myStructs (anIdx) == theStruct) - { - myStructs.Remove (anIdx); - MarkDirty(); - break; - } + Swap (anIndex - 1, Size() - 1); + myStructs.RemoveLast(); + MarkDirty(); + + return Standard_True; } + + return Standard_False; } // ======================================================================= @@ -137,5 +125,5 @@ void OpenGl_BVHClipPrimitiveSet::Clear() // ======================================================================= const OpenGl_Structure* OpenGl_BVHClipPrimitiveSet::GetStructureById (Standard_Integer theId) { - return myStructs (theId + 1); + return myStructs.FindKey (theId + 1); } diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx index bf3b607f4e..a525ca7ddc 100644 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx @@ -17,14 +17,12 @@ #define _OpenGl_BVHClipPrimitiveSet_HeaderFile #include -#include +#include #include #include #include -typedef NCollection_Array1 OpenGl_ArrayOfStructure; - //! Set of OpenGl_Structures for building BVH tree. class OpenGl_BVHClipPrimitiveSet : public BVH_PrimitiveSet { @@ -51,15 +49,13 @@ public: virtual void Swap (const Standard_Integer theIdx1, const Standard_Integer theIdx2); - //! Replaces the set by the given array taking into account - //! if each structure is cullable or not. - void Assign (const OpenGl_ArrayOfStructure& theStructs); - //! Adds structure theStruct to the set. - void Add (const OpenGl_Structure* theStruct); + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_Boolean Add (const OpenGl_Structure* theStruct); //! Removes the given OpenGl_Structure from the set. - void Remove (const OpenGl_Structure* theStruct); + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_Boolean Remove (const OpenGl_Structure* theStruct); //! Cleans the whole primitive set. void Clear(); @@ -69,7 +65,7 @@ public: private: - NCollection_Sequence myStructs; //!< Sequence of structures + NCollection_IndexedMap myStructs; //!< Sequence of structures }; diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx new file mode 100644 index 0000000000..07106c03e7 --- /dev/null +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx @@ -0,0 +1,179 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 +#include + +// ======================================================================= +// function : OpenGl_BVHClipPrimitiveTrsfPersSet +// purpose : +// ======================================================================= +OpenGl_BVHClipPrimitiveTrsfPersSet::OpenGl_BVHClipPrimitiveTrsfPersSet() +: myIsDirty (Standard_False), + myBVH (new BVH_Tree()) +{ + myBuilder = new BVH_LinearBuilder (1, 32); +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +Standard_Integer OpenGl_BVHClipPrimitiveTrsfPersSet::Size() const +{ + return myStructs.Size(); +} + +// ======================================================================= +// function : Box +// purpose : +// ======================================================================= +Graphic3d_BndBox4f OpenGl_BVHClipPrimitiveTrsfPersSet::Box (const Standard_Integer theIdx) const +{ + return *myStructBoxes (theIdx + 1); +} + +// ======================================================================= +// function : Center +// purpose : +// ======================================================================= +Standard_ShortReal OpenGl_BVHClipPrimitiveTrsfPersSet::Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const +{ + const Graphic3d_BndBox4f& aBndBox = *myStructBoxes (theIdx + 1); + + return (aBndBox.CornerMin()[theAxis] + aBndBox.CornerMax()[theAxis]) * 0.5f; +} + +// ======================================================================= +// function : Swap +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveTrsfPersSet::Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) +{ + const Standard_Integer aStructIdx1 = theIdx1 + 1; + const Standard_Integer aStructIdx2 = theIdx2 + 1; + + const OpenGl_Structure* aStruct1 = myStructs.FindKey (aStructIdx1); + const OpenGl_Structure* aStruct2 = myStructs.FindKey (aStructIdx2); + myStructs.Substitute (aStructIdx2, NULL); + myStructs.Substitute (aStructIdx1, aStruct2); + myStructs.Substitute (aStructIdx2, aStruct1); + + const HBndBox4f aBox1 = myStructBoxes.FindKey (aStructIdx1); + const HBndBox4f aBox2 = myStructBoxes.FindKey (aStructIdx2); + myStructBoxes.Substitute (aStructIdx2, EMPTY_BOX); + myStructBoxes.Substitute (aStructIdx1, aBox2); + myStructBoxes.Substitute (aStructIdx2, aBox1); +} + +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_BVHClipPrimitiveTrsfPersSet::Add (const OpenGl_Structure* theStruct) +{ + const Standard_Integer aSize = myStructs.Size(); + + if (myStructs.Add (theStruct) > aSize) // new structure? + { + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_BVHClipPrimitiveTrsfPersSet::Remove (const OpenGl_Structure* theStruct) +{ + const Standard_Integer anIndex = myStructs.FindIndex (theStruct); + + if (anIndex != 0) + { + Swap (anIndex - 1, Size() - 1); + myStructs.RemoveLast(); + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveTrsfPersSet::Clear() +{ + myStructs.Clear(); + MarkDirty(); +} + +// ======================================================================= +// function : GetStructureById +// purpose : +// ======================================================================= +const OpenGl_Structure* OpenGl_BVHClipPrimitiveTrsfPersSet::GetStructureById (Standard_Integer theId) +{ + return myStructs.FindKey (theId + 1); +} + +//======================================================================= +// function : BVH +// purpose : +//======================================================================= +const NCollection_Handle >& + OpenGl_BVHClipPrimitiveTrsfPersSet::BVH (const OpenGl_Mat4& theProjectionMatrix, + const OpenGl_Mat4& theWorldViewMatrix, + const Graphic3d_WorldViewProjState& theWVPState) +{ + if (!myIsDirty && (myStructBoxesState.IsValid() && !myStructBoxesState.IsChanged(theWVPState))) + { + return myBVH; + } + + myStructBoxes.ReSize (myStructs.Size()); + + for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Size(); ++aStructIdx) + { + const OpenGl_Structure* aStructure = myStructs (aStructIdx); + + HBndBox4f aBoundingBox = new Graphic3d_BndBox4f; + + if (aStructure->TransformPersistence.Flags && !(aStructure->TransformPersistence.Flags & Graphic3d_TMF_2d)) + { + *aBoundingBox = aStructure->BoundingBox(); + + aStructure->TransformPersistence.Apply (theProjectionMatrix, theWorldViewMatrix, 0, 0, *aBoundingBox); + } + + myStructBoxes.Add (aBoundingBox); + } + + myBuilder->Build (this, myBVH.operator->(), BVH_Set::Box()); + + myStructBoxesState = theWVPState; + myStructBoxes.Clear(); + myIsDirty = Standard_False; + + return myBVH; +} diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx new file mode 100644 index 0000000000..56dc317900 --- /dev/null +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx @@ -0,0 +1,108 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile +#define _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! Set of transformation persistent OpenGl_Structure for building BVH tree. +//! Provides built-in mechanism to invalidate tree when world view projection state changes. +//! Due to frequent invalidation of BVH tree the choice of BVH tree builder is made +//! in favor of BVH linear builder (quick rebuild). +class OpenGl_BVHClipPrimitiveTrsfPersSet : public BVH_Set +{ +private: + + typedef NCollection_Handle HBndBox4f; + + HBndBox4f EMPTY_BOX; + +public: + + //! Creates an empty primitive set for BVH clipping. + OpenGl_BVHClipPrimitiveTrsfPersSet(); + + //! Returns total number of structures. + virtual Standard_Integer Size() const Standard_OVERRIDE; + + //! Returns AABB of the structure. + virtual Graphic3d_BndBox4f Box (const Standard_Integer theIdx) const Standard_OVERRIDE; + + //! Calculates center of the AABB along given axis. + virtual Standard_ShortReal Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const Standard_OVERRIDE; + + //! Swaps structures with the given indices. + virtual void Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) Standard_OVERRIDE; + + //! Adds structure to the set. + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_Boolean Add (const OpenGl_Structure* theStruct); + + //! Removes the given structure from the set. + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_Boolean Remove (const OpenGl_Structure* theStruct); + + //! Cleans the whole primitive set. + void Clear(); + + //! Returns the structure corresponding to the given ID. + const OpenGl_Structure* GetStructureById (Standard_Integer theId); + + //! Marks object state as outdated (needs BVH rebuilding). + void MarkDirty() + { + myIsDirty = Standard_True; + } + + //! Returns BVH tree for the given world view projection (builds it if necessary). + const NCollection_Handle >& BVH (const OpenGl_Mat4& theProjectionMatrix, + const OpenGl_Mat4& theWorldViewMatrix, + const Graphic3d_WorldViewProjState& theWVPState); + +private: + + //! Marks internal object state as outdated. + Standard_Boolean myIsDirty; + + //! Constructed bottom-level BVH. + NCollection_Handle > myBVH; + + //! Builder for bottom-level BVH. + NCollection_Handle > myBuilder; + + //! Indexed map of structures. + NCollection_IndexedMap myStructs; + + //! Cached set of bounding boxes precomputed for transformation persistent selectable objects. + //! Cache exists only during computation of BVH Tree. Bounding boxes are world view projection + //! dependent and should by synchronized. + NCollection_IndexedMap myStructBoxes; + + //! State of world view projection used for generation of transformation persistence bounding boxes. + Graphic3d_WorldViewProjState myStructBoxesState; +}; + +#endif // _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx index cac526d811..07f5917636 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.cxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.cxx @@ -23,22 +23,27 @@ // purpose : // ======================================================================= OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() -: myIsProjectionParallel (Standard_True), - myProjectionState (0), - myModelViewState (0) +: myIsProjectionParallel (Standard_True) { // } // ======================================================================= -// function : SetClipVolume -// purpose : Retrieves view volume's planes equations and its vertices from projection and modelview matrices. +// function : SetViewVolume +// purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices. // ======================================================================= void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) { + if (myWorldViewProjState == theCamera->WorldViewProjState()) + { + return; + } + myIsProjectionParallel = theCamera->IsOrthographic(); - const OpenGl_Mat4& aProjMat = theCamera->ProjectionMatrixF(); - const OpenGl_Mat4& aModelMat = theCamera->OrientationMatrixF(); + + myProjectionMat = theCamera->ProjectionMatrixF(); + myWorldViewMat = theCamera->OrientationMatrixF(); + myWorldViewProjState = theCamera->WorldViewProjState(); Standard_ShortReal nLeft = 0.0f, nRight = 0.0f, nTop = 0.0f, nBottom = 0.0f; Standard_ShortReal fLeft = 0.0f, fRight = 0.0f, fTop = 0.0f, fBottom = 0.0f; @@ -46,32 +51,32 @@ void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theC if (!myIsProjectionParallel) { // handle perspective projection - aNear = aProjMat.GetValue (2, 3) / (- 1.0f + aProjMat.GetValue (2, 2)); - aFar = aProjMat.GetValue (2, 3) / ( 1.0f + aProjMat.GetValue (2, 2)); + aNear = myProjectionMat.GetValue (2, 3) / (- 1.0f + myProjectionMat.GetValue (2, 2)); + aFar = myProjectionMat.GetValue (2, 3) / ( 1.0f + myProjectionMat.GetValue (2, 2)); // Near plane - nLeft = aNear * (aProjMat.GetValue (0, 2) - 1.0f) / aProjMat.GetValue (0, 0); - nRight = aNear * (aProjMat.GetValue (0, 2) + 1.0f) / aProjMat.GetValue (0, 0); - nTop = aNear * (aProjMat.GetValue (1, 2) + 1.0f) / aProjMat.GetValue (1, 1); - nBottom = aNear * (aProjMat.GetValue (1, 2) - 1.0f) / aProjMat.GetValue (1, 1); + nLeft = aNear * (myProjectionMat.GetValue (0, 2) - 1.0f) / myProjectionMat.GetValue (0, 0); + nRight = aNear * (myProjectionMat.GetValue (0, 2) + 1.0f) / myProjectionMat.GetValue (0, 0); + nTop = aNear * (myProjectionMat.GetValue (1, 2) + 1.0f) / myProjectionMat.GetValue (1, 1); + nBottom = aNear * (myProjectionMat.GetValue (1, 2) - 1.0f) / myProjectionMat.GetValue (1, 1); // Far plane - fLeft = aFar * (aProjMat.GetValue (0, 2) - 1.0f) / aProjMat.GetValue (0, 0); - fRight = aFar * (aProjMat.GetValue (0, 2) + 1.0f) / aProjMat.GetValue (0, 0); - fTop = aFar * (aProjMat.GetValue (1, 2) + 1.0f) / aProjMat.GetValue (1, 1); - fBottom = aFar * (aProjMat.GetValue (1, 2) - 1.0f) / aProjMat.GetValue (1, 1); + fLeft = aFar * (myProjectionMat.GetValue (0, 2) - 1.0f) / myProjectionMat.GetValue (0, 0); + fRight = aFar * (myProjectionMat.GetValue (0, 2) + 1.0f) / myProjectionMat.GetValue (0, 0); + fTop = aFar * (myProjectionMat.GetValue (1, 2) + 1.0f) / myProjectionMat.GetValue (1, 1); + fBottom = aFar * (myProjectionMat.GetValue (1, 2) - 1.0f) / myProjectionMat.GetValue (1, 1); } else { // handle orthographic projection - aNear = (1.0f / aProjMat.GetValue (2, 2)) * (aProjMat.GetValue (2, 3) + 1.0f); - aFar = (1.0f / aProjMat.GetValue (2, 2)) * (aProjMat.GetValue (2, 3) - 1.0f); + aNear = (1.0f / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) + 1.0f); + aFar = (1.0f / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) - 1.0f); // Near plane - nLeft = ( 1.0f + aProjMat.GetValue (0, 3)) / (-aProjMat.GetValue (0, 0)); + nLeft = ( 1.0f + myProjectionMat.GetValue (0, 3)) / (-myProjectionMat.GetValue (0, 0)); fLeft = nLeft; - nRight = ( 1.0f - aProjMat.GetValue (0, 3)) / aProjMat.GetValue (0, 0); + nRight = ( 1.0f - myProjectionMat.GetValue (0, 3)) / myProjectionMat.GetValue (0, 0); fRight = nRight; - nTop = ( 1.0f - aProjMat.GetValue (1, 3)) / aProjMat.GetValue (1, 1); + nTop = ( 1.0f - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1); fTop = nTop; - nBottom = (-1.0f - aProjMat.GetValue (1, 3)) / aProjMat.GetValue (1, 1); + nBottom = (-1.0f - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1); fBottom = nBottom; } @@ -80,18 +85,18 @@ void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theC OpenGl_Vec4 aRightBottomNear (nRight, nBottom, -aNear, 1.0f), aLeftTopFar (fLeft, fTop, -aFar, 1.0f); OpenGl_Vec4 aRightTopNear (nRight, nTop, -aNear, 1.0f), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0f); - const OpenGl_Mat4 aViewProj = aModelMat * aProjMat; - OpenGl_Mat4 anInvModelView; - aModelMat.Inverted(anInvModelView); - - myClipVerts[ClipVert_LeftTopNear] = anInvModelView * aLeftTopNear; - myClipVerts[ClipVert_RightBottomFar] = anInvModelView * aRightBottomFar; - myClipVerts[ClipVert_LeftBottomNear] = anInvModelView * aLeftBottomNear; - myClipVerts[ClipVert_RightTopFar] = anInvModelView * aRightTopFar; - myClipVerts[ClipVert_RightBottomNear] = anInvModelView * aRightBottomNear; - myClipVerts[ClipVert_LeftTopFar] = anInvModelView * aLeftTopFar; - myClipVerts[ClipVert_RightTopNear] = anInvModelView * aRightTopNear; - myClipVerts[ClipVert_LeftBottomFar] = anInvModelView * aLeftBottomFar; + const OpenGl_Mat4 aViewProj = myWorldViewMat * myProjectionMat; + OpenGl_Mat4 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); diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx index 96183ce4ca..c111c21233 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.hxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.hxx @@ -17,7 +17,7 @@ #define _OpenGl_BVHTreeSelector_HeaderFile #include - +#include #include //! BVHTreeSelector class provides a possibility to store parameters of view volume, @@ -30,7 +30,7 @@ public: //! Creates an empty selector object with parallel projection type by default. Standard_EXPORT OpenGl_BVHTreeSelector(); - //! Retrieves view volume's planes equations and its vertices from projection and modelview matrices. + //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices. Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); //! Detects if AABB overlaps view volume using separating axis theorem (SAT). @@ -44,17 +44,23 @@ public: //! Must be called at the beginning of each BVH tree traverse loop. Standard_EXPORT void CacheClipPtsProjections(); - //! Returnes the state of projection matrix previously saved in selector. - Standard_EXPORT const Standard_Size ProjectionState() { return myProjectionState; } - - //! Returnes the link for changing the state of projection matrix. - Standard_EXPORT Standard_Size& ChangeProjectionState() { return myProjectionState; } + //! Returns current projection matrix. + const OpenGl_Mat4& ProjectionMatrix() const + { + return myProjectionMat; + } - //! Returnes the state of model view matrix previously saved in selector. - Standard_EXPORT const Standard_Size ModelViewState() { return myModelViewState; } + //! Returns current world view transformation matrix. + const OpenGl_Mat4& WorldViewMatrix() const + { + return myWorldViewMat; + } - //! Returnes the link for changing the state of model view matrix. - Standard_EXPORT Standard_Size& ChangeModelViewState() { return myModelViewState; } + //! Returns state of current world view projection transformation matrices. + const Graphic3d_WorldViewProjState& WorldViewProjState() const + { + return myWorldViewProjState; + } protected: @@ -94,8 +100,8 @@ protected: protected: - OpenGl_Vec4 myClipPlanes[PlanesNB]; //!< Plane equations - OpenGl_Vec4 myClipVerts[ClipVerticesNB]; //!< Vertices + OpenGl_Vec4 myClipPlanes[PlanesNB]; //!< Plane equations + OpenGl_Vec4 myClipVerts[ClipVerticesNB]; //!< Vertices // for caching clip points projections onto viewing area normals once per traverse // ORDER: TOP, BOTTOM, LEFT, RIGHT, NEAR, FAR @@ -104,14 +110,15 @@ protected: // for caching clip points projections onto AABB normals once per traverse // ORDER: E0, E1, E2 - Standard_ShortReal myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB - Standard_ShortReal myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB + Standard_ShortReal myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB + Standard_ShortReal myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB - Standard_Boolean myIsProjectionParallel; + Standard_Boolean myIsProjectionParallel; - Standard_Size myProjectionState; //! Caches the state of projection matrix to prevent unnecessary updates. - Standard_Size myModelViewState; //! Caches the state of model view matrix to prevent unnecessary updates. + OpenGl_Mat4 myProjectionMat; + OpenGl_Mat4 myWorldViewMat; + Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices. }; #endif // _OpenGl_BVHTreeSelector_HeaderFile diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 47caab9b13..4511207290 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include //! Forward declarations #if defined(__APPLE__) @@ -681,9 +681,9 @@ private: //! @name fields tracking current state public: - OpenGl_Utils::MatrixState ModelWorldState; //!< state of orientation matrix - OpenGl_Utils::MatrixState WorldViewState; //!< state of orientation matrix - OpenGl_Utils::MatrixState ProjectionState; //!< state of projection matrix + OpenGl_MatrixState ModelWorldState; //!< state of orientation matrix + OpenGl_MatrixState WorldViewState; //!< state of orientation matrix + OpenGl_MatrixState ProjectionState; //!< state of projection matrix private: diff --git a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx index 5f5523ca1c..ecfcef3b3f 100755 --- a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx +++ b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx @@ -14,7 +14,6 @@ // commercial license or contractual agreement. #include -#include #include #include #include @@ -27,9 +26,10 @@ #include #include +#include +#include #include #include -#include #include #include #include @@ -129,23 +129,23 @@ Standard_ShortReal OpenGl_GraduatedTrihedron::getNormal (const Handle(OpenGl_Con aProjMatrix .Convert (theContext->ProjectionState.Current()); OpenGl_Vec3 aPoint1, aPoint2, aPoint3; - OpenGl_Utils::UnProject ((Standard_ShortReal) aViewport[0], - (Standard_ShortReal) aViewport[1], - 0.0f, - aModelMatrix, aProjMatrix, aViewport, - aPoint1.x(), aPoint1.y(), aPoint1.z()); - - OpenGl_Utils::UnProject ((Standard_ShortReal) (aViewport[0] + aViewport[2]), - (Standard_ShortReal) aViewport[1], - 0.0f, - aModelMatrix, aProjMatrix, aViewport, - aPoint2.x(), aPoint2.y(), aPoint2.z()); - - OpenGl_Utils::UnProject ((Standard_ShortReal) aViewport[0], - (Standard_ShortReal) (aViewport[1] + aViewport[3]), - 0.0f, - aModelMatrix, aProjMatrix, aViewport, - aPoint3.x(), aPoint3.y(), aPoint3.z()); + Graphic3d_TransformUtils::UnProject ((Standard_ShortReal) aViewport[0], + (Standard_ShortReal) aViewport[1], + 0.0f, + aModelMatrix, aProjMatrix, aViewport, + aPoint1.x(), aPoint1.y(), aPoint1.z()); + + Graphic3d_TransformUtils::UnProject ((Standard_ShortReal) (aViewport[0] + aViewport[2]), + (Standard_ShortReal) aViewport[1], + 0.0f, + aModelMatrix, aProjMatrix, aViewport, + aPoint2.x(), aPoint2.y(), aPoint2.z()); + + Graphic3d_TransformUtils::UnProject ((Standard_ShortReal) aViewport[0], + (Standard_ShortReal) (aViewport[1] + aViewport[3]), + 0.0f, + aModelMatrix, aProjMatrix, aViewport, + aPoint3.x(), aPoint3.y(), aPoint3.z()); const OpenGl_Vec3 aD1 = aPoint3 - aPoint1; const OpenGl_Vec3 aD2 = aPoint2 - aPoint1; @@ -329,7 +329,7 @@ void OpenGl_GraduatedTrihedron::renderLine (const OpenGl_PrimitiveArray& theL { const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); OpenGl_Mat4 aMat (theMat); - OpenGl_Utils::Translate (aMat, theXt, theYt, theZt); + Graphic3d_TransformUtils::Translate (aMat, theXt, theYt, theZt); aContext->WorldViewState.SetCurrent (aMat); aContext->ApplyWorldViewMatrix(); theLine.Render (theWorkspace); @@ -369,14 +369,14 @@ void OpenGl_GraduatedTrihedron::renderGridPlane (const Handle(OpenGl_Workspace)& aStart.ChangeData()[anIndex] = myMin.GetData()[anIndex]; } - OpenGl_Utils::Translate (aMat, aStart.x(), aStart.y(), aStart.z()); + Graphic3d_TransformUtils::Translate (aMat, aStart.x(), aStart.y(), aStart.z()); aContext->WorldViewState.SetCurrent (aMat); aContext->ApplyWorldViewMatrix(); const OpenGl_Vec3 aStepVec (myAxes[theIndex].Direction * aStep); for (Standard_Integer anIt = myData.ToDrawAxes() ? 1 : 0; anIt < aCurAspect.TickmarksNumber(); ++anIt) { - OpenGl_Utils::Translate (aMat, aStepVec.x(), aStepVec.y(), aStepVec.z()); + Graphic3d_TransformUtils::Translate (aMat, aStepVec.x(), aStepVec.y(), aStepVec.z()); aContext->WorldViewState.SetCurrent (aMat); aContext->ApplyWorldViewMatrix(); anAxis.Line.Render (theWorkspace); @@ -402,56 +402,57 @@ void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theW aContext->ApplyWorldViewMatrix(); // Render arrow - - TEL_TRANSFORM_PERSISTENCE aTransMode; - aTransMode.mode = Graphic3d_TMF_ZoomPers; OpenGl_Vec3 anArrowVec = myMin + anAxis.Direction * (myMax - myMin); - aTransMode.pointX = anArrowVec.x(); - aTransMode.pointY = anArrowVec.y(); - aTransMode.pointZ = anArrowVec.z(); - theWorkspace->ActiveView()->BeginTransformPersistence (aContext, &aTransMode, theWorkspace->Width(), theWorkspace->Height()); + Graphic3d_TransformPers aTransMode; + aTransMode.Flags = Graphic3d_TMF_ZoomPers; + aTransMode.Point.x() = anArrowVec.x(); + aTransMode.Point.y() = anArrowVec.y(); + aTransMode.Point.z() = anArrowVec.z(); + + const OpenGl_Mat4& aProjection = aContext->ProjectionState.Current(); + const OpenGl_Mat4& aWorldView = aContext->WorldViewState.Current(); + const Standard_Integer aWidth = theWorkspace->Width(); + const Standard_Integer aHeight = theWorkspace->Height(); - // NOTE: - // OpenGl_View applies Transform Persistence only in Projection Matrix. // Take into account Transform Persistence + aContext->ModelWorldState.SetCurrent (aTransMode.Compute (aProjection, aWorldView, aWidth, aHeight)); aContext->ApplyModelViewMatrix(); + anAxis.Arrow.Render (theWorkspace); + // Get current Model-View and Projection states OpenGl_Mat4 aModelMat; OpenGl_Mat4 aProjMat; GLint aViewport[4]; aContext->core11fwd->glGetIntegerv (GL_VIEWPORT, aViewport); - aModelMat.Convert (aContext->ModelWorldState.Current() * aContext->WorldViewState.Current()); + aModelMat.Convert (aContext->WorldViewState.Current() * aContext->ModelWorldState.Current()); aProjMat .Convert (aContext->ProjectionState.Current()); - // Get the window's (fixed) coordinates for before matrixes modifications + // Get the window's (fixed) coordinates for before matrices modifications OpenGl_Vec3 aEndPoint = -anAxis.Direction * myData.ArrowsLength(); OpenGl_Vec3 aWinPoint; - OpenGl_Utils::Project (aEndPoint.x(), aEndPoint.y(), aEndPoint.z(), - aModelMat, aProjMat, aViewport, - aWinPoint.x(), aWinPoint.y(), aWinPoint.z()); - anAxis.Arrow.Render (theWorkspace); - theWorkspace->ActiveView()->EndTransformPersistence (aContext); + Graphic3d_TransformUtils::Project (aEndPoint.x(), aEndPoint.y(), aEndPoint.z(), + aModelMat, aProjMat, aViewport, + aWinPoint.x(), aWinPoint.y(), aWinPoint.z()); - // Get current Model-View and Projection states after the end of Transform Persistence - aModelMat.Convert (aContext->ModelWorldState.Current() * aContext->WorldViewState.Current()); + aContext->ModelWorldState.SetIdentity(); + aModelMat.Convert (aContext->WorldViewState.Current()); aProjMat .Convert (aContext->ProjectionState.Current()); // Get start point of zoom persistent arrow OpenGl_Vec3 anArrowStart; - OpenGl_Utils::UnProject (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(), - aModelMat, aProjMat, aViewport, - anArrowStart.x(), anArrowStart.y(), anArrowStart.z()); + Graphic3d_TransformUtils::UnProject (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(), + aModelMat, aProjMat, aViewport, + anArrowStart.x(), anArrowStart.y(), anArrowStart.z()); // Render axis line - aModelMat = theMat; - OpenGl_Utils::Translate (aModelMat, myMin.x(), myMin.y(), myMin.z()); + Graphic3d_TransformUtils::Translate (aModelMat, myMin.x(), myMin.y(), myMin.z()); Standard_ShortReal aScaleFactor = ( (anArrowStart - myMin)*anAxis.Direction ).Modulus() / (anAxis.Direction * (myMax - myMin) ).Modulus(); OpenGl_Vec3 aScaleAxes = anAxis.Direction * aScaleFactor; - OpenGl_Utils::Scale (aModelMat, aScaleAxes.x(), aScaleAxes.y(), aScaleAxes.z()); + Graphic3d_TransformUtils::Scale (aModelMat, aScaleAxes.x(), aScaleAxes.y(), aScaleAxes.z()); aContext->WorldViewState.SetCurrent (aModelMat); aContext->ApplyWorldViewMatrix(); @@ -490,16 +491,16 @@ void OpenGl_GraduatedTrihedron::renderTickmarkLabels (const Handle(OpenGl_Worksp OpenGl_Mat4 aModelMat (theMat); anAxis.InitTickmark (aContext, aDir * (Standard_ShortReal) aCurAspect.TickmarksLength() * theDpix); - OpenGl_Utils::Translate (aModelMat, theGridAxes.Ticks[theIndex].x(), - theGridAxes.Ticks[theIndex].y(), - theGridAxes.Ticks[theIndex].z()); + Graphic3d_TransformUtils::Translate (aModelMat, theGridAxes.Ticks[theIndex].x(), + theGridAxes.Ticks[theIndex].y(), + theGridAxes.Ticks[theIndex].z()); aContext->WorldViewState.SetCurrent (aModelMat); aContext->ApplyWorldViewMatrix(); OpenGl_Vec3 aStepVec = anAxis.Direction * aStep; for (Standard_Integer anIter = 0; anIter <= aCurAspect.TickmarksNumber(); ++anIter) { anAxis.Tickmark.Render (theWorkspace); - OpenGl_Utils::Translate (aModelMat, aStepVec.x(), aStepVec.y(), aStepVec.z()); + Graphic3d_TransformUtils::Translate (aModelMat, aStepVec.x(), aStepVec.y(), aStepVec.z()); aContext->WorldViewState.SetCurrent (aModelMat); aContext->ApplyWorldViewMatrix(); } diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx index 5ab137cd56..4c817d3980 100644 --- a/src/OpenGl/OpenGl_Layer.cxx +++ b/src/OpenGl/OpenGl_Layer.cxx @@ -21,7 +21,7 @@ #include // ======================================================================= -// function : OpenGl_PriorityList +// function : OpenGl_Layer // purpose : // ======================================================================= OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities) @@ -63,7 +63,14 @@ void OpenGl_Layer::Add (const OpenGl_Structure* theStruct, } else if (!isForChangePriority) { - myBVHPrimitives.Add (theStruct); + if (!theStruct->TransformPersistence.Flags) + { + myBVHPrimitives.Add (theStruct); + } + else + { + myBVHPrimitivesTrsfPers.Add (theStruct); + } } ++myNbStructures; } @@ -94,7 +101,10 @@ bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct, if (!theStruct->IsAlwaysRendered() && !isForChangePriority) { - myBVHPrimitives.Remove (theStruct); + if (!myBVHPrimitives.Remove (theStruct)) + { + myBVHPrimitivesTrsfPers.Remove (theStruct); + } } --myNbStructures; thePriority = aPriorityIter; @@ -152,8 +162,28 @@ void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) { if (myIsBVHPrimitivesNeedsReset) { - myBVHPrimitives.Assign (myArray); + myBVHPrimitives.Clear(); + myBVHPrimitivesTrsfPers.Clear(); myIsBVHPrimitivesNeedsReset = Standard_False; + for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx) + { + for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next()) + { + const OpenGl_Structure* aStruct = aStructIter.Value(); + + if (aStruct->IsAlwaysRendered()) + continue; + + if (!aStruct->TransformPersistence.Flags) + { + myBVHPrimitives.Add (aStruct); + } + else + { + myBVHPrimitivesTrsfPers.Add (aStruct); + } + } + } } OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector(); @@ -190,64 +220,93 @@ void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const { // handle a case when all objects are infinite - if (myBVHPrimitives.Size() == 0) + if (myBVHPrimitives.Size() == 0 && myBVHPrimitivesTrsfPers.Size() == 0) return; - const NCollection_Handle >& aBVHTree = myBVHPrimitives.BVH(); - - Standard_Integer aNode = 0; // a root node theSelector.CacheClipPtsProjections(); - if (!theSelector.Intersect (aBVHTree->MinPoint (0), - aBVHTree->MaxPoint (0))) - { - return; - } - Standard_Integer aStack[32]; - Standard_Integer aHead = -1; - for (;;) + NCollection_Handle > aBVHTree; + + for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) { - if (!aBVHTree->IsOuter (aNode)) + const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; + if (isTrsfPers) { - const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); - const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); - const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx), - aBVHTree->MaxPoint (aLeftChildIdx)); - const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx), - aBVHTree->MaxPoint (aRightChildIdx)); - if (isLeftChildIn - && isRightChildIn) + if (myBVHPrimitivesTrsfPers.Size() == 0) { - aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; - aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; - myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; + continue; } - else if (isLeftChildIn - || isRightChildIn) + const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix(); + const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix(); + const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState(); + aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState); + } + else + { + if (myBVHPrimitives.Size() == 0) { - aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + continue; + } + aBVHTree = myBVHPrimitives.BVH(); + } + + Standard_Integer aNode = 0; // a root node + + if (!theSelector.Intersect (aBVHTree->MinPoint (0), + aBVHTree->MaxPoint (0))) + { + continue; + } + + Standard_Integer aStack[32]; + Standard_Integer aHead = -1; + for (;;) + { + if (!aBVHTree->IsOuter (aNode)) + { + const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); + const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); + const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx), + aBVHTree->MaxPoint (aLeftChildIdx)); + const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx), + aBVHTree->MaxPoint (aRightChildIdx)); + if (isLeftChildIn + && isRightChildIn) + { + aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; + aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; + myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; + } + else if (isLeftChildIn + || isRightChildIn) + { + aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + } + else + { + if (aHead < 0) + { + break; + } + + aNode = aStack[aHead--]; + } } else { + Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); + const OpenGl_Structure* aStruct = + isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) + : myBVHPrimitives.GetStructureById (aIdx); + aStruct->MarkAsNotCulled(); if (aHead < 0) { - return; + break; } aNode = aStack[aHead--]; } } - else - { - Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); - myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled(); - if (aHead < 0) - { - return; - } - - aNode = aStack[aHead--]; - } } } diff --git a/src/OpenGl/OpenGl_Layer.hxx b/src/OpenGl/OpenGl_Layer.hxx index cc1697ee0d..b2ed370b0d 100644 --- a/src/OpenGl/OpenGl_Layer.hxx +++ b/src/OpenGl/OpenGl_Layer.hxx @@ -23,9 +23,11 @@ #include #include +#include #include #include +#include #include class Handle(OpenGl_Workspace); @@ -36,6 +38,8 @@ struct OpenGl_GlobalLayerSettings GLboolean DepthMask; }; +typedef NCollection_Array1 OpenGl_ArrayOfStructure; + //! Presentations list sorted within priorities. class OpenGl_Layer { @@ -105,12 +109,25 @@ protected: private: - OpenGl_ArrayOfStructure myArray; - Standard_Integer myNbStructures; - Graphic3d_ZLayerSettings myLayerSettings; //!< Layer setting flags - mutable OpenGl_BVHClipPrimitiveSet myBVHPrimitives; // +#include + +//! Software implementation for OpenGL matrix stack. +template +class OpenGl_MatrixState +{ +public: + + //! Constructs matrix state object. + OpenGl_MatrixState() + : myStack (8), + myStackHead (-1) + { + // + } + + //! Pushes current matrix into stack. + void Push() + { + if (++myStackHead >= myStack.Size()) + { + myStack.Append (myCurrent); + } + else + { + myStack.SetValue (myStackHead, myCurrent); + } + } + + //! Pops matrix from stack to current. + void Pop() + { + Standard_ASSERT_RETURN (myStackHead != -1, "Matrix stack already empty when MatrixState.Pop() called.", ); + myCurrent = myStack.Value (myStackHead--); + } + + //! @return current matrix. + const typename OpenGl::MatrixType::Mat4& Current() + { + return myCurrent; + } + + //! Sets given matrix as current. + void SetCurrent (const typename OpenGl::MatrixType::Mat4& theNewCurrent) + { + myCurrent = theNewCurrent; + } + + //! Sets given matrix as current. + template + void SetCurrent (const typename OpenGl::MatrixType::Mat4& theNewCurrent) + { + myCurrent.Convert (theNewCurrent); + } + + //! Sets current matrix to identity. + void SetIdentity() + { + myCurrent = typename OpenGl::MatrixType::Mat4(); + } + +private: + + NCollection_Vector::Mat4> myStack; //!< Collection used to maintenance matrix stack + typename OpenGl::MatrixType::Mat4 myCurrent; //!< Current matrix + Standard_Integer myStackHead; //!< Index of stack head +}; + +#endif // _OpenGl_MatrixState_H__ diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index df77dfcfac..faa5cb7367 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -120,7 +120,6 @@ public: OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager) : Graphic3d_CStructure (theManager), myTransformation (NULL), - myTransPers (NULL), myAspectLine (NULL), myAspectFace (NULL), myAspectMarker (NULL), @@ -143,7 +142,6 @@ OpenGl_Structure::~OpenGl_Structure() { Release (Handle(OpenGl_Context)()); delete myTransformation; myTransformation = NULL; - delete myTransPers; myTransPers = NULL; } // ======================================================================= @@ -152,8 +150,6 @@ OpenGl_Structure::~OpenGl_Structure() // ======================================================================= void OpenGl_Structure::UpdateAspects() { - SetTransformPersistence (TransformPersistence); - if (ContextLine.IsDef) SetAspectLine (ContextLine); @@ -196,22 +192,6 @@ void OpenGl_Structure::UpdateTransformation() } } -// ======================================================================= -// function : SetTransformPersistence -// purpose : -// ======================================================================= -void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers) -{ - if (!myTransPers) - myTransPers = new TEL_TRANSFORM_PERSISTENCE; - - myTransPers->mode = ATransPers.Flag; - myTransPers->pointX = ATransPers.Point.x; - myTransPers->pointY = ATransPers.Point.y; - myTransPers->pointZ = ATransPers.Point.z; - MarkAsNotCulled(); -} - // ======================================================================= // function : SetAspectLine // purpose : @@ -560,32 +540,40 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled(); // Apply local transformation + OpenGl_Mat4 aModelWorld; if (myTransformation) { - OpenGl_Matrix aModelWorld; - OpenGl_Transposemat3 (&aModelWorld, myTransformation); - aCtx->ModelWorldState.Push(); - aCtx->ModelWorldState.SetCurrent (OpenGl_Mat4::Map ((Standard_ShortReal* )aModelWorld.mat)); + OpenGl_Transposemat3 ((OpenGl_Matrix*)aModelWorld.ChangeData(), myTransformation); - Standard_ShortReal aScaleX = OpenGl_Vec3 (myTransformation->mat[0][0], - myTransformation->mat[0][1], - myTransformation->mat[0][2]).SquareModulus(); + Standard_ShortReal aScaleX = OpenGl_Vec3 (aModelWorld.GetValue (0, 0), + aModelWorld.GetValue (1, 0), + aModelWorld.GetValue (2, 0)).SquareModulus(); // Scale transform detected. if (Abs (aScaleX - 1.f) > Precision::Confusion()) { aCtx->SetGlNormalizeEnabled (Standard_True); } + + aCtx->ModelWorldState.Push(); + aCtx->ModelWorldState.SetCurrent (aModelWorld); } + if (TransformPersistence.Flags) + { + OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current(); + OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current(); + TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height()); - // Apply transform persistence - const TEL_TRANSFORM_PERSISTENCE *aTransPersistence = NULL; - if ( myTransPers && myTransPers->mode != 0 ) + aCtx->ProjectionState.Push(); + aCtx->WorldViewState.Push(); + aCtx->ProjectionState.SetCurrent (aProjection); + aCtx->WorldViewState.SetCurrent (aWorldView); + aCtx->ApplyProjectionMatrix(); + } + if (aModelWorld || TransformPersistence.Flags) { - aTransPersistence = theWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers, theWorkspace->Width(), theWorkspace->Height()); + aCtx->ApplyModelViewMatrix(); } - // Take into account transform persistence - aCtx->ApplyModelViewMatrix(); // Apply aspects const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False); @@ -694,12 +682,22 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con } } - // Apply local transformation - if (myTransformation) + // Restore local transformation + if (!aModelWorld.IsIdentity()) { aCtx->ModelWorldState.Pop(); aCtx->SetGlNormalizeEnabled (anOldGlNormalize); } + if (TransformPersistence.Flags) + { + aCtx->ProjectionState.Pop(); + aCtx->WorldViewState.Pop(); + aCtx->ApplyProjectionMatrix(); + } + if (!aModelWorld.IsIdentity() || TransformPersistence.Flags) + { + aCtx->ApplyWorldViewMatrix(); + } // Restore highlight color theWorkspace->HighlightColor = aHighlightColor; @@ -710,12 +708,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con theWorkspace->SetAspectMarker (anAspectMarker); theWorkspace->SetAspectText (anAspectText); - // Restore transform persistence - if ( myTransPers && myTransPers->mode != 0 ) - { - theWorkspace->ActiveView()->BeginTransformPersistence (aCtx, aTransPersistence, theWorkspace->Width(), theWorkspace->Height()); - } - // Apply highlight box if (!myHighlightBox.IsNull()) { diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index ac9619549b..23d79c0552 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -114,8 +114,6 @@ public: return (OpenGl_GraphicDriver* )myGraphicDriver.operator->(); } - void SetTransformPersistence (const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers); - void SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect); void SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect); void SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect); @@ -164,7 +162,7 @@ public: || IsForHighlight || IsMutable || Is2dText - || TransformPersistence.Flag != 0; + || TransformPersistence.Flags != 0; } //! This method releases GL resources without actual elements destruction. @@ -183,9 +181,6 @@ public: //! Returns OpenGL transformation matrix. const OpenGl_Matrix* Transformation() const { return myTransformation; } - - //! Returns OpenGL persistent translation. - const TEL_TRANSFORM_PERSISTENCE* PersistentTranslation() const { return myTransPers; } //! Returns structure modification state (for ray-tracing). Standard_Size ModificationState() const { return myModificationState; } @@ -206,7 +201,6 @@ protected: protected: OpenGl_Matrix* myTransformation; - TEL_TRANSFORM_PERSISTENCE* myTransPers; OpenGl_AspectLine* myAspectLine; OpenGl_AspectFace* myAspectFace; OpenGl_AspectMarker* myAspectMarker; diff --git a/src/OpenGl/OpenGl_StructureShadow.cxx b/src/OpenGl/OpenGl_StructureShadow.cxx index 9cfe62b99f..b6765fa5b8 100644 --- a/src/OpenGl/OpenGl_StructureShadow.cxx +++ b/src/OpenGl/OpenGl_StructureShadow.cxx @@ -42,7 +42,5 @@ OpenGl_StructureShadow::OpenGl_StructureShadow (const Handle(Graphic3d_Structure } } - TransformPersistence.IsSet = myParent->TransformPersistence.IsSet; - TransformPersistence.Flag = myParent->TransformPersistence.Flag; - TransformPersistence.Point = myParent->TransformPersistence.Point; + TransformPersistence = myParent->TransformPersistence; } diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 93ceede87e..6982e49cdf 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -13,6 +13,8 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include + #include #include #include @@ -20,7 +22,6 @@ #include #include #include -#include #include #include @@ -484,24 +485,24 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx, if (myIs2d) { - OpenGl_Utils::Translate (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f); - OpenGl_Utils::Scale (aModViewMat, 1.f, -1.f, 1.f); - OpenGl_Utils::Rotate (aModViewMat, theTextAspect.Angle(), 0.f, 0.f, 1.f); + Graphic3d_TransformUtils::Translate (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f); + Graphic3d_TransformUtils::Scale (aModViewMat, 1.f, -1.f, 1.f); + Graphic3d_TransformUtils::Rotate (aModViewMat, theTextAspect.Angle(), 0.f, 0.f, 1.f); } else { // align coordinates to the nearest integer // to avoid extra interpolation issues GLdouble anObjX, anObjY, anObjZ; - OpenGl_Utils::UnProject (std::floor (myWinX + theDVec.x()), - std::floor (myWinY + theDVec.y()), - myWinZ + theDVec.z(), - OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), - OpenGl_Mat4d::Map (aProjectMat), - myViewport, - anObjX, - anObjY, - anObjZ); + Graphic3d_TransformUtils::UnProject (std::floor (myWinX + theDVec.x()), + std::floor (myWinY + theDVec.y()), + myWinZ + theDVec.z(), + OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), + OpenGl_Mat4d::Map (aProjectMat), + myViewport, + anObjX, + anObjY, + anObjZ); if (myHasPlane) { @@ -516,8 +517,8 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx, } else { - OpenGl_Utils::Translate (aModViewMat, anObjX, anObjY, anObjZ); - OpenGl_Utils::Rotate (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0); + Graphic3d_TransformUtils::Translate (aModViewMat, anObjX, anObjY, anObjZ); + Graphic3d_TransformUtils::Rotate (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0); } if (!theTextAspect.IsZoomable()) @@ -533,10 +534,10 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx, // text should be scaled in all directions with same // factor to save its proportions, so use height (y) scaling // as it is better for keeping text/3d graphics proportions - OpenGl_Utils::Scale (aModViewMat, aTextScaley, aTextScaley, aTextScaley); + Graphic3d_TransformUtils::Scale (aModViewMat, aTextScaley, aTextScaley, aTextScaley); } #endif - OpenGl_Utils::Scale (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight); + Graphic3d_TransformUtils::Scale (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight); } } @@ -751,39 +752,39 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx, { glGetIntegerv (GL_VIEWPORT, myViewport); - OpenGl_Utils::Project (myPoint.x(), - myPoint.y(), - myPoint.z(), - myModelMatrix, - myProjMatrix, - myViewport, - myWinX, - myWinY, - myWinZ); + Graphic3d_TransformUtils::Project (myPoint.x(), + myPoint.y(), + myPoint.z(), + myModelMatrix, + myProjMatrix, + myViewport, + myWinX, + myWinY, + myWinZ); // compute scale factor for constant text height GLdouble x1, y1, z1; - OpenGl_Utils::UnProject (myWinX, - myWinY, - myWinZ, - OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), - myProjMatrix, - myViewport, - x1, - y1, - z1); + Graphic3d_TransformUtils::UnProject (myWinX, + myWinY, + myWinZ, + OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), + myProjMatrix, + myViewport, + x1, + y1, + z1); GLdouble x2, y2, z2; const GLdouble h = (GLdouble )myFont->FTFont()->PointSize(); - OpenGl_Utils::UnProject (myWinX, - myWinY + h, - myWinZ, - OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), - myProjMatrix, - myViewport, - x2, - y2, - z2); + Graphic3d_TransformUtils::UnProject (myWinX, + myWinY + h, + myWinZ, + OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), + myProjMatrix, + myViewport, + x2, + y2, + z2); myScaleHeight = (y2 - y1) / h; if (theTextAspect.IsZoomable()) diff --git a/src/OpenGl/OpenGl_Trihedron.cxx b/src/OpenGl/OpenGl_Trihedron.cxx index eb19352bee..5b5af494fb 100644 --- a/src/OpenGl/OpenGl_Trihedron.cxx +++ b/src/OpenGl/OpenGl_Trihedron.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -86,25 +87,25 @@ void OpenGl_Trihedron::resetTransformations (const Handle(OpenGl_Workspace)& the { case Aspect_TOTP_LEFT_LOWER: { - OpenGl_Utils::Translate (aProjMatrix, + Graphic3d_TransformUtils::Translate (aProjMatrix, -0.5 * anU + myScale, -0.5 * aV + myScale, 0.0); break; } case Aspect_TOTP_LEFT_UPPER: { - OpenGl_Utils::Translate (aProjMatrix, + Graphic3d_TransformUtils::Translate (aProjMatrix, -0.5 * anU + myScale, 0.5 * aV - myScale - myScale / 3.0, 0.0); break; } case Aspect_TOTP_RIGHT_LOWER: { - OpenGl_Utils::Translate (aProjMatrix, + Graphic3d_TransformUtils::Translate (aProjMatrix, 0.5 * anU - myScale - myScale / 3.0, -0.5 * aV + myScale, 0.0); break; } case Aspect_TOTP_RIGHT_UPPER: { - OpenGl_Utils::Translate (aProjMatrix, + Graphic3d_TransformUtils::Translate (aProjMatrix, 0.5 * anU - myScale - myScale / 3.0, 0.5 * aV - myScale - myScale / 3.0, 0.0); break; } @@ -231,7 +232,7 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace(&anAspectZ); theWorkspace->SetAspectLine (&anAspectLine); myLine.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewZ, 0.0, 0.0, aLineLength); + Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aLineLength); aContext->WorldViewState.SetCurrent(aModelViewZ); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -239,7 +240,7 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con // X axis theWorkspace->SetAspectFace (&anAspectX); - OpenGl_Utils::Rotate (aModelViewX, 90.0, 0.0, aScale, 0.0); + Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, 0.0, aScale, 0.0); aContext->WorldViewState.SetCurrent (aModelViewX); aContext->ApplyWorldViewMatrix(); @@ -249,7 +250,7 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con anAspectLine.SetAspect (aLineAspect); theWorkspace->SetAspectLine (&anAspectLine); myLine.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewX, 0.0, 0.0, aLineLength); + Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aLineLength); aContext->WorldViewState.SetCurrent (aModelViewX); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -257,7 +258,7 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con // Y axis theWorkspace->SetAspectFace (&anAspectY); - OpenGl_Utils::Rotate (aModelViewY, -90.0, aScale, 0.0, 0.0); + Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aScale, 0.0, 0.0); aContext->WorldViewState.SetCurrent (aModelViewY); aContext->ApplyWorldViewMatrix(); @@ -267,7 +268,7 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con anAspectLine.SetAspect (aLineAspect); theWorkspace->SetAspectLine (&anAspectLine); myLine.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewY, 0.0, 0.0, aLineLength); + Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aLineLength); aContext->WorldViewState.SetCurrent (aModelViewY); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -411,7 +412,7 @@ void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspa // Z axis theWorkspace->SetAspectFace (&anAspectZ); myCylinder.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewZ, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); + Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); aContext->WorldViewState.SetCurrent (aModelViewZ); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -419,11 +420,11 @@ void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspa // X axis theWorkspace->SetAspectFace (&anAspectX); - OpenGl_Utils::Rotate (aModelViewX, 90.0, aTriedronAxeY[0], aTriedronAxeY[1], aTriedronAxeY[2]); + Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, aTriedronAxeY[0], aTriedronAxeY[1], aTriedronAxeY[2]); aContext->WorldViewState.SetCurrent (aModelViewX); aContext->ApplyWorldViewMatrix(); myCylinder.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewX, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); + Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); aContext->WorldViewState.SetCurrent (aModelViewX); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -431,11 +432,11 @@ void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspa // Y axis theWorkspace->SetAspectFace (&anAspectY); - OpenGl_Utils::Rotate (aModelViewY, -90.0, aTriedronAxeX[0], aTriedronAxeX[1], aTriedronAxeX[2]); + Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aTriedronAxeX[0], aTriedronAxeX[1], aTriedronAxeX[2]); aContext->WorldViewState.SetCurrent (aModelViewY); aContext->ApplyWorldViewMatrix(); myCylinder.Render (theWorkspace); - OpenGl_Utils::Translate (aModelViewY, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); + Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH); aContext->WorldViewState.SetCurrent (aModelViewY); aContext->ApplyWorldViewMatrix(); myDisk.Render (theWorkspace); @@ -644,7 +645,7 @@ void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) con } const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); - theWorkspace->ActiveView()->EndTransformPersistence (theWorkspace->GetGlContext()); + theWorkspace->GetGlContext()->ApplyModelViewMatrix(); if (myIsWireframe) diff --git a/src/OpenGl/OpenGl_Utils.hxx b/src/OpenGl/OpenGl_Utils.hxx deleted file mode 100644 index 39702c147d..0000000000 --- a/src/OpenGl/OpenGl_Utils.hxx +++ /dev/null @@ -1,518 +0,0 @@ -// Created on: 2014-09-30 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2014 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 _OpenGl_Utils_H__ -#define _OpenGl_Utils_H__ - -#include -#include - -//! Helper class that implements some functionality of GLU library. -namespace OpenGl_Utils -{ - - //! Matrix type selector. - template - struct MatrixType { - // - }; - - template<> - struct MatrixType { - typedef OpenGl_Mat4d Mat4; - }; - - template<> - struct MatrixType { - typedef OpenGl_Mat4 Mat4; - }; - - //! Vector type selector. - template - struct VectorType { - // - }; - - template<> - struct VectorType { - typedef OpenGl_Vec2d Vec2; - typedef OpenGl_Vec3d Vec3; - typedef OpenGl_Vec4d Vec4; - }; - - template<> - struct VectorType { - typedef OpenGl_Vec2 Vec2; - typedef OpenGl_Vec3 Vec3; - typedef OpenGl_Vec4 Vec4; - }; - - //! Software implementation for OpenGL matrix stack. - template - class MatrixState - { - public: - - //! Constructs matrix state object. - MatrixState() - : myStack (8), - myStackHead (-1) - { - // - } - - //! Pushes current matrix into stack. - void Push() - { - if (++myStackHead >= myStack.Size()) - { - myStack.Append (myCurrent); - } - else - { - myStack.SetValue (myStackHead, myCurrent); - } - } - - //! Pops matrix from stack to current. - void Pop() - { - Standard_ASSERT_RETURN (myStackHead != -1, "Matrix stack already empty when MatrixState.Pop() called.", ); - myCurrent = myStack.Value (myStackHead--); - } - - //! @return current matrix. - const typename MatrixType::Mat4& Current() - { - return myCurrent; - } - - //! Sets given matrix as current. - void SetCurrent (const typename MatrixType::Mat4& theNewCurrent) - { - myCurrent = theNewCurrent; - } - - //! Sets given matrix as current. - template - void SetCurrent (const typename MatrixType::Mat4& theNewCurrent) - { - myCurrent.Convert (theNewCurrent); - } - - //! Sets current matrix to identity. - void SetIdentity() - { - myCurrent = typename MatrixType::Mat4(); - } - - private: - - NCollection_Vector::Mat4> myStack; //!< Collection used to maintenance matrix stack - typename MatrixType::Mat4 myCurrent; //!< Current matrix - Standard_Integer myStackHead; //!< Index of stack head - - }; - - //! Constructs a 3D orthographic projection matrix. - template - static void Ortho (typename MatrixType::Mat4& theOut, - const T theLeft, const T theRight, const T theBottom, const T theTop, const T theZNear, const T theZFar); - - //! Constructs a 2D orthographic projection matrix. - template - static void Ortho2D (typename MatrixType::Mat4& theOut, - const T theLeft, const T theRight, const T theBottom, const T theTop); - - //! Maps object coordinates to window coordinates. - template - static Standard_Boolean Project (const T theObjX, - const T theObjY, - const T theObjZ, - const typename MatrixType::Mat4& theModViewMat, - const typename MatrixType::Mat4& theProjectMat, - const Standard_Integer theViewport[4], - T& theWinX, - T& theWinY, - T& theWinZ); - - //! Maps window coordinates to object coordinates. - template - static Standard_Boolean UnProject (const T theWinX, - const T theWinY, - const T theWinZ, - const typename MatrixType::Mat4& theModViewMat, - const typename MatrixType::Mat4& theProjectMat, - const Standard_Integer theViewport[4], - T& theObjX, - T& theObjY, - T& theObjZ); - - //! Constructs a 4x4 rotation matrix. - template - static void ConstructRotate (typename MatrixType::Mat4& theOut, - T theA, - T theX, - T theY, - T theZ); - - //! Constructs a 4x4 rotation matrix. - template - static void Rotate (typename MatrixType::Mat4& theOut, - T theA, - T theX, - T theY, - T theZ); - - //! Constructs a 4x4 scaling matrix. - template - static void Scale (typename MatrixType::Mat4& theOut, - T theX, - T theY, - T theZ); - - //! Constructs a 4x4 translation matrix. - template - static void Translate (typename MatrixType::Mat4& theOut, - T theX, - T theY, - T theZ); - -} - -// ======================================================================= -// function : Rotate -// purpose : Constructs a 4x4 rotation matrix -// ======================================================================= -template -void OpenGl_Utils::Rotate (typename MatrixType::Mat4& theOut, - T theA, - T theX, - T theY, - T theZ) -{ - typename MatrixType::Mat4 aMat; - ConstructRotate (aMat, theA, theX, theY, theZ); - theOut = theOut * aMat; -} - -// ======================================================================= -// function : Translate -// purpose : Constructs a 4x4 translation matrix -// ======================================================================= -template -void OpenGl_Utils::Translate (typename MatrixType::Mat4& theOut, - T theX, - T theY, - T theZ) -{ - theOut.ChangeValue (0, 3) = theOut.GetValue (0, 0) * theX + - theOut.GetValue (0, 1) * theY + - theOut.GetValue (0, 2) * theZ + - theOut.GetValue (0, 3); - - theOut.ChangeValue (1, 3) = theOut.GetValue (1, 0) * theX + - theOut.GetValue (1, 1) * theY + - theOut.GetValue (1, 2) * theZ + - theOut.GetValue (1, 3); - - theOut.ChangeValue (2, 3) = theOut.GetValue (2, 0) * theX + - theOut.GetValue (2, 1) * theY + - theOut.GetValue (2, 2) * theZ + - theOut.GetValue (2, 3); - - theOut.ChangeValue (3, 3) = theOut.GetValue (3, 0) * theX + - theOut.GetValue (3, 1) * theY + - theOut.GetValue (3, 2) * theZ + - theOut.GetValue (3, 3); -} - -// ======================================================================= -// function : Scale -// purpose : Constructs a 4x4 scaling matrix -// ======================================================================= -template -void OpenGl_Utils::Scale (typename MatrixType::Mat4& theOut, - T theX, - T theY, - T theZ) -{ - theOut.ChangeValue (0, 0) *= theX; - theOut.ChangeValue (1, 0) *= theX; - theOut.ChangeValue (2, 0) *= theX; - theOut.ChangeValue (3, 0) *= theX; - - theOut.ChangeValue (0, 1) *= theY; - theOut.ChangeValue (1, 1) *= theY; - theOut.ChangeValue (2, 1) *= theY; - theOut.ChangeValue (3, 1) *= theY; - - theOut.ChangeValue (0, 2) *= theZ; - theOut.ChangeValue (1, 2) *= theZ; - theOut.ChangeValue (2, 2) *= theZ; - theOut.ChangeValue (3, 2) *= theZ; -} - -// ======================================================================= -// function : ConstructRotate -// purpose : Constructs a 4x4 rotation matrix -// ======================================================================= -template -void OpenGl_Utils::ConstructRotate (typename MatrixType::Mat4& theOut, T theA, T theX, T theY, T theZ) -{ - const T aSin = std::sin (theA * static_cast (M_PI / 180.0)); - const T aCos = std::cos (theA * static_cast (M_PI / 180.0)); - - const Standard_Boolean isOnlyX = (theX != static_cast (0.0)) - && (theY == static_cast (0.0)) - && (theZ == static_cast (0.0)); - - const Standard_Boolean isOnlyY = (theX == static_cast (0.0)) - && (theY != static_cast (0.0)) - && (theZ == static_cast (0.0)); - - const Standard_Boolean isOnlyZ = (theX == static_cast (0.0)) - && (theY == static_cast (0.0)) - && (theZ != static_cast (0.0)); - - if (isOnlyX) // Rotation only around X - { - theOut.SetValue (1, 1, aCos); - theOut.SetValue (2, 2, aCos); - - if (theX < static_cast (0.0)) - { - theOut.SetValue (1, 2, aSin); - theOut.SetValue (2, 1, -aSin); - } - else - { - theOut.SetValue (1, 2, -aSin); - theOut.SetValue (2, 1, aSin); - } - - return; - } - else if (isOnlyY) // Rotation only around Y - { - theOut.SetValue (0, 0, aCos); - theOut.SetValue (2, 2, aCos); - - if (theY < static_cast (0.0)) - { - theOut.SetValue (0, 2, -aSin); - theOut.SetValue (2, 0, aSin); - } - else - { - theOut.SetValue (0, 2, aSin); - theOut.SetValue (2, 0, -aSin); - } - - return; - } - else if (isOnlyZ) // Rotation only around Z - { - theOut.SetValue (0, 0, aCos); - theOut.SetValue (1, 1, aCos); - - if (theZ < static_cast (0.0)) - { - theOut.SetValue (0, 1, aSin); - theOut.SetValue (1, 0, -aSin); - } - else - { - theOut.SetValue (0, 1, -aSin); - theOut.SetValue (1, 0, aSin); - } - - return; - } - - T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ); - - if (aNorm <= static_cast (1.0e-4)) - { - return; // negligible rotation - } - - aNorm = static_cast (1.0) / aNorm; - - theX *= aNorm; - theY *= aNorm; - theZ *= aNorm; - - const T aXX = theX * theX; - const T aYY = theY * theY; - const T aZZ = theZ * theZ; - const T aXY = theX * theY; - const T aYZ = theY * theZ; - const T aZX = theZ * theX; - const T aSinX = theX * aSin; - const T aSinY = theY * aSin; - const T aSinZ = theZ * aSin; - - const T aOneMinusCos = static_cast (1.0) - aCos; - - theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos); - theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ); - theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY); - - theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ); - theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos); - theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX); - - theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY); - theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX); - theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos); -} - -// ======================================================================= -// function : Ortho -// purpose : Constructs a 3D orthographic projection matrix -// ======================================================================= -template -void OpenGl_Utils::Ortho (typename MatrixType::Mat4& theOut, - const T theLeft, const T theRight, const T theBottom, const T theTop, const T theZNear, const T theZFar) -{ - theOut.InitIdentity(); - - T* aData = theOut.ChangeData(); - - const T anInvDx = static_cast (1.0) / (theRight - theLeft); - const T anInvDy = static_cast (1.0) / (theTop - theBottom); - const T anInvDz = static_cast (1.0) / (theZFar - theZNear); - - aData[0] = static_cast ( 2.0) * anInvDx; - aData[5] = static_cast ( 2.0) * anInvDy; - aData[10] = static_cast (-2.0) * anInvDz; - - aData[12] = -(theRight + theLeft) * anInvDx; - aData[13] = -(theTop + theBottom) * anInvDy; - aData[14] = -(theZFar + theZNear) * anInvDz; -} - -// ======================================================================= -// function : Ortho2D -// purpose : Constructs a 2D orthographic projection matrix -// ======================================================================= -template -void OpenGl_Utils::Ortho2D (typename MatrixType::Mat4& theOut, - const T theLeft, const T theRight, const T theBottom, const T theTop) -{ - Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast (-1.0), static_cast (1.0)); -} - -// ======================================================================= -// function : Project -// purpose : Maps object coordinates to window coordinates -// ======================================================================= -template -static Standard_Boolean OpenGl_Utils::Project (const T theObjX, - const T theObjY, - const T theObjZ, - const typename MatrixType::Mat4& theModViewMat, - const typename MatrixType::Mat4& theProjectMat, - const Standard_Integer theViewport[4], - T& theWinX, - T& theWinY, - T& theWinZ) -{ - typename VectorType::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast (1.0)); - - typename VectorType::Vec4 anOut = theProjectMat * (theModViewMat * anIn); - - if (anOut.w() == static_cast (0.0)) - { - return Standard_False; - } - - anOut.w() = static_cast (1.0) / anOut.w(); - - anOut.x() *= anOut.w(); - anOut.y() *= anOut.w(); - anOut.z() *= anOut.w(); - - // Map x, y and z to range 0-1 - anOut.x() = anOut.x() * static_cast (0.5) + static_cast (0.5); - anOut.y() = anOut.y() * static_cast (0.5) + static_cast (0.5); - anOut.z() = anOut.z() * static_cast (0.5) + static_cast (0.5); - - // Map x,y to viewport - anOut.x() = anOut.x() * theViewport[2] + theViewport[0]; - anOut.y() = anOut.y() * theViewport[3] + theViewport[1]; - - theWinX = anOut.x(); - theWinY = anOut.y(); - theWinZ = anOut.z(); - - return Standard_True; -} - -// ======================================================================= -// function : UnProject -// purpose : Maps window coordinates to object coordinates -// ======================================================================= -template -static Standard_Boolean OpenGl_Utils::UnProject (const T theWinX, - const T theWinY, - const T theWinZ, - const typename MatrixType::Mat4& theModViewMat, - const typename MatrixType::Mat4& theProjectMat, - const Standard_Integer theViewport[4], - T& theObjX, - T& theObjY, - T& theObjZ) -{ - typename MatrixType::Mat4 anUnviewMat; - - if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat)) - { - return Standard_False; - } - - typename VectorType::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast (1.0)); - - // Map x and y from window coordinates - anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2]; - anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3]; - - // Map to range -1 to 1 - anIn.x() = anIn.x() * static_cast (2.0) - static_cast (1.0); - anIn.y() = anIn.y() * static_cast (2.0) - static_cast (1.0); - anIn.z() = anIn.z() * static_cast (2.0) - static_cast (1.0); - - typename VectorType::Vec4 anOut = anUnviewMat * anIn; - - if (anOut.w() == static_cast (0.0)) - { - return Standard_False; - } - - anOut.w() = static_cast (1.0) / anOut.w(); - - anOut.x() *= anOut.w(); - anOut.y() *= anOut.w(); - anOut.z() *= anOut.w(); - - theObjX = anOut.x(); - theObjY = anOut.y(); - theObjZ = anOut.z(); - - return Standard_True; -} - -#endif // _OpenGl_Utils_H__ diff --git a/src/OpenGl/OpenGl_Vec.hxx b/src/OpenGl/OpenGl_Vec.hxx index 34c9250984..cb4cf962c4 100755 --- a/src/OpenGl/OpenGl_Vec.hxx +++ b/src/OpenGl/OpenGl_Vec.hxx @@ -45,4 +45,45 @@ typedef Graphic3d_Vec4d OpenGl_Vec4d; typedef Graphic3d_Mat4 OpenGl_Mat4; typedef Graphic3d_Mat4d OpenGl_Mat4d; +namespace OpenGl +{ + //! Tool class for selecting appropriate vector type. + //! \tparam T Numeric data type + template struct VectorType + { + // Not implemented + }; + + template<> struct VectorType + { + typedef OpenGl_Vec2d Vec2; + typedef OpenGl_Vec3d Vec3; + typedef OpenGl_Vec4d Vec4; + }; + + template<> struct VectorType + { + typedef OpenGl_Vec2 Vec2; + typedef OpenGl_Vec3 Vec3; + typedef OpenGl_Vec4 Vec4; + }; + + //! Tool class for selecting appropriate matrix type. + //! \tparam T Numeric data type + template struct MatrixType + { + // Not implemented + }; + + template<> struct MatrixType + { + typedef OpenGl_Mat4d Mat4; + }; + + template<> struct MatrixType + { + typedef OpenGl_Mat4 Mat4; + }; +} + #endif // _OpenGl_Vec_H__ diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 44926c33d2..f4ea2af8e7 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include #include @@ -39,14 +37,6 @@ static const Tmatrix3 myDefaultMatrix = { { 1.F, 0.F, 0.F, 0.F }, { 0.F, 1.F, 0. static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } }; static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } }; -static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F }; -static const GLdouble THE_IDENTITY_MATRIX[4][4] = -{ - {1.0, 0.0, 0.0, 0.0}, - {0.0, 1.0, 0.0, 0.0}, - {0.0, 0.0, 1.0, 0.0}, - {0.0, 0.0, 0.0, 1.0} -}; /*----------------------------------------------------------------------*/ @@ -67,10 +57,7 @@ OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext, myVisualization(AContext.Visualization), myShadingModel ((Visual3d_TypeOfModel )AContext.Model), myAntiAliasing(Standard_False), - myTransPers(&myDefaultTransPers), - myIsTransPers(Standard_False), - myProjectionState (0), - myModelViewState (0), + myWorldViewProjState(), myStateCounter (theCounter), myLastLightSourceState (0, 0), myTextureParams (new OpenGl_AspectFace()), @@ -257,246 +244,3 @@ void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx) myToShowGradTrihedron = false; myGraduatedTrihedron.Release (theCtx.operator->()); } - -/*----------------------------------------------------------------------*/ - -//transform_persistence_end -void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx) -{ - if (myIsTransPers) - { - theCtx->WorldViewState.Pop(); - theCtx->ProjectionState.Pop(); - - theCtx->ApplyProjectionMatrix(); - theCtx->ApplyWorldViewMatrix(); - - myIsTransPers = Standard_False; - } -} - -/*----------------------------------------------------------------------*/ - -//transform_persistence_begin -const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx, - const TEL_TRANSFORM_PERSISTENCE* theTransPers, - Standard_Integer theWidth, - Standard_Integer theHeight) -{ - const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers; - myTransPers = theTransPers; - if (theTransPers->mode == 0) - { - EndTransformPersistence (theCtx); - return aTransPersPrev; - } - - GLint aViewport[4]; - OpenGl_Mat4d aModelMatrix, aProjMatrix; - theCtx->core11fwd->glGetIntegerv (GL_VIEWPORT, aViewport); - aModelMatrix.Convert (theCtx->ModelWorldState.Current() * theCtx->WorldViewState.Current()); - aProjMatrix .Convert (theCtx->ProjectionState.Current()); - - const GLdouble aViewportW = (GLdouble )aViewport[2]; - const GLdouble aViewportH = (GLdouble )aViewport[3]; - - if (myIsTransPers) - { - // pop matrix stack - it will be overridden later - theCtx->WorldViewState.Pop(); - theCtx->ProjectionState.Pop(); - } - else - { - myIsTransPers = Standard_True; - } - - if (theTransPers->mode & TPF_2D) - { - GLfloat aLeft = -static_cast (theWidth / 2); - GLfloat aRight = static_cast (theWidth / 2); - GLfloat aBottom = -static_cast (theHeight / 2); - GLfloat aTop = static_cast (theHeight / 2); - GLfloat aGap = static_cast (theTransPers->pointZ); - if (theTransPers->pointX > 0) - { - aLeft -= static_cast (theWidth / 2) - aGap; - aRight -= static_cast (theWidth / 2) - aGap; - } - else if (theTransPers->pointX < 0) - { - aLeft += static_cast (theWidth / 2) - aGap; - aRight += static_cast (theWidth / 2) - aGap; - } - if (theTransPers->pointY > 0) - { - aBottom -= static_cast (theHeight / 2) - aGap; - aTop -= static_cast (theHeight / 2) - aGap; - } - else if (theTransPers->pointY < 0) - { - aBottom += static_cast (theHeight / 2) - aGap; - aTop += static_cast (theHeight / 2) - aGap; - } - if (theTransPers->mode == TPF_2D_ISTOPDOWN) - { - const GLfloat aTemp = aTop; - aTop = aBottom; - aBottom = aTemp; - } - - OpenGl_Mat4 aProjectMat; - OpenGl_Utils::Ortho2D (aProjectMat, - aLeft, aRight, - aBottom, aTop); - - theCtx->WorldViewState.Push(); - theCtx->ProjectionState.Push(); - - theCtx->WorldViewState.SetIdentity(); - theCtx->ProjectionState.SetCurrent (aProjectMat); - - theCtx->ApplyWorldViewMatrix(); - theCtx->ApplyProjectionMatrix(); - return aTransPersPrev; - } - - // push matrices into stack and reset them - theCtx->WorldViewState.Push(); - theCtx->ProjectionState.Push(); - - // get the window's (fixed) coordinates for theTransPers->point before matrixes modifications - GLdouble aWinX = 0.0, aWinY = 0.0, aWinZ = 0.0; - if ((theTransPers->mode & TPF_PAN) != TPF_PAN) - { - OpenGl_Utils::Project (theTransPers->pointX, - theTransPers->pointY, - theTransPers->pointZ, - aModelMatrix, - aProjMatrix, - aViewport, - aWinX, - aWinY, - aWinZ); - } - - // prevent zooming - if ((theTransPers->mode & TPF_ZOOM) - || (theTransPers->mode == TPF_TRIEDRON)) - { - // compute fixed-zoom multiplier - // actually function works ugly with TelPerspective! - const GLdouble aDet2 = 0.002 / (aViewportW > aViewportH ? aProjMatrix.GetValue (1, 1) : aProjMatrix.GetValue (0, 0)); - aProjMatrix.ChangeValue (0, 0) *= aDet2; - aProjMatrix.ChangeValue (1, 1) *= aDet2; - aProjMatrix.ChangeValue (2, 2) *= aDet2; - } - - // prevent translation - annulate translate matrix - if ((theTransPers->mode & TPF_PAN) - || (theTransPers->mode == TPF_TRIEDRON)) - { - aModelMatrix.SetValue (0, 3, 0.0); - aModelMatrix.SetValue (1, 3, 0.0); - aModelMatrix.SetValue (2, 3, 0.0); - aProjMatrix .SetValue (0, 3, 0.0); - aProjMatrix .SetValue (1, 3, 0.0); - aProjMatrix .SetValue (2, 3, 0.0); - } - - // prevent scaling-on-axis - if (theTransPers->mode & TPF_ZOOM) - { - const gp_Pnt anAxialScale = myCamera->AxialScale(); - const double aScaleX = anAxialScale.X(); - const double aScaleY = anAxialScale.Y(); - const double aScaleZ = anAxialScale.Z(); - for (int i = 0; i < 3; ++i) - { - aModelMatrix.ChangeValue (0, i) /= aScaleX; - aModelMatrix.ChangeValue (1, i) /= aScaleY; - aModelMatrix.ChangeValue (2, i) /= aScaleZ; - } - } - - // prevent rotating - annulate rotate matrix - if (theTransPers->mode & TPF_ROTATE) - { - aModelMatrix.SetValue (0, 0, 1.0); - aModelMatrix.SetValue (1, 1, 1.0); - aModelMatrix.SetValue (2, 2, 1.0); - - aModelMatrix.SetValue (1, 0, 0.0); - aModelMatrix.SetValue (2, 0, 0.0); - aModelMatrix.SetValue (0, 1, 0.0); - aModelMatrix.SetValue (2, 1, 0.0); - aModelMatrix.SetValue (0, 2, 0.0); - aModelMatrix.SetValue (1, 2, 0.0); - } - - // load computed matrices - theCtx->ModelWorldState.SetIdentity(); - theCtx->WorldViewState.SetCurrent (aModelMatrix); - theCtx->ProjectionState.SetCurrent (aProjMatrix); - - if (theTransPers->mode == TPF_TRIEDRON) - { - // move to the window corner - if (theTransPers->pointX != 0.0 - && theTransPers->pointY != 0.0) - { - GLdouble aW1, aH1, aW2, aH2, aDummy; - - OpenGl_Mat4d anIdentity; - - OpenGl_Utils::UnProject (0.5 * aViewportW, - 0.5 * aViewportH, - 0.0, - anIdentity, - aProjMatrix, - aViewport, - aW1, - aH1, - aDummy); - - OpenGl_Utils::UnProject (-0.5 * aViewportW, - -0.5 * aViewportH, - 0.0, - anIdentity, - aProjMatrix, - aViewport, - aW2, - aH2, - aDummy); - - GLdouble aMoveX = 0.5 * (aW1 - aW2 - theTransPers->pointZ); - GLdouble aMoveY = 0.5 * (aH1 - aH2 - theTransPers->pointZ); - aMoveX = (theTransPers->pointX > 0.0) ? aMoveX : -aMoveX; - aMoveY = (theTransPers->pointY > 0.0) ? aMoveY : -aMoveY; - - OpenGl_Utils::Translate (aProjMatrix, aMoveX, aMoveY, 0.0); - theCtx->ProjectionState.SetCurrent (aProjMatrix); - } - } - else if ((theTransPers->mode & TPF_PAN) != TPF_PAN) - { - // move to thePoint using saved win-coordinates ('marker-behaviour') - GLdouble aMoveX, aMoveY, aMoveZ; - - OpenGl_Utils::UnProject (aWinX, - aWinY, - aWinZ, - aModelMatrix, - aProjMatrix, - aViewport, - aMoveX, - aMoveY, - aMoveZ); - - OpenGl_Utils::Translate (aModelMatrix, aMoveX, aMoveY, aMoveZ); - theCtx->WorldViewState.SetCurrent (aModelMatrix); - } - - theCtx->ApplyProjectionMatrix(); - return aTransPersPrev; -} diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 2a16e41593..592e7300f2 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -119,12 +120,6 @@ class OpenGl_View : public MMgt_TShared Standard_Integer Backfacing () const { return myBackfacing; } - const TEL_TRANSFORM_PERSISTENCE * BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx, - const TEL_TRANSFORM_PERSISTENCE *theTransPers, - Standard_Integer theWidth, - Standard_Integer theHeight); - void EndTransformPersistence (const Handle(OpenGl_Context)& theCtx); - //! Add structure to display list with specified priority. //! The structure will be added to associated with it z layer. //! If the z layer is not presented in the view, the structure will @@ -270,12 +265,8 @@ protected: OpenGl_LayerList myZLayers; //!< main list of displayed structure, sorted by layers OpenGl_SequenceOfStructure myImmediateList; //!< list of immediate structures rendered on top of main presentation - const TEL_TRANSFORM_PERSISTENCE *myTransPers; - Standard_Boolean myIsTransPers; - //! Modification state - Standard_Size myProjectionState; - Standard_Size myModelViewState; + Graphic3d_WorldViewProjState myWorldViewProjState; OpenGl_StateCounter* myStateCounter; Standard_Size myCurrLightSourceState; diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 3abea5156f..8d3e10feb5 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -270,48 +270,25 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, } #endif - // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm). - Standard_Boolean isProjectionMatUpdateNeeded = Standard_False; - Standard_Boolean isOrientationMatUpdateNeeded = Standard_False; - if (myBVHSelector.ProjectionState() != myCamera->ProjectionState()) - { - isProjectionMatUpdateNeeded = Standard_True; - myBVHSelector.ChangeProjectionState() = myCamera->ProjectionState(); - } - if (myBVHSelector.ModelViewState() != myCamera->ModelViewState()) - { - isOrientationMatUpdateNeeded = Standard_True; - myBVHSelector.ChangeModelViewState() = myCamera->ModelViewState(); - } + Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); - if (isProjectionMatUpdateNeeded - || isOrientationMatUpdateNeeded) - { - myBVHSelector.SetViewVolume (myCamera); - } + // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm). + myBVHSelector.SetViewVolume (myCamera); - const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); - const Standard_Boolean isSameView = aManager->IsSameView (this); // force camera state update when needed + const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) { aManager->UpdateLightSourceStateTo (&myLights); myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); } - if (myProjectionState != myCamera->ProjectionState() - || !isSameView) + if (myWorldViewProjState != aWVPState) { - myProjectionState = myCamera->ProjectionState(); aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF()); - aContext->ApplyProjectionMatrix(); - } - - if (myModelViewState != myCamera->ModelViewState() - || !isSameView) - { - myModelViewState = myCamera->ModelViewState(); aContext->WorldViewState.SetCurrent (myCamera->OrientationMatrixF()); + aContext->ApplyProjectionMatrix(); aContext->ApplyWorldViewMatrix(); + myWorldViewProjState = aWVPState; } if (aManager->ModelWorldState().Index() == 0) @@ -319,6 +296,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); } + // ==================================== // Step 2: Redraw background // ==================================== diff --git a/src/OpenGl/OpenGl_Window.cxx b/src/OpenGl/OpenGl_Window.cxx index 57c8872b3b..c428289f45 100644 --- a/src/OpenGl/OpenGl_Window.cxx +++ b/src/OpenGl/OpenGl_Window.cxx @@ -19,9 +19,9 @@ #include #include #include -#include #include +#include #include #include @@ -789,7 +789,7 @@ void OpenGl_Window::ReadDepths (const Standard_Integer theX, const Standard_ return; OpenGl_Mat4 aProjectMat; - OpenGl_Utils::Ortho2D (aProjectMat, + Graphic3d_TransformUtils::Ortho2D (aProjectMat, 0.f, static_cast (myWidth), 0.f, static_cast (myHeight)); myGlContext->WorldViewState.Push(); diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index b93bd86b37..491b8b142d 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -29,11 +29,11 @@ #include #include #include -#include #include #include #include +#include #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) #include @@ -400,9 +400,9 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& OpenGl_Mat4 aTextureMat; const Graphic3d_Vec2& aScale = aParams->Scale(); const Graphic3d_Vec2& aTrans = aParams->Translation(); - OpenGl_Utils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); - OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); - OpenGl_Utils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f); + Graphic3d_TransformUtils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); + Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); + Graphic3d_TransformUtils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f); glLoadMatrixf (aTextureMat); GLint anEnvMode = GL_MODULATE; // lighting mode @@ -1147,7 +1147,7 @@ void OpenGl_Workspace::copyBackToFront() #if !defined(GL_ES_VERSION_2_0) OpenGl_Mat4 aProjectMat; - OpenGl_Utils::Ortho2D (aProjectMat, + Graphic3d_TransformUtils::Ortho2D (aProjectMat, 0.f, static_cast (myWidth), 0.f, static_cast (myHeight)); myGlContext->WorldViewState.Push(); diff --git a/src/OpenGl/OpenGl_transform_persistence.hxx b/src/OpenGl/OpenGl_transform_persistence.hxx deleted file mode 100644 index 6d14deb337..0000000000 --- a/src/OpenGl/OpenGl_transform_persistence.hxx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 1999-2014 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 OPENGL_TRANSFORM_PERSISTENCE_H -#define OPENGL_TRANSFORM_PERSISTENCE_H - -enum TP_FLAGS -{ - TPF_PAN = 0x001, - TPF_ZOOM = 0x002, - TPF_ROTATE = 0x008, - TPF_TRIEDRON = 0x020, - TPF_2D = 0x040, - TPF_2D_ISTOPDOWN = 0x041 -}; - -#endif /*OPENGL_TRANSFORM_PERSISTENCE_H*/ diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cdl b/src/PrsMgr/PrsMgr_PresentableObject.cdl index 5101695c75..0c64571119 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.cdl +++ b/src/PrsMgr/PrsMgr_PresentableObject.cdl @@ -62,7 +62,7 @@ uses TransModeFlags from Graphic3d, Pnt from gp, Trsf from gp, - CTransPersStruct from Graphic3d, + TransformPers from Graphic3d, ZLayerId from Graphic3d raises @@ -192,19 +192,21 @@ is GetTransformPersistenceMode( me ) returns TransModeFlags from Graphic3d is static; - ---Level: Public ---Purpose: Gets Transform Persistence Mode for this object ---Category: Graphic attributes management GetTransformPersistencePoint( me ) returns Pnt from gp is static; - ---Level: Public ---Purpose: Gets point of transform persistence for this object ---Category: Graphic attributes management - -- ABD 29/10/04 Transform Persistence of Presentation( pan, zoom, rotate ) - + + TransformPersistence(me) returns TransformPers from Graphic3d is static; + ---Purpose: @return transform persistence of the presentable object. + ---C++: inline + ---C++: return const& + SetTypeOfPresentation(me:mutable; aType: TypeOfPresentation3d from PrsMgr); SetToUpdate (me:mutable;aMode:Integer from Standard); @@ -321,14 +323,14 @@ is -- implementation propagate clip planes to every presentation. fields - myPresentations: Presentations from PrsMgr is protected; - myTypeOfPresentation3d: TypeOfPresentation3d from PrsMgr is protected; - myClipPlanes : SequenceOfHClipPlane from Graphic3d is protected; - myTransformPersistence : CTransPersStruct from Graphic3d; - myIsMutable : Boolean from Standard is protected; - myZLayer : ZLayerId from Graphic3d is protected; - - myHasOwnPresentations : Boolean from Standard is protected; -- shows if object should have own presentations. + myPresentations : Presentations from PrsMgr is protected; + myTypeOfPresentation3d : TypeOfPresentation3d from PrsMgr is protected; + myClipPlanes : SequenceOfHClipPlane from Graphic3d is protected; + myTransformPersistence : TransformPers from Graphic3d; + myIsMutable : Boolean from Standard is protected; + myZLayer : ZLayerId from Graphic3d is protected; + + myHasOwnPresentations : Boolean from Standard is protected; -- shows if object should have own presentations. myParent : PresentableObjectPointer from PrsMgr; -- Reference to parent object in scene hierarchy. diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cxx b/src/PrsMgr/PrsMgr_PresentableObject.cxx index d21b6588d9..df9c8f4572 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.cxx +++ b/src/PrsMgr/PrsMgr_PresentableObject.cxx @@ -34,10 +34,7 @@ PrsMgr_PresentableObject::PrsMgr_PresentableObject (const PrsMgr_TypeOfPresentat myHasOwnPresentations (Standard_True), myParent (NULL) { - myTransformPersistence.Flag = 0; - myTransformPersistence.Point.x = 0.0; - myTransformPersistence.Point.y = 0.0; - myTransformPersistence.Point.z = 0.0; + // } //======================================================================= @@ -302,10 +299,10 @@ void PrsMgr_PresentableObject::UpdateTransformation(const Handle(Prs3d_Presentat void PrsMgr_PresentableObject::SetTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint) { - myTransformPersistence.Flag = theFlag; - myTransformPersistence.Point.x = (Standard_ShortReal )thePoint.X(); - myTransformPersistence.Point.y = (Standard_ShortReal )thePoint.Y(); - myTransformPersistence.Point.z = (Standard_ShortReal )thePoint.Z(); + myTransformPersistence.Flags = theFlag; + myTransformPersistence.Point.x() = thePoint.X(); + myTransformPersistence.Point.y() = thePoint.Y(); + myTransformPersistence.Point.z() = thePoint.Z(); for (Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter) { const Handle(PrsMgr_Presentation)& aPrs3d = myPresentations (aPrsIter).Presentation(); @@ -332,18 +329,20 @@ void PrsMgr_PresentableObject::SetTransformPersistence( //function : GetTransformPersistence //purpose : //======================================================================= -Graphic3d_TransModeFlags PrsMgr_PresentableObject::GetTransformPersistenceMode() const +Graphic3d_TransModeFlags PrsMgr_PresentableObject::GetTransformPersistenceMode() const { - return myTransformPersistence.Flag; + return myTransformPersistence.Flags; } //======================================================================= //function : GetTransformPersistence //purpose : //======================================================================= -gp_Pnt PrsMgr_PresentableObject::GetTransformPersistencePoint() const +gp_Pnt PrsMgr_PresentableObject::GetTransformPersistencePoint() const { - return gp_Pnt( myTransformPersistence.Point.x, myTransformPersistence.Point.y, myTransformPersistence.Point.z ); + return gp_Pnt (myTransformPersistence.Point.x(), + myTransformPersistence.Point.y(), + myTransformPersistence.Point.z()); } //======================================================================= diff --git a/src/PrsMgr/PrsMgr_PresentableObject.lxx b/src/PrsMgr/PrsMgr_PresentableObject.lxx index 7beaf60f8e..352219e0ba 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.lxx +++ b/src/PrsMgr/PrsMgr_PresentableObject.lxx @@ -17,6 +17,10 @@ inline PrsMgr_TypeOfPresentation3d PrsMgr_PresentableObject::TypeOfPresentation3d() const {return myTypeOfPresentation3d;} +inline const Graphic3d_TransformPers& PrsMgr_PresentableObject::TransformPersistence() const +{ + return myTransformPersistence; +} inline const gp_Trsf& PrsMgr_PresentableObject::LocalTransformation() const { diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES index 9bf32bac46..166f85bd46 100755 --- a/src/SelectMgr/FILES +++ b/src/SelectMgr/FILES @@ -3,6 +3,8 @@ SelectMgr_FrustumBuilder.hxx SelectMgr_FrustumBuilder.cxx SelectMgr_SelectableObjectSet.hxx SelectMgr_SelectableObjectSet.cxx +SelectMgr_SelectableObjectTrsfPersSet.hxx +SelectMgr_SelectableObjectTrsfPersSet.cxx SelectMgr_BaseFrustum.hxx SelectMgr_BaseFrustum.cxx SelectMgr_Frustum.hxx diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index 62d6de3de9..6d22437985 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -33,8 +33,9 @@ SelectMgr_BaseFrustum::SelectMgr_BaseFrustum() //======================================================================= void SelectMgr_BaseFrustum::SetCamera (const Handle(Graphic3d_Camera)& theCamera) { - myBuilder->SetOrientation (theCamera->OrientationMatrix()); - myBuilder->SetProjection (theCamera->ProjectionMatrix()); + myBuilder->SetWorldViewMatrix (theCamera->OrientationMatrix()); + myBuilder->SetProjectionMatrix (theCamera->ProjectionMatrix()); + myBuilder->SetWorldViewProjState (theCamera->WorldViewProjState()); myIsOrthographic = theCamera->IsOrthographic(); myBuilder->InvalidateViewport(); } @@ -44,14 +45,46 @@ void SelectMgr_BaseFrustum::SetCamera (const Handle(Graphic3d_Camera)& theCamera // purpose : Passes camera projection and orientation matrices to builder //======================================================================= void SelectMgr_BaseFrustum::SetCamera (const Graphic3d_Mat4d& theProjection, - const Graphic3d_Mat4d& theOrientation, - const Standard_Integer theIsOrthographic) + const Graphic3d_Mat4d& theWorldView, + const Standard_Integer theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState) { - myBuilder->SetOrientation (theOrientation); - myBuilder->SetProjection (theProjection); + myBuilder->SetWorldViewMatrix (theWorldView); + myBuilder->SetProjectionMatrix (theProjection); + myBuilder->SetWorldViewProjState (theWVPState); myIsOrthographic = theIsOrthographic; } +//======================================================================= +// function : ProjectionMatrix +// purpose : Returns current camera projection transformation common for +// all selecting volumes +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_BaseFrustum::ProjectionMatrix() const +{ + return myBuilder->ProjectionMatrix(); +} + +//======================================================================= +// function : WorldViewMatrix +// purpose : Returns current camera world view transformation common for +// all selecting volumes +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_BaseFrustum::WorldViewMatrix() const +{ + return myBuilder->WorldViewMatrix(); +} + +//======================================================================= +// function : WorldViewProjState +// purpose : Returns current camera world view projection transformation +// state +//======================================================================= +const Graphic3d_WorldViewProjState& SelectMgr_BaseFrustum::WorldViewProjState() const +{ + return myBuilder->WorldViewProjState(); +} + //======================================================================= // function : SetViewport // purpose : Passes viewport parameters to builder diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index 0efa02be3b..99cd574b35 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -53,8 +54,18 @@ public: //! Passes camera projection and orientation matrices to builder void SetCamera (const Graphic3d_Mat4d& theProjection, - const Graphic3d_Mat4d& theOrientation, - const Standard_Integer theIsOrthographic); + const Graphic3d_Mat4d& theWorldView, + const Standard_Integer theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()); + + //! @return current camera projection transformation common for all selecting volumes + const Graphic3d_Mat4d& ProjectionMatrix() const; + + //! @return current camera world view transformation common for all selecting volumes + const Graphic3d_Mat4d& WorldViewMatrix() const; + + //! @return current camera world view projection transformation state + const Graphic3d_WorldViewProjState& WorldViewProjState() const; void SetPixelTolerance (const Standard_Real theTol); diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx index 91be420ac2..46b4b58ca8 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx @@ -26,30 +26,70 @@ IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_FrustumBuilder, Standard_Transient) // purpose : Creates new frustum builder with empty matrices //======================================================================= SelectMgr_FrustumBuilder::SelectMgr_FrustumBuilder() -: myOrientation(), +: myWorldView(), myProjection(), + myWorldViewProjState(), myWidth (INT_MAX), myHeight (INT_MAX), - myIsViewportSet (Standard_False) {} + myIsViewportSet (Standard_False) +{ + // +} //======================================================================= -// function : SetOrientation -// purpose : Stores current orientation matrix +// function : SetWorldViewMatrix +// purpose : Stores current world view transformation matrix //======================================================================= -void SelectMgr_FrustumBuilder::SetOrientation (const Graphic3d_Mat4d& theOrientation) +void SelectMgr_FrustumBuilder::SetWorldViewMatrix (const Graphic3d_Mat4d& theWorldView) { - myOrientation = theOrientation; + myWorldView = theWorldView; } //======================================================================= -// function : SetProjection +// function : WorldViewMatrix +// purpose : Returns current world view transformation matrix +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_FrustumBuilder::WorldViewMatrix() const +{ + return myWorldView; +} + +//======================================================================= +// function : SetProjectionMatrix // purpose : Stores current projection matrix //======================================================================= -void SelectMgr_FrustumBuilder::SetProjection (const Graphic3d_Mat4d& theProjection) +void SelectMgr_FrustumBuilder::SetProjectionMatrix (const Graphic3d_Mat4d& theProjection) { myProjection = theProjection; } +//======================================================================= +// function : ProjectionMatrix +// purpose : Returns current projection matrix +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_FrustumBuilder::ProjectionMatrix() const +{ + return myProjection; +} + +//======================================================================= +// function : SetWorldViewProjState +// purpose : Stores current world view projection matrix state +//======================================================================= +void SelectMgr_FrustumBuilder::SetWorldViewProjState (const Graphic3d_WorldViewProjState& theState) +{ + myWorldViewProjState = theState; +} + +//======================================================================= +// function : WorldViewProjState +// purpose : Returns current world view projection matrix state +//======================================================================= +const Graphic3d_WorldViewProjState& SelectMgr_FrustumBuilder::WorldViewProjState() const +{ + return myWorldViewProjState; +} + //======================================================================= // function : SetWindowSize // purpose : Stores current window width and height @@ -133,7 +173,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const Graphic3d_Mat4d aInvProj; // this case should never happen - if (!myOrientation.Inverted (aInvView) || !myProjection.Inverted (aInvProj)) + if (!myWorldView.Inverted (aInvView) || !myProjection.Inverted (aInvProj)) { return SelectMgr_Vec3 (0.0, 0.0, 0.0); } diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx index 8480454cea..bda502d5cb 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -31,11 +32,23 @@ public: //! Creates new frustum builder with empty matrices SelectMgr_FrustumBuilder(); - //! Stores current orientation matrix - void SetOrientation (const Graphic3d_Mat4d& theOrientation); + //! Stores current world view transformation matrix + void SetWorldViewMatrix (const Graphic3d_Mat4d& theWorldViewMatrix); + + //! @return current world view transformation matrix + const Graphic3d_Mat4d& WorldViewMatrix() const; //! Stores current projection matrix - void SetProjection (const Graphic3d_Mat4d& theProjection); + void SetProjectionMatrix (const Graphic3d_Mat4d& theProjection); + + //! @return current projection matrix + const Graphic3d_Mat4d& ProjectionMatrix() const; + + //! Stores current world view projection matrix state for the orientation and projection matrices + void SetWorldViewProjState (const Graphic3d_WorldViewProjState& theState); + + //! @return current world view projection state + const Graphic3d_WorldViewProjState& WorldViewProjState() const; //! Stores current window width and height void SetWindowSize (const Standard_Integer theWidth, @@ -70,8 +83,9 @@ private: private: - Graphic3d_Mat4d myOrientation; + Graphic3d_Mat4d myWorldView; Graphic3d_Mat4d myProjection; + Graphic3d_WorldViewProjState myWorldViewProjState; Standard_Integer myWidth; Standard_Integer myHeight; NCollection_Vec4 myViewport; diff --git a/src/SelectMgr/SelectMgr_SelectableObject.cxx b/src/SelectMgr/SelectMgr_SelectableObject.cxx index 3985350d93..320154fcee 100644 --- a/src/SelectMgr/SelectMgr_SelectableObject.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObject.cxx @@ -234,25 +234,20 @@ void SelectMgr_SelectableObject::ResetTransformation() PrsMgr_PresentableObject::ResetTransformation(); } - //======================================================================= //function : UpdateTransformation //purpose : //======================================================================= -void SelectMgr_SelectableObject::UpdateTransformation() +void SelectMgr_SelectableObject::UpdateTransformation() { - - Handle(Select3D_SensitiveEntity) SE; - for(Init();More();Next()){ - const Handle(SelectMgr_Selection) & Sel = CurrentSelection(); - Sel->UpdateStatus(SelectMgr_TOU_Partial); - Sel->UpdateBVHStatus (SelectMgr_TBU_Invalidate); + for (Init(); More(); Next()) + { + CurrentSelection()->UpdateStatus (SelectMgr_TOU_Partial); } - PrsMgr_PresentableObject::UpdateTransformation(); + PrsMgr_PresentableObject::UpdateTransformation(); } - //======================================================================= //function : UpdateTransformation //purpose : diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx index 91bc2632f1..b9c5cbd2d3 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx @@ -32,13 +32,18 @@ SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet() // function : Append // purpose : Adds new object to the set and marks BVH tree for rebuild //======================================================================= -void SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) +Standard_Boolean SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) { Standard_Integer aSize = Size(); + if (aSize < myObjects.Add (theObject)) { MarkDirty(); + + return Standard_True; } + + return Standard_False; } //======================================================================= @@ -46,7 +51,7 @@ void SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObj // purpose : Removes object theObject from set and marks BVH tree for // rebuild //======================================================================= -void SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) +Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) { const Standard_Integer anIndex = myObjects.FindIndex (theObject); @@ -60,7 +65,11 @@ void SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObj myObjects.RemoveLast(); MarkDirty(); + + return Standard_True; } + + return Standard_False; } //======================================================================= @@ -119,21 +128,3 @@ Standard_Integer SelectMgr_SelectableObjectSet::Size() const { return myObjects.Size(); } - -//======================================================================= -// function : GetObjectById -// purpose : Returns object from set by theIndex given -//======================================================================= -const Handle(SelectMgr_SelectableObject)& SelectMgr_SelectableObjectSet::GetObjectById (const Standard_Integer theIndex) const -{ - return myObjects.FindKey (theIndex + 1); -} - -//======================================================================= -// function : Contains -// purpose : Returns true if this objects set contains theObject given -//======================================================================= -Standard_Boolean SelectMgr_SelectableObjectSet::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const -{ - return myObjects.Contains (theObject); -} diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx index 671f99654f..bb7ad1596a 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx @@ -36,37 +36,45 @@ public: //! Creates new empty objects set and initializes BVH tree //! builder to Binned builder with 1 element per list - SelectMgr_SelectableObjectSet(); + Standard_EXPORT SelectMgr_SelectableObjectSet(); //! Releases resources of selectable object set. virtual ~SelectMgr_SelectableObjectSet() { } - //! Adds new object to the set and marks BVH tree for rebuild - void Append (const Handle(SelectMgr_SelectableObject)& theObject); + //! Adds new object to the set and marks BVH tree for rebuild. + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_EXPORT Standard_Boolean Append (const Handle(SelectMgr_SelectableObject)& theObject); - //! Removes object theObject from set and marks BVH tree for rebuild - void Remove (const Handle(SelectMgr_SelectableObject)& theObject); + //! Removes object theObject from set and marks BVH tree for rebuild. + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_EXPORT Standard_Boolean Remove (const Handle(SelectMgr_SelectableObject)& theObject); //! Returns bounding box of object with index theIndex - virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE; + Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE; //! Returns center of object with index theIndex in the set //! along the given axis theAxis - virtual Standard_Real Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const Standard_OVERRIDE; + Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIndex, + const Standard_Integer theAxis) const Standard_OVERRIDE; //! Swaps items with indexes theIndex1 and theIndex2 in the set - virtual void Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) Standard_OVERRIDE; + Standard_EXPORT virtual void Swap (const Standard_Integer theIndex1, + const Standard_Integer theIndex2) Standard_OVERRIDE; //! Returns size of objects set - virtual Standard_Integer Size() const Standard_OVERRIDE; + Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; //! Returns object from set by theIndex given - const Handle(SelectMgr_SelectableObject)& GetObjectById (const Standard_Integer theIndex) const; + const Handle(SelectMgr_SelectableObject)& GetObjectById (const Standard_Integer theIndex) const + { + return myObjects.FindKey (theIndex + 1); + } //! Returns true if this objects set contains theObject given - Standard_Boolean Contains (const Handle(SelectMgr_SelectableObject)& theObject) const; + Standard_Boolean Contains (const Handle(SelectMgr_SelectableObject)& theObject) const + { + return myObjects.Contains (theObject); + } private: diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx new file mode 100644 index 0000000000..2fc3b70515 --- /dev/null +++ b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx @@ -0,0 +1,173 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 + +#include +#include +#include + +//======================================================================= +// function : SelectMgr_SelectableObjectTrsfPersSet +// purpose : +//======================================================================= +SelectMgr_SelectableObjectTrsfPersSet::SelectMgr_SelectableObjectTrsfPersSet() +: myIsDirty (Standard_False), + myBVH (new BVH_Tree()) +{ + myBuilder = new BVH_LinearBuilder (1, 32); +} + +//======================================================================= +// function : Size +// purpose : +//======================================================================= +Standard_Integer SelectMgr_SelectableObjectTrsfPersSet::Size() const +{ + return myObjects.Size(); +} + +//======================================================================= +// function : Box +// purpose : +//======================================================================= +Select3D_BndBox3d SelectMgr_SelectableObjectTrsfPersSet::Box (const Standard_Integer theIndex) const +{ + return *myObjectBoxes (theIndex + 1); +} + +//======================================================================= +// function : Center +// purpose : +//======================================================================= +Standard_Real SelectMgr_SelectableObjectTrsfPersSet::Center (const Standard_Integer theIndex, + const Standard_Integer theAxis) const +{ + const Select3D_BndBox3d& aBndBox = *myObjectBoxes (theIndex + 1); + + return (aBndBox.CornerMin()[theAxis] + aBndBox.CornerMax()[theAxis]) * 0.5; +} + +//======================================================================= +// function : Swap +// purpose : +//======================================================================= +void SelectMgr_SelectableObjectTrsfPersSet::Swap (const Standard_Integer theIndex1, + const Standard_Integer theIndex2) +{ + const Standard_Integer aStructIdx1 = theIndex1 + 1; + const Standard_Integer aStructIdx2 = theIndex2 + 1; + + const Handle(SelectMgr_SelectableObject) anObj1 = myObjects.FindKey (aStructIdx1); + const Handle(SelectMgr_SelectableObject) anObj2 = myObjects.FindKey (aStructIdx2); + myObjects.Substitute (aStructIdx2, EMPTY_OBJ); + myObjects.Substitute (aStructIdx1, anObj2); + myObjects.Substitute (aStructIdx2, anObj1); + + const HBndBox3d aBox1 = myObjectBoxes.FindKey (aStructIdx1); + const HBndBox3d aBox2 = myObjectBoxes.FindKey (aStructIdx2); + myObjectBoxes.Substitute (aStructIdx2, EMPTY_BOX); + myObjectBoxes.Substitute (aStructIdx1, aBox2); + myObjectBoxes.Substitute (aStructIdx2, aBox1); +} + +//======================================================================= +// function : Append +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_SelectableObjectTrsfPersSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) +{ + Standard_Integer aSize = Size(); + + if (aSize < myObjects.Add (theObject)) + { + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +//======================================================================= +// function : Remove +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_SelectableObjectTrsfPersSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) +{ + const Standard_Integer anIndex = myObjects.FindIndex (theObject); + + if (anIndex != 0) + { + Swap (anIndex - 1, Size() - 1); + myObjects.RemoveLast(); + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +//======================================================================= +// function : BVH +// purpose : +//======================================================================= +const NCollection_Handle >& + SelectMgr_SelectableObjectTrsfPersSet::BVH (const Graphic3d_Mat4d& theProjectionMatrix, + const Graphic3d_Mat4d& theWorldViewMatrix, + const Graphic3d_WorldViewProjState& theWVPState) +{ + if (!myIsDirty && (myObjectBoxesState.IsValid() && !myObjectBoxesState.IsChanged(theWVPState))) + { + return myBVH; + } + + myObjectBoxes.ReSize (myObjects.Size()); + + for (Standard_Integer anObjectIdx = 1; anObjectIdx <= myObjects.Size(); ++anObjectIdx) + { + const Handle(SelectMgr_SelectableObject)& anObject = myObjects (anObjectIdx); + + Bnd_Box aBoundingBox; + + if (anObject->TransformPersistence().Flags && !(anObject->TransformPersistence().Flags & Graphic3d_TMF_2d)) + { + anObject->BoundingBox (aBoundingBox); + anObject->TransformPersistence().Apply (theProjectionMatrix, theWorldViewMatrix, 0, 0, aBoundingBox); + } + + if (aBoundingBox.IsVoid()) + { + myObjectBoxes.Add (new Select3D_BndBox3d()); + } + else + { + gp_Pnt aMin = aBoundingBox.CornerMin(); + gp_Pnt aMax = aBoundingBox.CornerMax(); + + myObjectBoxes.Add (new Select3D_BndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()), + Select3D_Vec3 (aMax.X(), aMax.Y(), aMax.Z()))); + } + } + + myBuilder->Build (this, myBVH.operator->(), BVH_Set::Box()); + + myObjectBoxesState = theWVPState; + myObjectBoxes.Clear(); + myIsDirty = Standard_False; + + return myBVH; +} diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx new file mode 100644 index 0000000000..e4c33127f0 --- /dev/null +++ b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx @@ -0,0 +1,117 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 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 _SelectMgr_SelectableObjectTrsfPersSet_HeaderFile +#define _SelectMgr_SelectableObjectTrsfPersSet_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! Primitive set specialized for transformation persistent selectable objects. +//! Provides built-in mechanism to invalidate tree when world view projection state changes. +//! Due to frequent invalidation of BVH tree the choice of BVH tree builder is made +//! in favor of BVH linear builder (quick rebuild). +class SelectMgr_SelectableObjectTrsfPersSet : public BVH_Set +{ +private: + + typedef NCollection_Handle HBndBox3d; + + Handle(SelectMgr_SelectableObject) EMPTY_OBJ; + + HBndBox3d EMPTY_BOX; + +public: + + //! Creates new empty objects set and initializes BVH tree + //! builder to Linear builder with 1 element per list. + Standard_EXPORT SelectMgr_SelectableObjectTrsfPersSet(); + + //! Returns size of objects set. + Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; + + //! Returns bounding box of object with index theIndex. + Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE; + + //! Returns center of object with index theIndex in the set along the given axis theAxis. + Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIndex, + const Standard_Integer theAxis) const Standard_OVERRIDE; + + //! Swaps items with indexes theIndex1 and theIndex2 in the set. + Standard_EXPORT virtual void Swap (const Standard_Integer theIndex1, + const Standard_Integer theIndex2) Standard_OVERRIDE; + + //! Adds new selectable object to the set. + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_EXPORT Standard_Boolean Append (const Handle(SelectMgr_SelectableObject)& theObject); + + //! Removes selectable object from set. + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_EXPORT Standard_Boolean Remove (const Handle(SelectMgr_SelectableObject)& theObject); + + //! Returns object from set by theIndex given. + const Handle(SelectMgr_SelectableObject)& GetObjectById (const Standard_Integer theIndex) const + { + return myObjects.FindKey (theIndex + 1); + } + + //! Marks object state as outdated (needs BVH rebuilding). + void MarkDirty() + { + myIsDirty = Standard_True; + } + + //! Returns true if this objects set contains theObject given + Standard_Boolean Contains (const Handle(SelectMgr_SelectableObject)& theObject) const + { + return myObjects.Contains (theObject); + } + + //! Returns BVH tree for the given world view projection (builds it if necessary). + const NCollection_Handle >& BVH (const Graphic3d_Mat4d& theProjectionMatrix, + const Graphic3d_Mat4d& theWorldViewMatrix, + const Graphic3d_WorldViewProjState& theWVPState); + +private: + + //! Marks internal object state as outdated. + Standard_Boolean myIsDirty; + + //! Constructed bottom-level BVH. + NCollection_Handle > myBVH; + + //! Builder for bottom-level BVH. + NCollection_Handle > myBuilder; + + //! Set of transform persistence objects. + NCollection_IndexedMap myObjects; + + //! Cached set of bounding boxes precomputed for transformation persistent selectable objects. + //! Cache exists only during computation of BVH Tree. Bounding boxes are world view projection + //! dependent and should by synchronized. + NCollection_IndexedMap myObjectBoxes; + + //! State of world view projection used for generation of transformation persistence bounding boxes. + Graphic3d_WorldViewProjState myObjectBoxesState; +}; + +#endif diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index aa1ff3ba70..a7bb82f478 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -106,15 +106,46 @@ void SelectMgr_SelectingVolumeManager::SetCamera (const Handle(Graphic3d_Camera) // selecting volumes //======================================================================= void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProjection, - const Graphic3d_Mat4d& theOrientation, - const Standard_Boolean theIsOrthographic) + const Graphic3d_Mat4d& theWorldView, + const Standard_Boolean theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState) { for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) { - mySelectingVolumes[anIdx]->SetCamera (theProjection, theOrientation, theIsOrthographic); + mySelectingVolumes[anIdx]->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState); } } +//======================================================================= +// function : ProjectionMatrix +// purpose : Returns current projection transformation common for all +// selecting volumes +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() const +{ + return mySelectingVolumes[Frustum]->ProjectionMatrix(); +} + +//======================================================================= +// function : WorldViewMatrix +// purpose : Returns current world view transformation common for all +// selecting volumes +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const +{ + return mySelectingVolumes[Frustum]->WorldViewMatrix(); +} + +//======================================================================= +// function : WorldViewProjState +// purpose : Returns current camera world view projection transformation +// state common for all selecting volumes +//======================================================================= +const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewProjState() const +{ + return mySelectingVolumes[Frustum]->WorldViewProjState(); +} + //======================================================================= // function : SetCamera // purpose : Updates viewport in all selecting volumes diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 6c6a7d7238..34e514ad24 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -53,8 +54,18 @@ public: //! Updates camera projection and orientation matrices in all selecting volumes Standard_EXPORT void SetCamera (const Graphic3d_Mat4d& theProjection, - const Graphic3d_Mat4d& theOrientation, - const Standard_Boolean theIsOrthographic); + const Graphic3d_Mat4d& theWorldView, + const Standard_Boolean theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()); + + //! @return current projection transformation common for all selecting volumes + Standard_EXPORT const Graphic3d_Mat4d& ProjectionMatrix() const; + + //! @return current world view transformation common for all selecting volumes + Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const; + + //! @return current camera world view projection transformation state common for all selecting volumes + Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const; //! Updates viewport in all selecting volumes Standard_EXPORT void SetViewport (const Standard_Real theX, diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 28a12000fc..12383904f2 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -150,10 +150,8 @@ myCurRank (0), myIsLeftChildQueuedFirst (Standard_False), myEntityIdx (0) { - mySelectableObjects = new SelectMgr_SelectableObjectSet(); } - //================================================== // Function: Activate // Purpose : @@ -172,7 +170,6 @@ void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theS myToUpdateTolerance = Standard_True; } - //================================================== // Function: Deactivate // Purpose : @@ -299,8 +296,32 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable const NCollection_Handle >& aSensitivesTree = anEntitySet->BVH(); - SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ? - mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr; + gp_Trsf aInversedTrsf; + + if (theObject->HasTransformation() || theObject->TransformPersistence().Flags) + { + if (!theObject->TransformPersistence().Flags) + { + aInversedTrsf = theObject->InversedTransformation(); + } + else + { + const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); + + gp_Trsf aTPers; + Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (aProjection, aWorldView, 0, 0); + aTPers.SetValues (aMat.GetValue (0, 0), aMat.GetValue (0, 1), aMat.GetValue (0, 2), aMat.GetValue (0, 3), + aMat.GetValue (1, 0), aMat.GetValue (1, 1), aMat.GetValue (1, 2), aMat.GetValue (1, 3), + aMat.GetValue (2, 0), aMat.GetValue (2, 1), aMat.GetValue (2, 2), aMat.GetValue (2, 3)); + + aInversedTrsf = (aTPers * theObject->Transformation()).Inverted(); + } + } + + SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity + ? mySelectingVolumeMgr.Transform (aInversedTrsf) + : mySelectingVolumeMgr; NCollection_DataMap aScaledTrnsfFrustums; @@ -362,7 +383,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable if (!aScaledTrnsfFrustums.IsBound (anEnt->DynamicType())) { aScaledTrnsfFrustums.Bind (anEnt->DynamicType(), - scaleAndTransform (anEnt->SensitivityFactor(), theObject->InversedTransformation())); + scaleAndTransform (anEnt->SensitivityFactor(), aInversedTrsf)); } aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType()); @@ -391,45 +412,86 @@ void SelectMgr_ViewerSelector::TraverseSensitives() mystored.Clear(); myMapOfDetected.Clear(); - if (mySelectableObjects->Size() == 0) - return; - - const NCollection_Handle >& anObjectsTree = mySelectableObjects->BVH(); - - Standard_Integer aNode = 0; - if (!mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (0), - anObjectsTree->MaxPoint (0))) - { - return; - } - Standard_Integer aStack[32]; - Standard_Integer aHead = -1; - for (;;) + NCollection_Handle > aBVHTree; + for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) { - if (!anObjectsTree->IsOuter (aNode)) + const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; + if (isTrsfPers) { - const Standard_Integer aLeftChildIdx = anObjectsTree->LeftChild (aNode); - const Standard_Integer aRightChildIdx = anObjectsTree->RightChild (aNode); - const Standard_Boolean isLeftChildIn = - mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aLeftChildIdx), - anObjectsTree->MaxPoint (aLeftChildIdx)); - const Standard_Boolean isRightChildIn = - mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aRightChildIdx), - anObjectsTree->MaxPoint (aRightChildIdx)); - if (isLeftChildIn - && isRightChildIn) + if (mySelectableObjectsTrsfPers.Size() == 0) { - aNode = aLeftChildIdx; - ++aHead; - aStack[aHead] = aRightChildIdx; + continue; } - else if (isLeftChildIn - || isRightChildIn) + const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); + const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); + aBVHTree = mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState); + } + else + { + if (mySelectableObjects.Size() == 0) { - aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + continue; + } + aBVHTree = mySelectableObjects.BVH(); + } + + Standard_Integer aNode = 0; + if (!mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (0), + aBVHTree->MaxPoint (0))) + { + continue; + } + + Standard_Integer aStack[32]; + Standard_Integer aHead = -1; + for (;;) + { + if (!aBVHTree->IsOuter (aNode)) + { + const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); + const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); + const Standard_Boolean isLeftChildIn = + mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), + aBVHTree->MaxPoint (aLeftChildIdx)); + const Standard_Boolean isRightChildIn = + mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), + aBVHTree->MaxPoint (aRightChildIdx)); + if (isLeftChildIn + && isRightChildIn) + { + aNode = aLeftChildIdx; + ++aHead; + aStack[aHead] = aRightChildIdx; + } + else if (isLeftChildIn + || isRightChildIn) + { + aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + } + else + { + if (aHead < 0) + { + break; + } + + aNode = aStack[aHead]; + --aHead; + } } else { + Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode); + Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode); + for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) + { + Handle(SelectMgr_SelectableObject) aSelectableObject = + isTrsfPers ? mySelectableObjectsTrsfPers.GetObjectById (anIdx) + : mySelectableObjects.GetObjectById (anIdx); + + traverseObject (aSelectableObject); + } if (aHead < 0) { break; @@ -439,22 +501,6 @@ void SelectMgr_ViewerSelector::TraverseSensitives() --aHead; } } - else - { - Standard_Integer aStartIdx = anObjectsTree->BegPrimitive (aNode); - Standard_Integer anEndIdx = anObjectsTree->EndPrimitive (aNode); - for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) - { - traverseObject (mySelectableObjects->GetObjectById (anIdx)); - } - if (aHead < 0) - { - break; - } - - aNode = aStack[aHead]; - --aHead; - } } SortResult(); @@ -548,7 +594,8 @@ Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_In //================================================== Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const { - return mySelectableObjects->Contains (theObject); + return mySelectableObjects.Contains (theObject) + || mySelectableObjectsTrsfPers.Contains (theObject); } //================================================== @@ -559,7 +606,7 @@ Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_Selecta TColStd_ListOfInteger& theModeList, const SelectMgr_StateOfSelection theWantedState) const { - Standard_Boolean hasActivatedStates = mySelectableObjects->Contains (theSelectableObject); + Standard_Boolean hasActivatedStates = Contains (theSelectableObject); for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) { if (theWantedState == SelectMgr_SOS_Any) @@ -582,7 +629,7 @@ Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_Selecta Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject, const Standard_Integer theMode) const { - if (!mySelectableObjects->Contains (theSelectableObject)) + if (!Contains (theSelectableObject)) return Standard_False; for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) @@ -603,7 +650,7 @@ Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_Sele Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject, const Standard_Integer theMode) const { - if (!mySelectableObjects->Contains (theSelectableObject)) + if (!Contains (theSelectableObject)) return Standard_False; for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) @@ -655,7 +702,7 @@ TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr } } - if (mySelectableObjects->Contains (theSelectableObject)) + if (!Contains (theSelectableObject)) { aStatus = aStatus + "Not Present in the selector\n\n"; } @@ -710,7 +757,15 @@ void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_Selec { if (!myMapOfObjectSensitives.IsBound (theObject)) { - mySelectableObjects->Append (theObject); + if (!theObject->TransformPersistence().Flags) + { + mySelectableObjects.Append (theObject); + } + else + { + mySelectableObjectsTrsfPers.Append (theObject); + } + NCollection_Handle anEntitySet = new SelectMgr_SensitiveEntitySet(); myMapOfObjectSensitives.Bind (theObject, anEntitySet); } @@ -745,8 +800,11 @@ void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_Se { if (myMapOfObjectSensitives.IsBound (theObject)) { + if (!mySelectableObjects.Remove (theObject)) + { + mySelectableObjectsTrsfPers.Remove (theObject); + } myMapOfObjectSensitives.UnBind (theObject); - mySelectableObjects->Remove (theObject); } } @@ -772,11 +830,17 @@ void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_S //======================================================================= void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce) { - mySelectableObjects->MarkDirty(); + mySelectableObjects.MarkDirty(); + mySelectableObjectsTrsfPers.MarkDirty(); if (theIsForce) { - mySelectableObjects->BVH(); + const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); + const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); + + mySelectableObjects.BVH(); + mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState); } } @@ -788,7 +852,7 @@ void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsF void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject, const Standard_Boolean theIsForce) { - if (!mySelectableObjects->Contains (theObject)) + if (!Contains (theObject)) return; NCollection_Handle& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject); diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx index 3f9def378b..6c558f32eb 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,7 @@ class SelectMgr_ToleranceMap public: //! Sets tolerance values to -1.0 - SelectMgr_ToleranceMap(); + Standard_EXPORT SelectMgr_ToleranceMap(); Standard_EXPORT ~SelectMgr_ToleranceMap(); @@ -132,7 +133,7 @@ public: Standard_EXPORT void Clear(); //! returns the Sensitivity of picking - Standard_Real Sensitivity() const; + Standard_EXPORT Standard_Real Sensitivity() const; //! Sorts the detected entites by priority and distance. //! to be redefined if other criterion are used... @@ -230,21 +231,21 @@ public: const Standard_Boolean theIsForce = Standard_False); //! Initializes internal iterator for stored detected sensitive entities - Standard_EXPORT void InitDetected(); + void InitDetected(); //! Makes a step along the map of detected sensitive entities and their owners - Standard_EXPORT void NextDetected(); + void NextDetected(); //! Returns true if iterator of map of detected sensitive entities has reached //! its end - Standard_EXPORT Standard_Boolean MoreDetected(); + Standard_Boolean MoreDetected(); //! Returns sensitive entity that was detected during the previous run of //! selection algorithm Standard_EXPORT const Handle(SelectBasics_SensitiveEntity)& DetectedEntity() const; //! Returns instance of selecting volume manager of the viewer selector - Standard_EXPORT SelectMgr_SelectingVolumeManager& GetManager(); + SelectMgr_SelectingVolumeManager& GetManager(); friend class SelectMgr_SelectionManager; @@ -269,23 +270,23 @@ protected: //! Internal function that checks if there is possible overlap //! between some entity of selectable object theObject and //! current selecting volume - void traverseObject (const Handle(SelectMgr_SelectableObject)& theObject); + Standard_EXPORT void traverseObject (const Handle(SelectMgr_SelectableObject)& theObject); //! Internal function that checks if a particular sensitive //! entity theEntity overlaps current selecting volume precisely - void checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity, - const Standard_Integer theEntityIdx, - SelectMgr_SelectingVolumeManager& theMgr); + Standard_EXPORT void checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity, + const Standard_Integer theEntityIdx, + SelectMgr_SelectingVolumeManager& theMgr); //! Marks all added sensitive entities of all objects as non-selectable - void resetSelectionActivationStatus(); + Standard_EXPORT void resetSelectionActivationStatus(); //! Checks if the entity given requires to scale current selecting frustum - Standard_Boolean isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity); + Standard_EXPORT Standard_Boolean isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity); //! Applies given scale and transformation matrices to the default selecting volume manager - SelectMgr_SelectingVolumeManager scaleAndTransform (const Standard_Real theScale, - const gp_Trsf& theTrsf); + Standard_EXPORT SelectMgr_SelectingVolumeManager scaleAndTransform (const Standard_Real theScale, + const gp_Trsf& theTrsf); private: @@ -298,13 +299,14 @@ private: protected: - Standard_Boolean preferclosest; - Standard_Real mytolerance; - Standard_Boolean myToUpdateTolerance; - SelectMgr_IndexedDataMapOfOwnerCriterion mystored; - SelectMgr_SelectingVolumeManager mySelectingVolumeMgr; - mutable NCollection_Handle mySelectableObjects; - SelectMgr_ToleranceMap myTolerances; + Standard_Boolean preferclosest; + Standard_Real mytolerance; + Standard_Boolean myToUpdateTolerance; + SelectMgr_IndexedDataMapOfOwnerCriterion mystored; + SelectMgr_SelectingVolumeManager mySelectingVolumeMgr; + mutable SelectMgr_SelectableObjectSet mySelectableObjects; + mutable SelectMgr_SelectableObjectTrsfPersSet mySelectableObjectsTrsfPers; + SelectMgr_ToleranceMap myTolerances; private: diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.cxx b/src/StdSelect/StdSelect_ViewerSelector3d.cxx index 3c0967bb07..581694cf6b 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.cxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.cxx @@ -182,39 +182,51 @@ void StdSelect_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline, //======================================================================= void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theView) { - // Preparation des structures - if (mystruct.IsNull()) + for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjects.Size(); ++anObjectIdx) { - mystruct = new Graphic3d_Structure (theView->Viewer()->Viewer()); + const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjects.GetObjectById (anObjectIdx); + + Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer()); + + for (anObj->Init(); anObj->More(); anObj->Next()) + { + if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated) + { + ComputeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), Graphic3d_TransformPers()); + } + } + + myStructs.Append (aStruct); } - if (mysensgroup.IsNull()) + for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjectsTrsfPers.Size(); ++anObjectIdx) { - mysensgroup = mystruct->NewGroup(); - } + const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjectsTrsfPers.GetObjectById (anObjectIdx); - Quantity_Color aColor (Quantity_NOC_INDIANRED3); - Handle(Graphic3d_AspectMarker3d) aMarkerAspect = - new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0); + Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer()); - mysensgroup->SetPrimitivesAspect (aMarkerAspect); - mysensgroup->SetPrimitivesAspect ( - new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0)); + if (!anObj->TransformPersistence().Flags || (anObj->TransformPersistence().Flags & Graphic3d_TMF_2d)) + { + continue; + } - for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjects->Size(); ++anObjectIdx) - { - const Handle (SelectMgr_SelectableObject)& anObject = mySelectableObjects->GetObjectById (anObjectIdx); - for (anObject->Init(); anObject->More(); anObject->Next()) + for (anObj->Init(); anObj->More(); anObj->Next()) { - if (anObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated) + if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated) { - ComputeSensitivePrs (anObject->CurrentSelection(), anObject->Transformation()); + ComputeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), anObj->TransformPersistence()); } } + + myStructs.Append (aStruct); } - mysensgroup->Structure()->SetDisplayPriority (10); - mystruct->Display(); + for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx) + { + Handle(Graphic3d_Structure)& aStruct = myStructs.ChangeValue (aStructIdx); + aStruct->SetDisplayPriority (10); + aStruct->Display(); + } theView->Update(); } @@ -225,19 +237,17 @@ void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theVi //======================================================================= void StdSelect_ViewerSelector3d::ClearSensitive (const Handle(V3d_View)& theView) { - if (mysensgroup.IsNull()) + for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx) { - return; + myStructs.Value (aStructIdx)->Remove(); } - mysensgroup->Clear(); + myStructs.Clear(); - if (theView.IsNull()) + if (!theView.IsNull()) { - return; + theView->Update(); } - - theView->Update(); } //======================================================================= @@ -249,32 +259,18 @@ void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(SelectMgr_Select const Handle(V3d_View)& theView, const Standard_Boolean theToClearOthers) { - if (mystruct.IsNull()) - { - mystruct = new Graphic3d_Structure (theView->Viewer()->Viewer()); - } - - if (mysensgroup.IsNull()) - { - mysensgroup = mystruct->NewGroup(); - Quantity_Color aColor (Quantity_NOC_INDIANRED3); - Handle(Graphic3d_AspectMarker3d) aMarkerAspect = - new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0); - - mysensgroup-> SetPrimitivesAspect (aMarkerAspect); - mysensgroup->SetPrimitivesAspect ( - new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0)); - } - if (theToClearOthers) { - mysensgroup->Clear(); + ClearSensitive (theView); } - ComputeSensitivePrs (theSel, theTrsf); + Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer()); - mystruct->SetDisplayPriority (10); - mystruct->Display(); + ComputeSensitivePrs (aStruct, theSel, theTrsf, Graphic3d_TransformPers()); + + myStructs.Append (aStruct); + myStructs.Last()->SetDisplayPriority (10); + myStructs.Last()->Display(); theView->Update(); } @@ -283,9 +279,30 @@ void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(SelectMgr_Select //function : ComputeSensitivePrs //purpose : //======================================================================= -void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(SelectMgr_Selection)& theSel, - const gp_Trsf& theLoc) +void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure, + const Handle(SelectMgr_Selection)& theSel, + const gp_Trsf& theLoc, + const Graphic3d_TransformPers& theTransPers) { + theStructure->SetTransformPersistence (theTransPers.Flags, gp_Pnt (theTransPers.Point.x(), + theTransPers.Point.y(), + theTransPers.Point.z())); + + Handle(Graphic3d_Group) aSensGroup = theStructure->NewGroup(); + + Quantity_Color aColor (Quantity_NOC_INDIANRED3); + Handle(Graphic3d_AspectMarker3d) aMarkerAspect = + new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0); + + aSensGroup->SetPrimitivesAspect (aMarkerAspect); + aSensGroup->SetPrimitivesAspect ( + new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0)); + + Handle(Graphic3d_Group) anAreaGroup = theStructure->NewGroup(); + + anAreaGroup->SetPrimitivesAspect ( + new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0)); + TColgp_SequenceOfPnt aSeqLines, aSeqFree; TColStd_SequenceOfInteger aSeqBnds; @@ -512,7 +529,7 @@ void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(SelectMgr_Sel Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theLoc); Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1); anArrayOfPoints->AddVertex (P.X(), P.Y(), P.Z()); - mysensgroup->AddPrimitiveArray (anArrayOfPoints); + aSensGroup->AddPrimitiveArray (anArrayOfPoints); } //============================================================ // Triangulation : On met un petit offset ves l'interieur... @@ -617,12 +634,12 @@ void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(SelectMgr_Sel aPrims->AddVertex(aSeqLines(i)); for (i = 1; i <= aSeqBnds.Length(); i++) aPrims->AddBound(aSeqBnds(i)); - myareagroup->AddPrimitiveArray(aPrims); + anAreaGroup->AddPrimitiveArray(aPrims); } if (aSeqFree.Length()) { - mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0)); + aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0)); Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqFree.Length(),aSeqFree.Length()/2); for (i = 1; i <= aSeqFree.Length(); i++) { @@ -630,8 +647,8 @@ void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(SelectMgr_Sel aPrims->AddVertex(aSeqLines(i++)); aPrims->AddVertex(aSeqLines(i)); } - mysensgroup->AddPrimitiveArray(aPrims); - mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0)); + aSensGroup->AddPrimitiveArray(aPrims); + aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0)); } } diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.hxx b/src/StdSelect/StdSelect_ViewerSelector3d.hxx index 86407bcfd5..10e670e036 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.hxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.hxx @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ class Graphic3d_Group; class Graphic3d_Structure; +class Graphic3d_TransformPers; class V3d_View; class TColgp_Array1OfPnt2d; class SelectMgr_EntityOwner; @@ -102,11 +104,12 @@ protected: private: - void ComputeSensitivePrs (const Handle(SelectMgr_Selection)& theSel, const gp_Trsf& theLoc); + void ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure, + const Handle(SelectMgr_Selection)& theSel, + const gp_Trsf& theLoc, + const Graphic3d_TransformPers& theTransPers); - Handle_Graphic3d_Group myareagroup; - Handle_Graphic3d_Group mysensgroup; - Handle_Graphic3d_Structure mystruct; + Graphic3d_SequenceOfStructure myStructs; Graphic3d_SequenceOfHClipPlane myClipPlanes; }; diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index dc78b59bd2..cf5d0aec05 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -3493,10 +3493,7 @@ static int VDisplay2 (Draw_Interpretor& theDI, ? aCtx->DisplayMode() : 0); Standard_Integer aSelMode = -1; - if ( isSelectable == 1 - || (isSelectable == -1 - && aCtx->GetAutoActivateSelection() - && aShape->GetTransformPersistenceMode() == 0)) + if (isSelectable == 1 || (isSelectable == -1 && aCtx->GetAutoActivateSelection())) { aSelMode = aShape->HasSelectionMode() ? aShape->SelectionMode() : -1; } diff --git a/src/Visual3d/Visual3d_View.cxx b/src/Visual3d/Visual3d_View.cxx index 164096e86d..aef2938705 100644 --- a/src/Visual3d/Visual3d_View.cxx +++ b/src/Visual3d/Visual3d_View.cxx @@ -1682,53 +1682,6 @@ Standard_Boolean Visual3d_View::ContainsFacet (const Graphic3d_MapOfStructure& t return Standard_False; } -//! Auxiliary method for MinMaxValues() method -inline void addStructureBndBox (const Handle(Graphic3d_Structure)& theStruct, - const Standard_Boolean theToIgnoreInfiniteFlag, - Bnd_Box& theBndBox) -{ - if (!theStruct->IsVisible()) - { - return; - } - else if (theStruct->IsInfinite() - && !theToIgnoreInfiniteFlag) - { - // XMin, YMin .... ZMax are initialized by means of infinite line data - const Bnd_Box aBox = theStruct->MinMaxValues (Standard_False); - if (!aBox.IsWhole() - && !aBox.IsVoid()) - { - theBndBox.Add (aBox); - } - return; - } - - // Only non-empty and non-infinite structures - // are taken into account for calculation of MinMax - if (theStruct->IsEmpty() - || theStruct->TransformPersistenceMode() != Graphic3d_TMF_None) - { - return; - } - - // "FitAll" operation ignores object with transform persistence parameter - const Bnd_Box aBox = theStruct->MinMaxValues (theToIgnoreInfiniteFlag); - - // To prevent float overflow at camera parameters calculation and further - // rendering, bounding boxes with at least one vertex coordinate out of - // float range are skipped by view fit algorithms - if (Abs (aBox.CornerMax().X()) >= ShortRealLast() || - Abs (aBox.CornerMax().Y()) >= ShortRealLast() || - Abs (aBox.CornerMax().Z()) >= ShortRealLast() || - Abs (aBox.CornerMin().X()) >= ShortRealLast() || - Abs (aBox.CornerMin().Y()) >= ShortRealLast() || - Abs (aBox.CornerMin().Z()) >= ShortRealLast()) - return; - - theBndBox.Add (aBox); -} - // ======================================================================== // function : MinMaxValues // purpose : @@ -1753,17 +1706,61 @@ Bnd_Box Visual3d_View::MinMaxValues (const Graphic3d_MapOfStructure& theSet, for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (theSet); aStructIter.More(); aStructIter.Next()) { const Handle(Graphic3d_Structure)& aStructure = aStructIter.Key(); - if (!aStructIter.Value()->IsVisible()) + if (!aStructure->IsVisible()|| aStructure->IsEmpty()) { continue; } - else if (!aStructIter.Value()->CStructure()->ViewAffinity.IsNull() - && !aStructIter.Value()->CStructure()->ViewAffinity->IsVisible (aViewId)) + else if (!aStructure->CStructure()->ViewAffinity.IsNull() + && !aStructure->CStructure()->ViewAffinity->IsVisible (aViewId)) + { + continue; + } + + // "FitAll" operation ignores object with transform persistence parameter + if (aStructure->TransformPersistence().Flags) + { + // Panning and 2d persistence apply changes to projection or/and its translation components. + // It makes them incompatible with z-fitting algorithm. Ignored by now. + if (!theToIgnoreInfiniteFlag || + (aStructure->TransformPersistence().Flags & Graphic3d_TMF_2d) || + (aStructure->TransformPersistence().Flags & Graphic3d_TMF_PanPers)) + { + continue; + } + } + + Bnd_Box aBox = aStructure->MinMaxValues (theToIgnoreInfiniteFlag); + + if (aBox.IsWhole() || aBox.IsVoid()) + { + continue; + } + + if (aStructure->TransformPersistence().Flags) + { + Standard_Integer aWidth, aHeight; + Window()->Size (aWidth, aHeight); + + const Graphic3d_Mat4d& aProjectionMat = MyCView.Context.Camera->ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = MyCView.Context.Camera->OrientationMatrix(); + + aStructure->TransformPersistence().Apply (aProjectionMat, aWorldViewMat, aWidth, aHeight, aBox); + } + + // To prevent float overflow at camera parameters calculation and further + // rendering, bounding boxes with at least one vertex coordinate out of + // float range are skipped by view fit algorithms + if (Abs (aBox.CornerMax().X()) >= ShortRealLast() || + Abs (aBox.CornerMax().Y()) >= ShortRealLast() || + Abs (aBox.CornerMax().Z()) >= ShortRealLast() || + Abs (aBox.CornerMin().X()) >= ShortRealLast() || + Abs (aBox.CornerMin().Y()) >= ShortRealLast() || + Abs (aBox.CornerMin().Z()) >= ShortRealLast()) { continue; } - addStructureBndBox (aStructure, theToIgnoreInfiniteFlag, aResult); + aResult.Add (aBox); } return aResult; } diff --git a/tests/bugs/vis/bug26344 b/tests/bugs/vis/bug26344 new file mode 100644 index 0000000000..8a2f5893f4 --- /dev/null +++ b/tests/bugs/vis/bug26344 @@ -0,0 +1,81 @@ +puts "============" +puts "CR26344" +puts "============" +puts "" + +########################################################################################## +puts "Visualization - provide a support of zoom persistent selection" +########################################################################################## + +vinit View1 w=409 h=409 +vtrihedron tri +vpan 50 50 + +box b1 50 50 50 +box b2 50 50 50 +box b3 100 100 100 +box b4 100 100 100 +box b5 100 100 100 + +# 1) Zoom persistence +vpoint p1 200 200 200 + +vdisplay b1 -trsfPers zoom -trsfPersPos 200 200 200 +vdisplay b2 -trsfPers zoom -trsfPersPos 200 200 200 +vsetlocation b2 -50 -50 -50 + +vmoveto 384 78 +if { ![checkcolor 384 78 0 1 1] } { + puts "Error picking zoom persistence object" +} + +vmoveto 356 96 +if { ![checkcolor 356 96 0 1 1] } { + puts "Error picking zoom persistent object with location" +} + +vselect 330 120 400 50 + +if { ![checkcolor 384 78 0.8 0.8 0.8] || ![checkcolor 356 96 0.8 0.8 0.8] } { + puts "Error selecting zoom persistence object(s)" +} + +# 2) Rotate persistence + +vdisplay b3 -trsfPers rotate -trsfPersPos -200 -200 -200 +vmoveto 160 200 +if { ![checkcolor 160 180 0 1 1] } { + puts "Error picking rotate persistence object" +} +vselect 130 230 190 170 +if { ![checkcolor 160 180 0.8 0.8 0.8] } { + puts "Error selecting rotate persistence object" +} + +# 3) Pan persistence + +vdisplay b4 -trsfPers pan +vmoveto 233 188 +if { ![checkcolor 233 188 0 1 1] } { + puts "Error picking pan persistence object" +} +vselect 200 230 270 140 +if { ![checkcolor 233 188 0.8 0.8 0.8] } { + puts "Error selecting pan persistence object" +} + +# 4) Trihedron persistence + +vdisplay b5 -trsfPers trihedron -trsfPersPos -1 -1 300 +vmoveto 90 300 +if { ![checkcolor 90 300 0 1 1] } { + puts "Error picking trihedron persistence object" +} +vselect 50 380 140 280 +if { ![checkcolor 90 300 0.8 0.8 0.8] } { + puts "Error selecting trihedron persistence object" +} + +vselect 50 380 400 50 + +set only_screen 1 \ No newline at end of file