From b7cd4ba79579b26f9be9de9a1ec08ea65201ceda Mon Sep 17 00:00:00 2001 From: vpa Date: Fri, 20 Jun 2014 11:26:14 +0400 Subject: [PATCH] 0024307: TKOpenGl - efficient culling of large number of presentations Implement SAT intersection tests and frustum culling algorithm using BVH trees. New Draw command vfrustumculling to manage frustum culling. Add test cases bugs/vis/bug24307_1 and bugs/vis/bug24307_2. Remove CALL_DEF_BOUNDBOX and CALL_DEF_BOUNDS. --- src/BVH/BVH_PrimitiveSet.hxx | 2 + src/Graphic3d/FILES | 3 +- src/Graphic3d/Graphic3d.cdl | 7 +- src/Graphic3d/Graphic3d_BndBox4d.hxx | 23 ++ src/Graphic3d/Graphic3d_BndBox4f.hxx | 23 ++ src/Graphic3d/Graphic3d_CBounds.hxx | 27 -- src/Graphic3d/Graphic3d_CStructure.cxx | 3 + src/Graphic3d/Graphic3d_CStructure.hxx | 32 +- src/Graphic3d/Graphic3d_CView.hxx | 10 +- src/Graphic3d/Graphic3d_GraphicDriver.cdl | 15 + src/Graphic3d/Graphic3d_Group.cdl | 20 +- src/Graphic3d/Graphic3d_Group.cxx | 103 +++-- src/Graphic3d/Graphic3d_Structure.cdl | 59 +-- src/Graphic3d/Graphic3d_Structure.cxx | 359 ++++++------------ .../InterfaceGraphic_Graphic3d.hxx | 29 +- src/NCollection/NCollection_Vec4.hxx | 2 +- src/OpenGl/FILES | 4 + src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx | 143 +++++++ src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx | 78 ++++ src/OpenGl/OpenGl_BVHTreeSelector.cxx | 283 ++++++++++++++ src/OpenGl/OpenGl_BVHTreeSelector.hxx | 117 ++++++ src/OpenGl/OpenGl_GraphicDriver.hxx | 9 + src/OpenGl/OpenGl_GraphicDriver_4.cxx | 18 + src/OpenGl/OpenGl_GraphicDriver_7.cxx | 13 + src/OpenGl/OpenGl_LayerList.cxx | 64 +++- src/OpenGl/OpenGl_LayerList.hxx | 12 +- src/OpenGl/OpenGl_PriorityList.cxx | 255 ++++++++++--- src/OpenGl/OpenGl_PriorityList.hxx | 56 ++- src/OpenGl/OpenGl_SceneGeometry.cxx | 7 +- src/OpenGl/OpenGl_SceneGeometry.hxx | 7 +- src/OpenGl/OpenGl_Structure.cxx | 49 ++- src/OpenGl/OpenGl_Structure.hxx | 32 ++ src/OpenGl/OpenGl_View.hxx | 16 + src/OpenGl/OpenGl_View_2.cxx | 38 ++ src/OpenGl/OpenGl_Workspace.cxx | 3 + src/OpenGl/OpenGl_Workspace.hxx | 5 + src/OpenGl/OpenGl_Workspace_Raytrace.cxx | 4 +- src/Prs3d/Prs3d_Presentation.cdl | 6 + src/Prs3d/Prs3d_Presentation.cxx | 9 + src/PrsMgr/PrsMgr_PresentableObject.cdl | 12 +- src/PrsMgr/PrsMgr_PresentableObject.cxx | 42 +- src/PrsMgr/PrsMgr_Presentation.cxx | 5 +- src/Standard/Standard_Real.hxx | 14 + src/V3d/V3d_View.cdl | 8 + src/V3d/V3d_View.cxx | 20 + src/ViewerTest/ViewerTest.cxx | 64 +++- src/ViewerTest/ViewerTest_ObjectCommands.cxx | 23 +- src/ViewerTest/ViewerTest_OpenGlCommands.cxx | 23 +- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 50 +++ src/Visual3d/Visual3d_View.cdl | 19 - src/Visual3d/Visual3d_View.cxx | 22 +- tests/bugs/vis/bug24307_1 | 82 ++++ tests/bugs/vis/bug24307_2 | 86 +++++ 53 files changed, 1881 insertions(+), 534 deletions(-) create mode 100644 src/Graphic3d/Graphic3d_BndBox4d.hxx create mode 100644 src/Graphic3d/Graphic3d_BndBox4f.hxx delete mode 100644 src/Graphic3d/Graphic3d_CBounds.hxx create mode 100644 src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx create mode 100644 src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx create mode 100644 src/OpenGl/OpenGl_BVHTreeSelector.cxx create mode 100644 src/OpenGl/OpenGl_BVHTreeSelector.hxx create mode 100644 tests/bugs/vis/bug24307_1 create mode 100644 tests/bugs/vis/bug24307_2 diff --git a/src/BVH/BVH_PrimitiveSet.hxx b/src/BVH/BVH_PrimitiveSet.hxx index ec414b2727..a1e7f4ca69 100644 --- a/src/BVH/BVH_PrimitiveSet.hxx +++ b/src/BVH/BVH_PrimitiveSet.hxx @@ -23,6 +23,8 @@ template class BVH_PrimitiveSet : public BVH_Object, public BVH_Set { +protected: + using BVH_Set::Box; public: diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 84af421dfc..96a87af006 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -1,3 +1,5 @@ +Graphic3d_BndBox4d.hxx +Graphic3d_BndBox4f.hxx Graphic3d_Buffer.hxx Graphic3d_Buffer_Handle.hxx Graphic3d_BoundBuffer.hxx @@ -18,7 +20,6 @@ Graphic3d_CBitFields4.hxx Graphic3d_CTexture.hxx Graphic3d_CLight.hxx Graphic3d_CPick.hxx -Graphic3d_CBounds.hxx Graphic3d_CUserDraw.hxx Graphic3d_CView.hxx Graphic3d_CGraduatedTrihedron.hxx diff --git a/src/Graphic3d/Graphic3d.cdl b/src/Graphic3d/Graphic3d.cdl index f1bf523b35..ab803157c5 100644 --- a/src/Graphic3d/Graphic3d.cdl +++ b/src/Graphic3d/Graphic3d.cdl @@ -347,6 +347,9 @@ is -- Category: Imported types --------------------------- + imported BndBox4f; + ---Purpose: Redefines BVH_Box for AABB representation + ---Category: Imported types imported Buffer; imported Buffer_Handle; imported BoundBuffer; @@ -354,6 +357,7 @@ is imported IndexBuffer; imported IndexBuffer_Handle; + imported BndBox4d; imported BufferType; imported CBitFields20; @@ -389,9 +393,6 @@ is imported CPlane; ---Category: Imported types - imported CBounds; - ---Category: Imported types - imported CUserDraw; ---Category: Imported types diff --git a/src/Graphic3d/Graphic3d_BndBox4d.hxx b/src/Graphic3d/Graphic3d_BndBox4d.hxx new file mode 100644 index 0000000000..90ec6fe0df --- /dev/null +++ b/src/Graphic3d/Graphic3d_BndBox4d.hxx @@ -0,0 +1,23 @@ +// Created on: 2014-04-09 +// Created by: Varvara POSKONINA +// 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 _Graphic3d_BndBox4d_HeaderFile +#define _Graphic3d_BndBox4d_HeaderFile + +#include + +typedef BVH_Box Graphic3d_BndBox4d; + +#endif // _Graphic3d_BndBox4d_HeaderFile diff --git a/src/Graphic3d/Graphic3d_BndBox4f.hxx b/src/Graphic3d/Graphic3d_BndBox4f.hxx new file mode 100644 index 0000000000..7a86c2a150 --- /dev/null +++ b/src/Graphic3d/Graphic3d_BndBox4f.hxx @@ -0,0 +1,23 @@ +// Created on: 2014-04-09 +// Created by: Varvara POSKONINA +// 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 _Graphic3d_BndBox4f_HeaderFile +#define _Graphic3d_BndBox4f_HeaderFile + +#include + +typedef BVH_Box Graphic3d_BndBox4f; + +#endif // _Graphic3d_BndBox4f_HeaderFile diff --git a/src/Graphic3d/Graphic3d_CBounds.hxx b/src/Graphic3d/Graphic3d_CBounds.hxx deleted file mode 100644 index f3b5cb8b2e..0000000000 --- a/src/Graphic3d/Graphic3d_CBounds.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. - -/*============================================================================*/ -/*==== Titre: Graphic3d_CBounds.hxx */ -/*==== Role : The header file of primitive type "CBounds" from Graphic3d */ -/*==== */ -/*==== Implementation: This is a primitive type implemented with typedef */ -/*============================================================================*/ - -#ifndef _Graphic3d_CBounds_HeaderFile -#define _Graphic3d_CBounds_HeaderFile - -#include -typedef CALL_DEF_BOUNDS Graphic3d_CBounds; - -#endif /*Graphic3d_CBounds_HeaderFile*/ diff --git a/src/Graphic3d/Graphic3d_CStructure.cxx b/src/Graphic3d/Graphic3d_CStructure.cxx index 7b4262ca0e..5f71832ada 100644 --- a/src/Graphic3d/Graphic3d_CStructure.cxx +++ b/src/Graphic3d/Graphic3d_CStructure.cxx @@ -37,6 +37,9 @@ Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureMana visible (1), pick (1), HLRValidation (0), + IsForHighlight (Standard_False), + IsMutable (Standard_False), + Is2dText (Standard_False), myGraphicDriver (theManager->GraphicDriver()) { for (Standard_Integer i = 0; i <= 3; ++i) diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index de97997c07..92fd2ff186 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -15,6 +15,7 @@ #ifndef _Graphic3d_CStructure_HeaderFile #define _Graphic3d_CStructure_HeaderFile +#include #include #include #include @@ -53,6 +54,19 @@ public: //! Pass clip planes to the associated graphic driver structure void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; } + //! @return bounding box of this presentation + const Graphic3d_BndBox4f& BoundingBox() const + { + return myBndBox; + } + + //! @return bounding box of this presentation + //! without transformation matrix applied + Graphic3d_BndBox4f& ChangeBoundingBox() + { + return myBndBox; + } + public: //! Update structure visibility state @@ -101,19 +115,22 @@ public: CALL_DEF_CONTEXTMARKER ContextMarker; CALL_DEF_CONTEXTTEXT ContextText; - CALL_DEF_BOUNDBOX BoundBox; + CALL_DEF_COLOR HighlightColor; float Transformation[4][4]; Graphic3d_TypeOfComposition Composition; int ContainsFacet; - unsigned IsInfinite : 1; - unsigned stick : 1; - unsigned highlight : 1; - unsigned visible : 1; - unsigned pick : 1; - unsigned HLRValidation : 1; + unsigned IsInfinite : 1; + unsigned stick : 1; + unsigned highlight : 1; + unsigned visible : 1; + unsigned pick : 1; + unsigned HLRValidation : 1; + unsigned IsForHighlight : 1; + unsigned IsMutable : 1; + unsigned Is2dText : 1; CALL_DEF_TRANSFORM_PERSISTENCE TransformPersistence; @@ -126,6 +143,7 @@ protected: Handle(Graphic3d_GraphicDriver) myGraphicDriver; Graphic3d_SequenceOfGroup myGroups; + Graphic3d_BndBox4f myBndBox; Graphic3d_SequenceOfHClipPlane myClipPlanes; public: diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx index e8d9e73b62..f329e76a7d 100644 --- a/src/Graphic3d/Graphic3d_CView.hxx +++ b/src/Graphic3d/Graphic3d_CView.hxx @@ -93,13 +93,14 @@ public: ptrUnderLayer (NULL), ptrOverLayer (NULL), Backfacing (0), - GContext (NULL), + GContext (NULL), GDisplayCB (NULL), GClientData (NULL), ptrFBO (NULL), - WasRedrawnGL (0) + WasRedrawnGL (0), + IsCullingEnabled (Standard_True) { - memset(&DefWindow,0,sizeof(DefWindow)); + memset (&DefWindow, 0, sizeof(DefWindow)); } public: @@ -134,6 +135,9 @@ public: //! Specifies rendering parameters and effects. Graphic3d_RenderingParams RenderParams; + //! Enables/disables frustum culling. + Standard_Boolean IsCullingEnabled; + }; #endif // Graphic3d_CView_HeaderFile diff --git a/src/Graphic3d/Graphic3d_GraphicDriver.cdl b/src/Graphic3d/Graphic3d_GraphicDriver.cdl index 140d92e9a2..c656e50cf4 100644 --- a/src/Graphic3d/Graphic3d_GraphicDriver.cdl +++ b/src/Graphic3d/Graphic3d_GraphicDriver.cdl @@ -643,6 +643,13 @@ is -- In contrast to Bitmaps, Vector graphics is scalable (so you may got quality benefits on printing to laser printer). -- Notice however that results may differ a lot and do not contain some elements. + InvalidateBVHData( me : mutable; + theCView : out CView from Graphic3d; + theLayerId : Integer from Standard ) + is deferred; + ---Purpose: + -- Marks BVH tree and the set of BVH primitives of correspondent priority list with id theLayerId as outdated. + AddZLayer( me : mutable; theCView : CView from Graphic3d; theLayerId : Integer from Standard ) @@ -696,6 +703,14 @@ is is deferred; ---Purpose: Sets the settings for a single Z layer of specified view. + ChangePriority( me : mutable; + theCStructure : CStructure from Graphic3d; + theCView : CView from Graphic3d; + theNewPriority : Integer from Standard ) + is deferred; + ---Purpose: Changes the priority of a structure within its Z layer + -- in the specified view. + ----------------------------- -- Category: Internal methods ----------------------------- diff --git a/src/Graphic3d/Graphic3d_Group.cdl b/src/Graphic3d/Graphic3d_Group.cdl index 19bee13a7c..10b640a955 100644 --- a/src/Graphic3d/Graphic3d_Group.cdl +++ b/src/Graphic3d/Graphic3d_Group.cdl @@ -90,7 +90,7 @@ deferred class Group from Graphic3d inherits TShared Buffer_Handle from Graphic3d, BoundBuffer_Handle from Graphic3d, TransModeFlags from Graphic3d, - CBounds from Graphic3d, + BndBox4f from Graphic3d, Ax2 from gp raises @@ -480,6 +480,22 @@ deferred class Group from Graphic3d inherits TShared -- XMin = YMin = ZMin = RealFirst (). -- XMax = YMax = ZMax = RealLast (). ---Category: Inquire methods + + BoundingBox ( me ) + returns BndBox4f from Graphic3d + is static; + ---Level: Public + ---Purpose: Returns boundary box of the group without transformation applied, + ---if it is specified for the structure. + ---C++: return const & + + ChangeBoundingBox ( me : mutable ) + returns BndBox4f from Graphic3d + is static; + ---Level: Public + ---Purpose: Returns non-const boundary box of the group without transformation applied, + ---if it is specified for the structure. + ---C++: return & Structure ( me ) returns Structure from Graphic3d @@ -534,7 +550,7 @@ deferred class Group from Graphic3d inherits TShared myStructure : StructurePtr from Graphic3d is protected; -- the min-max - myBounds : CBounds from Graphic3d is protected; + myBounds : BndBox4f from Graphic3d is protected; -- Identifies group forming closed volume. Used to filter groups for back face culling and capping algorithms. myIsClosed : Boolean from Standard is protected; diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx index 3547817fe3..1c64878f83 100644 --- a/src/Graphic3d/Graphic3d_Group.cxx +++ b/src/Graphic3d/Graphic3d_Group.cxx @@ -39,14 +39,6 @@ Graphic3d_Group::Graphic3d_Group (const Handle(Graphic3d_Structure)& theStruct) : myIsClosed (Standard_False) { - myBounds.XMin = ShortRealLast(); - myBounds.YMin = ShortRealLast(); - myBounds.ZMin = ShortRealLast(); - myBounds.XMax = ShortRealFirst(); - myBounds.YMax = ShortRealFirst(); - myBounds.ZMax = ShortRealFirst(); - - // // A small commentary on the usage of This! // // Graphic3d_Group is created in a structure. Graphic3d_Structure is a @@ -95,12 +87,7 @@ void Graphic3d_Group::Clear (Standard_Boolean theUpdateStructureMgr) ContextMarker.IsDef = 0, ContextFillArea.IsDef = 0; - myBounds.XMin = ShortRealLast(); - myBounds.YMin = ShortRealLast(); - myBounds.ZMin = ShortRealLast(); - myBounds.XMax = ShortRealFirst(); - myBounds.YMax = ShortRealFirst(); - myBounds.ZMax = ShortRealFirst(); + myBounds.Clear(); if (MyContainsFacet) { @@ -148,12 +135,7 @@ void Graphic3d_Group::Remove() Update(); - myBounds.XMin = ShortRealLast(); - myBounds.YMin = ShortRealLast(); - myBounds.ZMin = ShortRealLast(); - myBounds.XMax = ShortRealFirst(); - myBounds.YMax = ShortRealFirst(); - myBounds.ZMax = ShortRealFirst(); + myBounds.Clear(); MyIsEmpty = Standard_True; } @@ -188,11 +170,7 @@ Standard_Boolean Graphic3d_Group::IsEmpty() const return Standard_True; } - const Standard_ShortReal RL = ShortRealLast(); - const Standard_ShortReal RF = ShortRealFirst(); - const Standard_Boolean isEmpty = ((myBounds.XMin == RL) && (myBounds.YMin == RL) - && (myBounds.ZMin == RL) && (myBounds.XMax == RF) - && (myBounds.YMax == RF) && (myBounds.ZMax == RF)); + const Standard_Boolean isEmpty = myStructure->IsInfinite() ? Standard_False : !myBounds.IsValid(); if (isEmpty != MyIsEmpty) { ::Message::DefaultMessenger()->Send ("Graphic3d_Group: MyIsEmpty != IsEmpty()", Message_Trace); @@ -207,12 +185,14 @@ Standard_Boolean Graphic3d_Group::IsEmpty() const void Graphic3d_Group::SetMinMaxValues (const Standard_Real theXMin, const Standard_Real theYMin, const Standard_Real theZMin, const Standard_Real theXMax, const Standard_Real theYMax, const Standard_Real theZMax) { - myBounds.XMin = Standard_ShortReal (theXMin); - myBounds.YMin = Standard_ShortReal (theYMin); - myBounds.ZMin = Standard_ShortReal (theZMin); - myBounds.XMax = Standard_ShortReal (theXMax); - myBounds.YMax = Standard_ShortReal (theYMax); - myBounds.ZMax = Standard_ShortReal (theZMax); + myBounds.CornerMin() = Graphic3d_Vec4 (static_cast (theXMin), + static_cast (theYMin), + static_cast (theZMin), + 1.0f); + myBounds.CornerMax() = Graphic3d_Vec4 (static_cast (theXMax), + static_cast (theYMax), + static_cast (theZMax), + 1.0f); } // ======================================================================= @@ -248,14 +228,22 @@ void Graphic3d_Group::MinMaxCoord (Standard_Real& theXMin, Standard_Real& theYMi theXMin = theYMin = theZMin = ShortRealFirst(); theXMax = theYMax = theZMax = ShortRealLast(); } + else if (myBounds.IsValid()) + { + const Graphic3d_Vec4& aMinPt = myBounds.CornerMin(); + const Graphic3d_Vec4& aMaxPt = myBounds.CornerMax(); + theXMin = Standard_Real (aMinPt.x()); + theYMin = Standard_Real (aMinPt.y()); + theZMin = Standard_Real (aMinPt.z()); + theXMax = Standard_Real (aMaxPt.x()); + theYMax = Standard_Real (aMaxPt.y()); + theZMax = Standard_Real (aMaxPt.z()); + } else { - theXMin = Standard_Real (myBounds.XMin); - theYMin = Standard_Real (myBounds.YMin); - theZMin = Standard_Real (myBounds.ZMin); - theXMax = Standard_Real (myBounds.XMax); - theYMax = Standard_Real (myBounds.YMax); - theZMax = Standard_Real (myBounds.ZMax); + // for consistency with old API + theXMin = theYMin = theZMin = ShortRealLast(); + theXMax = theYMax = theZMax = ShortRealFirst(); } } @@ -1039,10 +1027,7 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter) { const Graphic3d_Vec2& aVert = *reinterpret_cast(theAttribs->value (aVertIter) + anOffset); - if (aVert.x() < myBounds.XMin) myBounds.XMin = aVert.x(); - if (aVert.y() < myBounds.YMin) myBounds.YMin = aVert.y(); - if (aVert.x() > myBounds.XMax) myBounds.XMax = aVert.x(); - if (aVert.y() > myBounds.YMax) myBounds.YMax = aVert.y(); + myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), 0.0f, 1.0f)); } break; } @@ -1052,12 +1037,7 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter) { const Graphic3d_Vec3& aVert = *reinterpret_cast(theAttribs->value (aVertIter) + anOffset); - if (aVert.x() < myBounds.XMin) myBounds.XMin = aVert.x(); - if (aVert.y() < myBounds.YMin) myBounds.YMin = aVert.y(); - if (aVert.z() < myBounds.ZMin) myBounds.ZMin = aVert.z(); - if (aVert.x() > myBounds.XMax) myBounds.XMax = aVert.x(); - if (aVert.y() > myBounds.YMax) myBounds.YMax = aVert.y(); - if (aVert.z() > myBounds.ZMax) myBounds.ZMax = aVert.z(); + myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), aVert.z(), 1.0f)); } break; } @@ -1130,12 +1110,11 @@ void Graphic3d_Group::Text (const Standard_CString /*theText*/, { Standard_ShortReal x, y, z; thePoint.Coord (x, y, z); - if (x < myBounds.XMin) myBounds.XMin = x; - if (y < myBounds.YMin) myBounds.YMin = y; - if (z < myBounds.ZMin) myBounds.ZMin = z; - if (x > myBounds.XMax) myBounds.XMax = x; - if (y > myBounds.YMax) myBounds.YMax = y; - if (z > myBounds.ZMax) myBounds.ZMax = z; + myStructure->CStructure()->Is2dText = Standard_True; + myBounds.Add (Graphic3d_Vec4 (static_cast (x), + static_cast (y), + static_cast (z), + 1.0f)); } Update(); } @@ -1202,3 +1181,21 @@ Standard_Boolean Graphic3d_Group::IsClosed() const { return myIsClosed; } + +//======================================================================= +//function : BoundingBox +//purpose : +//======================================================================= +const Graphic3d_BndBox4f& Graphic3d_Group::BoundingBox() const +{ + return myBounds; +} + +//======================================================================= +//function : ChangeBoundingBox +//purpose : +//======================================================================= +Graphic3d_BndBox4f& Graphic3d_Group::ChangeBoundingBox() +{ + return myBounds; +} diff --git a/src/Graphic3d/Graphic3d_Structure.cdl b/src/Graphic3d/Graphic3d_Structure.cdl index 7134dfc6d4..f0231affd9 100644 --- a/src/Graphic3d/Graphic3d_Structure.cdl +++ b/src/Graphic3d/Graphic3d_Structure.cdl @@ -71,7 +71,9 @@ uses Vertex from Graphic3d, TransModeFlags from Graphic3d, Pnt from gp, - SequenceOfHClipPlane from Graphic3d + SequenceOfHClipPlane from Graphic3d, + BndBox4f from Graphic3d, + BndBox4d from Graphic3d raises @@ -210,6 +212,12 @@ is -- Warning: No more graphic operations in after this call. -- Category: Methods to modify the class definition + CalculateBoundBox ( me : mutable ) + is static; + ---Level: Public + ---Purpose: Computes axis-aligned bounding box of a structure. + -- Category: Methods to modify the class definition + SetHighlightColor ( me : mutable; AColor : Color from Quantity ) is static; @@ -358,6 +366,14 @@ is -- is a negative value. raises StructureDefinitionError from Graphic3d is static; + SetIsForHighlight ( me : mutable; + isForHighlight : Boolean from Standard ) + is static; + ---Level: Internal + ---Purpose: marks the structure representing wired structure needed for + -- highlight only so it won't be added to BVH tree. + -- Category: Methods to modify the class definition + UnHighlight ( me : mutable ) is static; ---Level: Public @@ -810,6 +826,17 @@ is ---Purpose: Get the current point of relative modelling transform persistence is static; + SetMutable ( me : mutable; + theIsMutable : Boolean from Standard ) + is static; + ---Purpose: Sets if the structure location has mutable nature (content or location will be changed regularly). + + IsMutable ( me ) + returns Boolean from Standard + is static; + ---Purpose: Returns true if structure has mutable nature (content or location are be changed regularly). + -- Mutable structure will be managed in different way than static onces. + ---------------------------- -- Category: Private methods ---------------------------- @@ -878,28 +905,16 @@ is ---Purpose: Returns the identification number of the structure . ---Category: Private methods - MinMaxCoord (me; - theXMin, theYMin, theZMin : out Real from Standard; - theXMax, theYMax, theZMax : out Real from Standard) - is static private; - ---Level: Internal - ---Purpose: Returns the extreme coordinates found in the structure . - -- Warning: If the structure is empty or infinite then : - -- theXMin = theYMin = theZMin = RealFirst(). - -- theXMax = theYMax = theZMax = RealLast(). - ---Category: Private methods + minMaxCoord (me; + theToIgnoreInfiniteFlag : Boolean from Standard = Standard_False) + returns BndBox4f from Graphic3d + is static private; + ---Purpose: Returns the extreme coordinates found in the structure without transformation applied. - MinMaxCoordWithDescendants (me; - theXMin, theYMin, theZMin : out Real from Standard; - theXMax, theYMax, theZMax : out Real from Standard) - is static private; - ---Level: Internal - ---Purpose: Returns the extreme coordinates found in the structure - -- and its descendants with transformation applied. - -- Warning: If the structure is empty or infinite then : - -- theXMin = theYMin = theZMin = RealFirst(). - -- theXMax = theYMax = theZMax = RealLast(). - ---Category: Private methods + addTransformed (me; + theBox : out BndBox4d from Graphic3d; + theToIgnoreInfiniteFlag : Boolean from Standard = Standard_False) + is static private; PrintNetwork ( myclass; AStructure : Structure from Graphic3d; diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index 6425246765..884967a9af 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -114,6 +114,32 @@ void Graphic3d_Structure::Clear (const Standard_Boolean theWithDestruction) Update(); } +//======================================================================= +//function : CalculateBoundBox +//purpose : Calculates AABB of a structure. +//======================================================================= +void Graphic3d_Structure::CalculateBoundBox() +{ + Graphic3d_BndBox4d aBox; + addTransformed (aBox, Standard_True); + if (aBox.IsValid() && myCStructure->TransformPersistence.Flag == 0) + { + Graphic3d_Vec4 aMinPt (RealToShortReal (aBox.CornerMin().x()), + RealToShortReal (aBox.CornerMin().y()), + RealToShortReal (aBox.CornerMin().z()), + 1.0f); + Graphic3d_Vec4 aMaxPt (RealToShortReal (aBox.CornerMax().x()), + RealToShortReal (aBox.CornerMax().y()), + RealToShortReal (aBox.CornerMax().z()), + 1.0f); + myCStructure->ChangeBoundingBox() = Graphic3d_BndBox4f (aMinPt, aMaxPt); + } + else + { + myCStructure->ChangeBoundingBox().Clear(); + } +} + //============================================================================= //function : Remove //purpose : @@ -150,8 +176,6 @@ void Graphic3d_Structure::Remove() ((Graphic3d_Structure *)(myAncestors.ChangeValue (aStructIter)))->Remove (APtr, Graphic3d_TOC_DESCENDANT); } - myCStructure->ContainsFacet = 0; - // Destruction of me in the graphic library const Standard_Integer aStructId = myCStructure->Id; myCStructure->GraphicDriver()->RemoveStructure (myCStructure); @@ -182,6 +206,15 @@ void Graphic3d_Structure::Display() myCStructure->visible = 1; } +//============================================================================= +//function : SetIsForHighlight +//purpose : +//============================================================================= +void Graphic3d_Structure::SetIsForHighlight (const Standard_Boolean isForHighlight) +{ + myCStructure->IsForHighlight = isForHighlight; +} + //============================================================================= //function : Display //purpose : @@ -1375,6 +1408,7 @@ void Graphic3d_Structure::Connect (const Handle(Graphic3d_Structure)& theStructu } myDescendants.Append (theStructure.operator->()); + CalculateBoundBox(); theStructure->Connect (this, Graphic3d_TOC_ANCESTOR); GraphicConnect (theStructure); @@ -1395,6 +1429,7 @@ void Graphic3d_Structure::Connect (const Handle(Graphic3d_Structure)& theStructu } myAncestors.Append (theStructure.operator->()); + CalculateBoundBox(); theStructure->Connect (this, Graphic3d_TOC_DESCENDANT); // myGraphicDriver->Connect is called in case if connection between parent and child @@ -1422,6 +1457,8 @@ void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStru GraphicDisconnect (theStructure); myStructureManager->Disconnect (this, theStructure); + CalculateBoundBox(); + Update(); return; } @@ -1434,6 +1471,7 @@ void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStru { myAncestors.Remove (anIter); theStructure->Disconnect (this); + CalculateBoundBox(); // no call of myGraphicDriver->Disconnect in case of an ancestor return; } @@ -1608,6 +1646,7 @@ void Graphic3d_Structure::Transform (TColStd_Array2OfReal& theMatrix) const } } + //============================================================================= //function : MinMaxValues //purpose : @@ -1620,89 +1659,9 @@ void Graphic3d_Structure::MinMaxValues (Standard_Real& theXMin, Standard_Real& theZMax, const Standard_Boolean theToIgnoreInfiniteFlag) const { - if (IsEmpty()) - { - return; - } - - Standard_Real aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; - MinMaxCoord (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - - // Infinite boundaries corresponding to empty structure or - // non-empty structure, without any primitives specified - if (aXMin == RealFirst() && aYMin == RealFirst() && aZMin == RealFirst() && - aXMax == RealLast() && aYMax == RealLast() && aZMax == RealLast()) - { - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); - return; - } - - // Handle flag, which specifies that structure should be considered as infinite - if (IsInfinite() && !theToIgnoreInfiniteFlag) - { - Graphic3d_Vertex aVertexMin (aXMin, aYMin, aZMin); - Graphic3d_Vertex aVertexMax (aXMax, aYMax, aZMax); - const Standard_Real aDistance = aVertexMin.Distance (aVertexMax); - - // Special case for infinite line: - // Bounding borders of infinite line has been - // calculated as own point in center of this line - if (aDistance >= 500000.0) - { - theXMin = theXMax = 0.5 * (aXMin + aXMax); - theYMin = theYMax = 0.5 * (aYMin + aYMax); - theZMin = theZMax = 0.5 * (aZMin + aZMax); - return; - } - - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); - return; - } - - // Min-Max values of the descendant structures - Standard_Real aDescXMin = RealLast(); - Standard_Real aDescYMin = RealLast(); - Standard_Real aDescZMin = RealLast(); - Standard_Real aDescXMax = RealFirst(); - Standard_Real aDescYMax = RealFirst(); - Standard_Real aDescZMax = RealFirst(); - for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); aStructIt++) - { - Graphic3d_Structure* aStructure = (Graphic3d_Structure*) myDescendants.Value (aStructIt); - aStructure->MinMaxValues (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - aDescXMin = Min (aXMin, aDescXMin); - aDescYMin = Min (aYMin, aDescYMin); - aDescZMin = Min (aZMin, aDescZMin); - aDescXMax = Max (aXMax, aDescXMax); - aDescYMax = Max (aYMax, aDescYMax); - aDescZMax = Max (aZMax, aDescZMax); - } - - if (aDescXMin != RealLast() || aDescYMin != RealLast() || - aDescZMin != RealLast() || aDescXMax != RealFirst() || - aDescYMax != RealFirst() || aDescZMax != RealFirst()) - { - aXMin = Min (aDescXMin, aXMin); - aYMin = Min (aDescYMin, aYMin); - aZMin = Min (aDescZMin, aZMin); - aXMax = Max (aDescXMax, aXMax); - aYMax = Max (aDescYMax, aYMax); - aZMax = Max (aDescZMax, aZMax); - } - - // Case impossible as it would mean that the structure is empty or infinite - if (aXMin == RealFirst() && aYMin == RealFirst() && aZMin == RealFirst() && - aXMax == RealLast() && aYMax == RealLast() && aZMax == RealLast()) + Graphic3d_BndBox4d aBox; + addTransformed (aBox, theToIgnoreInfiniteFlag); + if (!aBox.IsValid()) { theXMin = RealFirst(); theYMin = RealFirst(); @@ -1713,15 +1672,12 @@ void Graphic3d_Structure::MinMaxValues (Standard_Real& theXMin, return; } - TColStd_Array2OfReal aTrsf(0, 3, 0, 3); - Transform (aTrsf); - TransformBoundaries (aTrsf, aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - theXMin = aXMin; - theYMin = aYMin; - theZMin = aZMin; - theXMax = aXMax; - theYMax = aYMax; - theZMax = aZMax; + theXMin = aBox.CornerMin().x(); + theYMin = aBox.CornerMin().y(); + theZMin = aBox.CornerMin().z(); + theXMax = aBox.CornerMax().x(); + theYMax = aBox.CornerMax().y(); + theZMax = aBox.CornerMax().z(); } //============================================================================= @@ -1756,6 +1712,7 @@ void Graphic3d_Structure::SetTransformPersistence (const Graphic3d_TransModeFlag myCStructure->TransformPersistence.Point.y = float (thePoint.Y()); myCStructure->TransformPersistence.Point.z = float (thePoint.Z()); myCStructure->UpdateAspects(); + CalculateBoundBox(); myCStructure->TransformPersistence.IsSet = 1; } @@ -1855,154 +1812,79 @@ Handle(Graphic3d_StructureManager) Graphic3d_Structure::StructureManager() const } //============================================================================= -//function : MinMaxCoord +//function : minMaxCoord //purpose : //============================================================================= -void Graphic3d_Structure::MinMaxCoord (Standard_Real& theXMin, - Standard_Real& theYMin, - Standard_Real& theZMin, - Standard_Real& theXMax, - Standard_Real& theYMax, - Standard_Real& theZMax) const +Graphic3d_BndBox4f Graphic3d_Structure::minMaxCoord (const Standard_Boolean theToIgnoreInfiniteFlag) const { - if (IsEmpty()) - { - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); - return; - } - - Standard_Real aXMin = RealLast(); - Standard_Real aYMin = RealLast(); - Standard_Real aZMin = RealLast(); - Standard_Real aXMax = RealFirst(); - Standard_Real aYMax = RealFirst(); - Standard_Real aZMax = RealFirst(); - Standard_Real aGroupXMin, aGroupYMin, aGroupZMin, aGroupXMax, aGroupYMax, aGroupZMax; + Graphic3d_BndBox4f aBnd; for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myCStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) { - const Handle(Graphic3d_Group)& aGroup = aGroupIter.Value(); - if (aGroup->IsEmpty()) + if (!theToIgnoreInfiniteFlag) { - continue; + aBnd.Combine (aGroupIter.Value()->BoundingBox()); + } + else + { + Graphic3d_BndBox4f aValidBnd (aGroupIter.Value()->BoundingBox().CornerMin(), + aGroupIter.Value()->BoundingBox().CornerMax()); + aBnd.Combine (aValidBnd); } - - aGroup->MinMaxValues (aGroupXMin, aGroupYMin, aGroupZMin, aGroupXMax, aGroupYMax, aGroupZMax); - aXMin = Min (aXMin, aGroupXMin); - aYMin = Min (aYMin, aGroupYMin); - aZMin = Min (aZMin, aGroupZMin); - aXMax = Max (aXMax, aGroupXMax); - aYMax = Max (aYMax, aGroupYMax); - aZMax = Max (aZMax, aGroupZMax); - } - - // Case impossible as it would mean that the structure is empty - if (aXMin == RealLast() && aYMin == RealLast() && aZMin == RealLast() && - aXMax == RealFirst() && aYMax == RealFirst() && aZMax == RealFirst()) - { - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); } - - theXMin = aXMin; - theYMin = aYMin; - theZMin = aZMin; - theXMax = aXMax; - theYMax = aYMax; - theZMax = aZMax; + return aBnd; } //============================================================================= -//function : MinMaxCoordWithDescendants +//function : addTransformed //purpose : //============================================================================= -void Graphic3d_Structure::MinMaxCoordWithDescendants (Standard_Real& theXMin, - Standard_Real& theYMin, - Standard_Real& theZMin, - Standard_Real& theXMax, - Standard_Real& theYMax, - Standard_Real& theZMax) const +void Graphic3d_Structure::addTransformed (Graphic3d_BndBox4d& theBox, + const Standard_Boolean theToIgnoreInfiniteFlag) const { - if (IsEmpty()) + Graphic3d_BndBox4d aBox; + Graphic3d_BndBox4f aBoxF = minMaxCoord (theToIgnoreInfiniteFlag); + if (aBoxF.IsValid()) { - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); - return; - } - - Standard_Real aXMin, aYMin, aZMin, aXMax, aYMax, aZMax; - MinMaxCoord (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - - // Min-Max of the descendant structures - Standard_Real aDescXMin = RealLast(); - Standard_Real aDescYMin = RealLast(); - Standard_Real aDescZMin = RealLast(); - Standard_Real aDescXMax = RealFirst(); - Standard_Real aDescYMax = RealFirst(); - Standard_Real aDescZMax = RealFirst(); - for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); aStructIt++) - { - Graphic3d_Structure* aStructure = (Graphic3d_Structure*) myDescendants.Value (aStructIt); - if (aStructure->IsEmpty()) + aBox = Graphic3d_BndBox4d (Graphic3d_Vec4d ((Standard_Real )aBoxF.CornerMin().x(), + (Standard_Real )aBoxF.CornerMin().y(), + (Standard_Real )aBoxF.CornerMin().z(), + (Standard_Real )aBoxF.CornerMin().w()), + Graphic3d_Vec4d ((Standard_Real )aBoxF.CornerMax().x(), + (Standard_Real )aBoxF.CornerMax().y(), + (Standard_Real )aBoxF.CornerMax().z(), + (Standard_Real )aBoxF.CornerMax().w())); + if (IsInfinite() + && !theToIgnoreInfiniteFlag) { - continue; + const Graphic3d_Vec4d aDiagVec = aBox.CornerMax() - aBox.CornerMin(); + if (aDiagVec.xyz().SquareModulus() >= 500000.0 * 500000.0) + { + // bounding borders of infinite line has been calculated as own point in center of this line + aBox = Graphic3d_BndBox4d ((aBox.CornerMin() + aBox.CornerMax()) * 0.5); + } + else + { + theBox = Graphic3d_BndBox4d (Graphic3d_Vec4d (RealFirst(), RealFirst(), RealFirst(), 1.0), + Graphic3d_Vec4d (RealLast(), RealLast(), RealLast(), 1.0)); + return; + } } - - aStructure->MinMaxCoordWithDescendants (aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - aDescXMin = Min (aXMin, aDescXMin); - aDescYMin = Min (aYMin, aDescYMin); - aDescZMin = Min (aZMin, aDescZMin); - aDescXMax = Max (aXMax, aDescXMax); - aDescYMax = Max (aYMax, aDescYMax); - aDescZMax = Max (aZMax, aDescZMax); } - if (aDescXMin != RealLast() || aDescYMin != RealLast() || - aDescZMin != RealLast() || aDescXMax != RealFirst() || - aDescYMax != RealFirst() || aDescZMax != RealFirst()) + for (Standard_Integer aStructIt = 1; aStructIt <= myDescendants.Length(); ++aStructIt) { - TColStd_Array2OfReal aTrsf(0, 3, 0, 3); - Transform (aTrsf); - TransformBoundaries (aTrsf, aDescXMin, aDescYMin, aDescZMin, aDescXMax, aDescYMax, aDescZMax); - - aXMin = Min (aDescXMin, aXMin); - aYMin = Min (aDescYMin, aYMin); - aZMin = Min (aDescZMin, aZMin); - aXMax = Max (aDescXMax, aXMax); - aYMax = Max (aDescYMax, aYMax); - aZMax = Max (aDescZMax, aZMax); + const Graphic3d_Structure* aStruct = (const Graphic3d_Structure* )myDescendants.Value (aStructIt); + aStruct->addTransformed (aBox, theToIgnoreInfiniteFlag); } - // Case impossible as it would mean that the structure is empty - if (aXMin == RealLast() && aYMin == RealLast() && aZMin == RealLast() && - aXMax == RealFirst() && aYMax == RealFirst() && aZMax == RealFirst()) + if (aBox.IsValid()) { - theXMin = RealFirst(); - theYMin = RealFirst(); - theZMin = RealFirst(); - theXMax = RealLast(); - theYMax = RealLast(); - theZMax = RealLast(); + TColStd_Array2OfReal aTrsf (0, 3, 0, 3); + Transform (aTrsf); + TransformBoundaries (aTrsf, aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z(), + aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z()); + theBox.Combine (aBox); } - - theXMin = aXMin; - theYMin = aYMin; - theZMin = aZMin; - theXMax = aXMax; - theYMax = aYMax; - theZMax = aZMax; } //============================================================================= @@ -2384,27 +2266,10 @@ void Graphic3d_Structure::GraphicHighlight (const Aspect_TypeOfHighlightMethod t } case Aspect_TOHM_BOUNDBOX: { - Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax; - if (IsEmpty() || IsInfinite()) - { - // Empty or infinite structure - XMin = YMin = ZMin = 0.0; - XMax = YMax = ZMax = 0.0; - } - else - { - MinMaxCoordWithDescendants (XMin, YMin, ZMin, XMax, YMax, ZMax); - } - myCStructure->BoundBox.Pmin.x = float (XMin); - myCStructure->BoundBox.Pmin.y = float (YMin); - myCStructure->BoundBox.Pmin.z = float (ZMin); - myCStructure->BoundBox.Pmax.x = float (XMax); - myCStructure->BoundBox.Pmax.y = float (YMax); - myCStructure->BoundBox.Pmax.z = float (ZMax); myHighlightColor.Values (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB); - myCStructure->BoundBox.Color.r = float (anRGB[0]); - myCStructure->BoundBox.Color.g = float (anRGB[1]); - myCStructure->BoundBox.Color.b = float (anRGB[2]); + myCStructure->HighlightColor.r = float (anRGB[0]); + myCStructure->HighlightColor.g = float (anRGB[1]); + myCStructure->HighlightColor.b = float (anRGB[2]); myCStructure->HighlightWithBndBox (this, Standard_True); break; } @@ -2531,3 +2396,21 @@ const Graphic3d_SequenceOfHClipPlane& Graphic3d_Structure::GetClipPlanes() const { return myCStructure->ClipPlanes(); } + +//======================================================================= +//function : SetMutable +//purpose : +//======================================================================= +void Graphic3d_Structure::SetMutable (const Standard_Boolean theIsMutable) +{ + myCStructure->IsMutable = theIsMutable; +} + +//======================================================================= +//function : IsMutable +//purpose : +//======================================================================= +Standard_Boolean Graphic3d_Structure::IsMutable() const +{ + return myCStructure->IsMutable; +} diff --git a/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx b/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx index 950197a3ab..2e33160e57 100644 --- a/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx +++ b/src/InterfaceGraphic/InterfaceGraphic_Graphic3d.hxx @@ -16,6 +16,7 @@ #define InterfaceGraphic_Graphic3dHeader #include +#include #include /* COULEUR */ @@ -34,18 +35,6 @@ typedef struct { } CALL_DEF_POINT; -/* BOITE ENGLOBANTE */ - -typedef struct { - - CALL_DEF_COLOR Color; - - CALL_DEF_POINT Pmin; - - CALL_DEF_POINT Pmax; - -} CALL_DEF_BOUNDBOX; - /* MATERIAL */ typedef struct { @@ -85,26 +74,12 @@ typedef struct CALL_DEF_POINT Point; } CALL_DEF_TRANSFORM_PERSISTENCE; -/* BOUNDING BOX */ - -typedef struct { - - float XMin; - float YMin; - float ZMin; - - float XMax; - float YMax; - float ZMax; - -} CALL_DEF_BOUNDS; - /* USERDRAW DATA */ typedef struct { void *Data; - CALL_DEF_BOUNDS *Bounds; + Graphic3d_BndBox4f *Bounds; } CALL_DEF_USERDRAW; diff --git a/src/NCollection/NCollection_Vec4.hxx b/src/NCollection/NCollection_Vec4.hxx index 1758217c41..45aa2b013a 100644 --- a/src/NCollection/NCollection_Vec4.hxx +++ b/src/NCollection/NCollection_Vec4.hxx @@ -315,7 +315,7 @@ public: //! Compute per-component division by scale factor. NCollection_Vec4 operator/ (const Element_t theInvFactor) { - NCollection_Vec4 aResult(this); + NCollection_Vec4 aResult(*this); return aResult /= theInvFactor; } diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 2a8a56d1e2..3991fff2aa 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -143,3 +143,7 @@ OpenGl_SceneGeometry.cxx OpenGl_Workspace_Raytrace.cxx OpenGl_Flipper.hxx OpenGl_Flipper.cxx +OpenGl_BVHTreeSelector.hxx +OpenGl_BVHTreeSelector.cxx +OpenGl_BVHClipPrimitiveSet.cxx +OpenGl_BVHClipPrimitiveSet.hxx diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx new file mode 100644 index 0000000000..4f3b9e83a9 --- /dev/null +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx @@ -0,0 +1,143 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// 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. + +#include + +#include + +// ======================================================================= +// function : OpenGl_BVHClipPrimitiveSet +// purpose : +// ======================================================================= +OpenGl_BVHClipPrimitiveSet::OpenGl_BVHClipPrimitiveSet() +{ + myBuilder = new BVH_BinnedBuilder (1, 32); +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +Standard_Integer OpenGl_BVHClipPrimitiveSet::Size() const +{ + return myStructs.Size(); +} + +// ======================================================================= +// function : Box +// purpose : +// ======================================================================= +Graphic3d_BndBox4f OpenGl_BVHClipPrimitiveSet::Box (const Standard_Integer theIdx) const +{ + return myStructs (theIdx + 1)->BoundingBox(); +} + +// ======================================================================= +// function : Center +// purpose : +// ======================================================================= +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; +} + +// ======================================================================= +// function : Swap +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveSet::Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) +{ + const OpenGl_Structure* aStruct1 = myStructs (theIdx1 + 1); + const OpenGl_Structure* aStruct2 = myStructs (theIdx2 + 1); + myStructs.ChangeValue (theIdx1 + 1) = aStruct2; + myStructs.ChangeValue (theIdx2 + 1) = aStruct1; +} + +// ======================================================================= +// function : Assign +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveSet::Assign (const OpenGl_ArrayOfStructure& theStructs) +{ + myStructs.Clear(); + + const Standard_Integer aNbPriorities = theStructs.Length(); + OpenGl_SequenceOfStructure::Iterator aStructIter; + for (Standard_Integer aPriorityIdx = 0; aPriorityIdx < aNbPriorities; ++aPriorityIdx) + { + const OpenGl_SequenceOfStructure& aSeq = theStructs (aPriorityIdx); + for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next()) + { + const OpenGl_Structure* aStruct = aStructIter.Value(); + if (!aStruct->IsAlwaysRendered()) + myStructs.Append (aStruct); + } + } + + MarkDirty(); +} + +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveSet::Add (const OpenGl_Structure* theStruct) +{ + myStructs.Append (theStruct); + MarkDirty(); +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveSet::Remove (const OpenGl_Structure* theStruct) +{ + for (Standard_Integer anIdx = 1; anIdx <= myStructs.Size(); ++anIdx) + { + if (myStructs (anIdx) == theStruct) + { + myStructs.Remove (anIdx); + MarkDirty(); + break; + } + } +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void OpenGl_BVHClipPrimitiveSet::Clear() +{ + myStructs.Clear(); + MarkDirty(); +} + +// ======================================================================= +// function : GetStructureById +// purpose : +// ======================================================================= +const OpenGl_Structure* OpenGl_BVHClipPrimitiveSet::GetStructureById (Standard_Integer theId) +{ + return myStructs (theId + 1); +} diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx new file mode 100644 index 0000000000..9a5c18a2fe --- /dev/null +++ b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx @@ -0,0 +1,78 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// 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_BVHClipPrimitiveSet_HeaderFile +#define _OpenGl_BVHClipPrimitiveSet_HeaderFile + +#include + +#include +#include + +#include +#include + +typedef NCollection_Sequence OpenGl_SequenceOfStructure; +typedef NCollection_Array1 OpenGl_ArrayOfStructure; + +//! Set of OpenGl_Structures for building BVH tree. +class OpenGl_BVHClipPrimitiveSet : public BVH_PrimitiveSet +{ +protected: + + using BVH_PrimitiveSet::Box; + +public: + + //! Creates an empty primitive set for BVH clipping. + OpenGl_BVHClipPrimitiveSet(); + + //! Returns total number of structures. + virtual Standard_Integer Size() const; + + //! Returns AABB of a structure. + virtual Graphic3d_BndBox4f Box (const Standard_Integer theIdx) const; + + //! Calculates center of the AABB projection onto given axis. + virtual Standard_ShortReal Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const; + + //! Swaps given AABBs. + 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); + + //! Removes the given OpenGl_Structure from the set. + void 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); + +private: + + NCollection_Sequence myStructs; //!< Sequence of structures + +}; + +#endif // _OpenGl_BVHClipPrimitiveSet_HeaderFile diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx new file mode 100644 index 0000000000..75a60b7559 --- /dev/null +++ b/src/OpenGl/OpenGl_BVHTreeSelector.cxx @@ -0,0 +1,283 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// 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. + +#include +#include + +#include +#include + +// ======================================================================= +// function : DotProduct +// purpose : Calculates a dot product of 4-dimensional vectors in homogeneous coordinates +// ======================================================================= +static Standard_ShortReal DotProduct (const OpenGl_Vec4& theA, + const OpenGl_Vec4& theB) +{ + return theA.x() * theB.x() + theA.y() * theB.y() + theA.z() * theB.z(); +} + +// ======================================================================= +// function : BinarySign +// purpose : +// ======================================================================= +static OpenGl_Vec4 BinarySign (const OpenGl_Vec4& theVec) +{ + return OpenGl_Vec4 (theVec.x() > 0.0f ? 1.0f : 0.0f, + theVec.y() > 0.0f ? 1.0f : 0.0f, + theVec.z() > 0.0f ? 1.0f : 0.0f, + theVec.w() > 0.0f ? 1.0f : 0.0f); +} + +// ======================================================================= +// function : InversedBinarySign +// purpose : +// ======================================================================= +static OpenGl_Vec4 InversedBinarySign (const OpenGl_Vec4& theVec) +{ + return OpenGl_Vec4 (theVec.x() > 0.0f ? 0.0f : 1.0f, + theVec.y() > 0.0f ? 0.0f : 1.0f, + theVec.z() > 0.0f ? 0.0f : 1.0f, + theVec.w() > 0.0f ? 0.0f : 1.0f); +} + +// ======================================================================= +// function : OpenGl_BVHTreeSelector +// purpose : +// ======================================================================= +OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() +: myIsProjectionParallel (Standard_True), + myProjectionState (0), + myModelViewState (0) +{ + // +} + +// ======================================================================= +// function : SetClipVolume +// purpose : Retrieves view volume's planes equations and its vertices from projection and modelview matrices. +// ======================================================================= +void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) +{ + myIsProjectionParallel = theCamera->IsOrthographic(); + const OpenGl_Mat4& aProjMat = theCamera->ProjectionMatrixF(); + const OpenGl_Mat4& aModelMat = theCamera->OrientationMatrixF(); + + 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; + Standard_ShortReal aNear = 0.0f, aFar = 0.0f; + 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)); + // 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); + // 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); + } + 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); + // Near plane + nLeft = ( 1.0f + aProjMat.GetValue (0, 3)) / (-aProjMat.GetValue (0, 0)); + fLeft = nLeft; + nRight = ( 1.0f - aProjMat.GetValue (0, 3)) / aProjMat.GetValue (0, 0); + fRight = nRight; + nTop = ( 1.0f - aProjMat.GetValue (1, 3)) / aProjMat.GetValue (1, 1); + fTop = nTop; + nBottom = (-1.0f - aProjMat.GetValue (1, 3)) / aProjMat.GetValue (1, 1); + fBottom = nBottom; + } + + OpenGl_Vec4 aLeftTopNear (nLeft, nTop, -aNear, 1.0f), aRightBottomFar (fRight, fBottom, -aFar, 1.0f); + OpenGl_Vec4 aLeftBottomNear (nLeft, nBottom, -aNear, 1.0f), aRightTopFar (fRight, fTop, -aFar, 1.0f); + 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; + + // UNNORMALIZED! + myClipPlanes[Plane_Left] = aViewProj.GetRow (3) + aViewProj.GetRow (0); + myClipPlanes[Plane_Right] = aViewProj.GetRow (3) - aViewProj.GetRow (0); + myClipPlanes[Plane_Top] = aViewProj.GetRow (3) - aViewProj.GetRow (1); + myClipPlanes[Plane_Bottom] = aViewProj.GetRow (3) + aViewProj.GetRow (1); + myClipPlanes[Plane_Near] = aViewProj.GetRow (3) + aViewProj.GetRow (2); + myClipPlanes[Plane_Far] = aViewProj.GetRow (3) - aViewProj.GetRow (2); + + gp_Pnt aPtCenter = theCamera->Center(); + OpenGl_Vec4 aCenter (static_cast (aPtCenter.X()), + static_cast (aPtCenter.Y()), + static_cast (aPtCenter.Z()), + 1.0f); + + for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter) + { + OpenGl_Vec4 anEq = myClipPlanes[aPlaneIter]; + if (SignedPlanePointDistance (anEq, aCenter) > 0) + { + anEq *= -1.0f; + myClipPlanes[aPlaneIter] = anEq; + } + } +} + +// ======================================================================= +// function : SignedPlanePointDistance +// purpose : +// ======================================================================= +Standard_ShortReal OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4& theNormal, + const OpenGl_Vec4& thePnt) +{ + const Standard_ShortReal aNormLength = std::sqrt (theNormal.x() * theNormal.x() + + theNormal.y() * theNormal.y() + + theNormal.z() * theNormal.z()); + const Standard_ShortReal anInvNormLength = 1.0f / aNormLength; + const Standard_ShortReal aD = theNormal.w() * anInvNormLength; + const Standard_ShortReal anA = theNormal.x() * anInvNormLength; + const Standard_ShortReal aB = theNormal.y() * anInvNormLength; + const Standard_ShortReal aC = theNormal.z() * anInvNormLength; + return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z()); +} + +// ======================================================================= +// function : CacheClipPtsProjections +// purpose : Caches view volume's vertices projections along its normals and AABBs dimensions +// Must be called at the beginning of each BVH tree traverse loop +// ======================================================================= +void OpenGl_BVHTreeSelector::CacheClipPtsProjections() +{ + Standard_ShortReal aProjectedVerts[ClipVerticesNB]; + for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter) + { + const OpenGl_Vec4 aPlane = myClipPlanes[aPlaneIter]; + for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter) + { + Standard_ShortReal aProjection = DotProduct (aPlane, myClipVerts[aCornerIter]); + aProjectedVerts[aCornerIter] = aProjection; + } + myMaxClipProjectionPts[aPlaneIter] = *std::max_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB); + myMinClipProjectionPts[aPlaneIter] = *std::min_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB); + } + + OpenGl_Vec4 aDimensions[3] = + { + OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f), + OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f), + OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f) + }; + + for (Standard_Integer aDim = 0; aDim < 3; ++aDim) + { + for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter) + { + Standard_ShortReal aProjection = DotProduct (aDimensions[aDim], myClipVerts[aCornerIter]); + aProjectedVerts[aCornerIter] = aProjection; + } + myMaxOrthoProjectionPts[aDim] = *std::max_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB); + myMinOrthoProjectionPts[aDim] = *std::min_element (aProjectedVerts, aProjectedVerts + ClipVerticesNB); + } +} + +// ======================================================================= +// function : Intersect +// purpose : Detects if AABB overlaps view volume using separating axis theorem (SAT) +// ======================================================================= +Standard_Boolean OpenGl_BVHTreeSelector::Intersect (const OpenGl_Vec4& theMinPt, + const OpenGl_Vec4& theMaxPt) const +{ + // E1 + // |_ E0 + // / + // E2 + const OpenGl_Vec4 aShiftedBoxMax = theMaxPt - theMinPt; + Standard_ShortReal aBoxProjMax = 0.0f, aBoxProjMin = 0.0f; + Standard_ShortReal aFrustumProjMax = 0.0f, aFrustumProjMin = 0.0f; + + // E0 test + aBoxProjMax = aShiftedBoxMax.x(); + aFrustumProjMax = myMaxOrthoProjectionPts[0] - DotProduct (OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f), theMinPt); + aFrustumProjMin = myMinOrthoProjectionPts[0] - DotProduct (OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 1.0f), theMinPt); + if (aBoxProjMin > aFrustumProjMax + || aBoxProjMax < aFrustumProjMin) + { + return Standard_False; + } + + // E1 test + aBoxProjMax = aShiftedBoxMax.y(); + aFrustumProjMax = myMaxOrthoProjectionPts[1] - DotProduct (OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f), theMinPt); + aFrustumProjMin = myMinOrthoProjectionPts[1] - DotProduct (OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 1.0f), theMinPt); + if (aBoxProjMin > aFrustumProjMax + || aBoxProjMax < aFrustumProjMin) + { + return Standard_False; + } + + // E2 test + aBoxProjMax = aShiftedBoxMax.z(); + aFrustumProjMax = myMaxOrthoProjectionPts[2] - DotProduct (OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f), theMinPt); + aFrustumProjMin = myMinOrthoProjectionPts[2] - DotProduct (OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 1.0f), theMinPt); + if (aBoxProjMin > aFrustumProjMax + || aBoxProjMax < aFrustumProjMin) + { + return Standard_False; + } + + const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; + for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor) + { + OpenGl_Vec4 aPlane = myClipPlanes[aPlaneIter]; + OpenGl_Vec4 aPt1 (0.0f), aPt2 (0.0f); + aPt1 = BinarySign (aPlane) * aShiftedBoxMax; + aBoxProjMax = DotProduct (aPlane, aPt1); + aFrustumProjMax = myMaxClipProjectionPts[aPlaneIter] - DotProduct (aPlane, theMinPt); + aFrustumProjMin = myMinClipProjectionPts[aPlaneIter] - DotProduct (aPlane, theMinPt); + if (aFrustumProjMin < aBoxProjMax + && aBoxProjMax < aFrustumProjMax) + { + continue; + } + + aPt2 = InversedBinarySign (aPlane) * aShiftedBoxMax; + aBoxProjMin = DotProduct (aPlane, aPt2); + if (aBoxProjMin > aFrustumProjMax + || aBoxProjMax < aFrustumProjMin) + { + return Standard_False; + } + } + + return Standard_True; +} diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx new file mode 100644 index 0000000000..96183ce4ca --- /dev/null +++ b/src/OpenGl/OpenGl_BVHTreeSelector.hxx @@ -0,0 +1,117 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// 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_BVHTreeSelector_HeaderFile +#define _OpenGl_BVHTreeSelector_HeaderFile + +#include + +#include + +//! BVHTreeSelector class provides a possibility to store parameters of view volume, +//! such as its vertices and equations, and contains methods detecting if given AABB overlaps +//! view volume. +class OpenGl_BVHTreeSelector +{ +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. + Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); + + //! Detects if AABB overlaps view volume using separating axis theorem (SAT). + //! @param theMinPt [in] maximum point of AABB. + //! @param theMaxPt [in] minimum point of AABB. + //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise. + Standard_EXPORT Standard_Boolean Intersect (const OpenGl_Vec4& theMinPt, + const OpenGl_Vec4& theMaxPt) const; + + //! Caches view volume's vertices projections along its normals and AABBs dimensions. + //! 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; } + + //! Returnes the state of model view matrix previously saved in selector. + Standard_EXPORT const Standard_Size ModelViewState() { return myModelViewState; } + + //! Returnes the link for changing the state of model view matrix. + Standard_EXPORT Standard_Size& ChangeModelViewState() { return myModelViewState; } + +protected: + + //! Calculates signed distance from plane to point. + //! @param theNormal [in] the plane's normal. + //! @param thePnt [in] + Standard_EXPORT Standard_ShortReal SignedPlanePointDistance (const OpenGl_Vec4& theNormal, + const OpenGl_Vec4& thePnt); + +protected: + + //! Enumerates planes of view volume. + enum + { + Plane_Top, + Plane_Bottom, + Plane_Left, + Plane_Right, + Plane_Near, + Plane_Far, + PlanesNB + }; + + //! Enumerates vertices of view volume. + enum + { + ClipVert_LeftTopNear, + ClipVert_LeftBottomNear, + ClipVert_RightTopNear, + ClipVert_RightBottomNear, + ClipVert_LeftTopFar, + ClipVert_LeftBottomFar, + ClipVert_RightTopFar, + ClipVert_RightBottomFar, + ClipVerticesNB + }; + +protected: + + OpenGl_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 + Standard_ShortReal myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals + Standard_ShortReal myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals + + // 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_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. + +}; + +#endif // _OpenGl_BVHTreeSelector_HeaderFile diff --git a/src/OpenGl/OpenGl_GraphicDriver.hxx b/src/OpenGl/OpenGl_GraphicDriver.hxx index a82d358602..d1828ec630 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.hxx +++ b/src/OpenGl/OpenGl_GraphicDriver.hxx @@ -279,6 +279,11 @@ public: const Standard_Integer theLayerId, const Graphic3d_ZLayerSettings& theSettings); + //! Changes priority of a structure within its Z layer for the specified view. + Standard_EXPORT void ChangePriority (const Graphic3d_CStructure& theCStructure, + const Graphic3d_CView& theCView, + const Standard_Integer theNewPriority); + public: //! @return the visualization options @@ -315,6 +320,10 @@ public: //! Could return NULL-handle if no window created by this driver. Standard_EXPORT const Handle(OpenGl_Context)& GetSharedContext() const; + //! Marks BVH tree for given priority list as dirty and + //! marks primitive set for rebuild. + Standard_EXPORT void InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId); + public: DEFINE_STANDARD_RTTI(OpenGl_GraphicDriver) diff --git a/src/OpenGl/OpenGl_GraphicDriver_4.cxx b/src/OpenGl/OpenGl_GraphicDriver_4.cxx index f12cc7abad..5e6a01514a 100644 --- a/src/OpenGl/OpenGl_GraphicDriver_4.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver_4.cxx @@ -127,3 +127,21 @@ void OpenGl_GraphicDriver::UnsetZLayer (const Standard_Integer theLayerId) aStruct->SetZLayer (0); } } + +//======================================================================= +//function : ChangePriority +//purpose : +//======================================================================= +void OpenGl_GraphicDriver::ChangePriority (const Graphic3d_CStructure& theCStructure, + const Graphic3d_CView& theCView, + const Standard_Integer theNewPriority) +{ + const OpenGl_CView *aCView = (const OpenGl_CView *)theCView.ptrView; + + if (!myMapOfStructure.IsBound (theCStructure.Id) || !aCView) + return; + + OpenGl_Structure* aStructure = myMapOfStructure.Find (theCStructure.Id); + + aCView->View->ChangePriority (aStructure, theNewPriority); +} diff --git a/src/OpenGl/OpenGl_GraphicDriver_7.cxx b/src/OpenGl/OpenGl_GraphicDriver_7.cxx index 9eabd7f852..224813bab8 100644 --- a/src/OpenGl/OpenGl_GraphicDriver_7.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver_7.cxx @@ -459,6 +459,19 @@ void OpenGl_GraphicDriver::Transparency (const Graphic3d_CView& ACView, const St aCView->WS->UseTransparency(AFlag); } +// ======================================================================= +// function : InvalidateBVHData +// purpose : +// ======================================================================= +void OpenGl_GraphicDriver::InvalidateBVHData (Graphic3d_CView& theCView, const Standard_Integer theLayerId) +{ + OpenGl_CView *aCView = (OpenGl_CView *)theCView.ptrView; + if(aCView) + { + aCView->View->InvalidateBVHData (theLayerId); + } +} + Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView) { if (myMapOfView.IsBound (theCView.ViewId) diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index 1392fe4f81..2d908581e9 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -156,14 +156,15 @@ void OpenGl_LayerList::RemoveLayer (const Standard_Integer theLayerId) void OpenGl_LayerList::AddStructure (const OpenGl_Structure *theStructure, const Standard_Integer theLayerId, - const Standard_Integer thePriority) + const Standard_Integer thePriority, + Standard_Boolean isForChangePriority) { // add structure to associated layer, // if layer doesn't exists, display structure in default layer OpenGl_PriorityList& aList = !HasLayer (theLayerId) ? defaultLayer ().PriorityList() : myLayers.ChangeValue (myLayerIds.Find (theLayerId)).PriorityList(); - aList.Add (theStructure, thePriority); + aList.Add (theStructure, thePriority, isForChangePriority); myNbStructures++; // Note: In ray-tracing mode we don't modify modification @@ -222,6 +223,20 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure *theStructure, } } +//======================================================================= +//function : InvalidateBVHData +//purpose : +//======================================================================= +void OpenGl_LayerList::InvalidateBVHData (const Standard_Integer theLayerId) +{ + Standard_Integer aSeqPos = !HasLayer (theLayerId) ? + 1 : myLayerIds.Find (theLayerId); + + OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList(); + + aList.InvalidateBVHData(); +} + //======================================================================= //function : ChangeLayer //purpose : @@ -239,10 +254,10 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure *theStructure, // take priority and remove structure from list found by // if the structure is not found there, scan through all other layers - if ((aPriority = aList.Remove (theStructure)) >= 0) + if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0) { myNbStructures--; - AddStructure (theStructure, theNewLayerId, aPriority); + AddStructure (theStructure, theNewLayerId, aPriority, Standard_True); } else { @@ -255,10 +270,47 @@ void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure *theStructure, continue; // try to remove structure and get priority value from this layer - if ((aPriority = aList.Remove (theStructure)) >= 0) + if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0) + { + myNbStructures--; + AddStructure (theStructure, theNewLayerId, aPriority, Standard_True); + break; + } + } + } +} + +//======================================================================= +//function : ChangePriority +//purpose : +//======================================================================= +void OpenGl_LayerList::ChangePriority (const OpenGl_Structure *theStructure, + const Standard_Integer theLayerId, + const Standard_Integer theNewPriority) +{ + Standard_Integer aSeqPos = !HasLayer (theLayerId) ? + 1 : myLayerIds.Find (theLayerId); + + OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList(); + + if (aList.Remove (theStructure, Standard_True) >= 0) + { + myNbStructures--; + AddStructure (theStructure, theLayerId, theNewPriority, Standard_True); + } + else + { + Standard_Integer aSeqId = 1; + OpenGl_SequenceOfLayers::Iterator anIts; + for (anIts.Init (myLayers); anIts.More (); anIts.Next (), aSeqId++) + { + if (aSeqPos == aSeqId) + continue; + + if (aList.Remove (theStructure, Standard_True) >= 0) { myNbStructures--; - AddStructure (theStructure, theNewLayerId, aPriority); + AddStructure (theStructure, theLayerId, theNewPriority, Standard_True); break; } } diff --git a/src/OpenGl/OpenGl_LayerList.hxx b/src/OpenGl/OpenGl_LayerList.hxx index 210ebe25c9..c979feb1e7 100644 --- a/src/OpenGl/OpenGl_LayerList.hxx +++ b/src/OpenGl/OpenGl_LayerList.hxx @@ -60,7 +60,8 @@ class OpenGl_LayerList //! to default bottom-level layer. void AddStructure (const OpenGl_Structure *theStructure, const Standard_Integer theLayerId, - const Standard_Integer thePriority); + const Standard_Integer thePriority, + Standard_Boolean isForChangePriority = Standard_False); //! Remove structure from structure list and return its previous priority void RemoveStructure (const OpenGl_Structure *theStructure, @@ -73,6 +74,11 @@ class OpenGl_LayerList const Standard_Integer theOldLayerId, const Standard_Integer theNewLayerId); + //! Changes structure priority within its ZLayer + void ChangePriority (const OpenGl_Structure *theStructure, + const Standard_Integer theLayerId, + const Standard_Integer theNewPriority); + //! Returns reference to the layer with given ID. OpenGl_Layer& Layer (const Standard_Integer theLayerId); @@ -85,6 +91,10 @@ class OpenGl_LayerList //! Returns the set of OpenGL Z-layers. const OpenGl_SequenceOfLayers& Layers() const { return myLayers; } + //! Marks BVH tree for given priority list as dirty and + //! marks primitive set for rebuild. + void InvalidateBVHData (const Standard_Integer theLayerId); + //! Returns structure modification state (for ray-tracing). Standard_Size ModificationState() const { return myModificationState; } diff --git a/src/OpenGl/OpenGl_PriorityList.cxx b/src/OpenGl/OpenGl_PriorityList.cxx index f721715777..e6b8cc4d39 100644 --- a/src/OpenGl/OpenGl_PriorityList.cxx +++ b/src/OpenGl/OpenGl_PriorityList.cxx @@ -15,36 +15,78 @@ #include +#include #include +#include -/*----------------------------------------------------------------------*/ +// ======================================================================= +// function : OpenGl_PriorityList +// purpose : +// ======================================================================= +OpenGl_PriorityList::OpenGl_PriorityList (const Standard_Integer theNbPriorities) +: myArray (0, theNbPriorities - 1), + myNbStructures (0), + myBVHIsLeftChildQueuedFirst (Standard_True), + myIsBVHPrimitivesNeedsReset (Standard_False) +{ + // +} -void OpenGl_PriorityList::Add (const OpenGl_Structure *AStructure,const Standard_Integer APriority) +// ======================================================================= +// function : ~OpenGl_PriorityList +// purpose : +// ======================================================================= +OpenGl_PriorityList::~OpenGl_PriorityList() { - Standard_Integer anIndex = APriority; - if (anIndex < 0) anIndex = 0; - else if (anIndex >= myArray.Length()) anIndex = myArray.Length()-1; - myArray(anIndex).Append(AStructure); - myNbStructures++; + // } -/*----------------------------------------------------------------------*/ +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +void OpenGl_PriorityList::Add (const OpenGl_Structure* theStructure, + const Standard_Integer thePriority, + Standard_Boolean isForChangePriority) +{ + const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1); -Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure *AStructure) + myArray (anIndex).Append (theStructure); + if (theStructure->IsAlwaysRendered()) + { + theStructure->MarkAsNotCulled(); + } + else if (!isForChangePriority) + { + myBVHPrimitives.Add (theStructure); + } + ++myNbStructures; +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure* theStructure, + Standard_Boolean isForChangePriority) { - const Standard_Integer aNbPr = myArray.Length(); - Standard_Integer i = 0; - OpenGl_SequenceOfStructure::Iterator its; - for (; i < aNbPr; i++) + const Standard_Integer aNbPriorities = myArray.Length(); + OpenGl_SequenceOfStructure::Iterator aStructIter; + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) { - OpenGl_SequenceOfStructure &aSeq = myArray(i); - for (its.Init(aSeq); its.More(); its.Next()) + OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter); + for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next()) { - if (its.Value() == AStructure) + if (aStructIter.Value() == theStructure) { - aSeq.Remove(its); - myNbStructures--; - return i; + aSeq.Remove (aStructIter); + if (!theStructure->IsAlwaysRendered() + && !isForChangePriority) + { + myBVHPrimitives.Remove (theStructure); + } + --myNbStructures; + return aPriorityIter; } } } @@ -52,50 +94,177 @@ Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure *AStructure return -1; } -/*----------------------------------------------------------------------*/ +// ======================================================================= +// function : InvalidateBVHData +// purpose : +// ======================================================================= +void OpenGl_PriorityList::InvalidateBVHData() +{ + myIsBVHPrimitivesNeedsReset = Standard_True; +} -void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace) &AWorkspace) const +// ======================================================================= +// function : Render +// purpose : +// ======================================================================= +void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace)& theWorkspace) const { - const Standard_Integer aNbPr = myArray.Length(); - Standard_Integer i = 0; - OpenGl_SequenceOfStructure::Iterator its; - for (; i < aNbPr; i++) + theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace); +} + +// ======================================================================= +// function : renderAll +// purpose : +// ======================================================================= +void OpenGl_PriorityList::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + const Standard_Integer aNbPriorities = myArray.Length(); + OpenGl_SequenceOfStructure::Iterator aStructIter; + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) { - for (its.Init(myArray(i)); its.More(); its.Next()) - its.Value()->Render(AWorkspace); + for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next()) + { + aStructIter.Value()->Render (theWorkspace); + } } } -//======================================================================= -//function : Append -//purpose : -//======================================================================= +// ======================================================================= +// function : renderTraverse +// purpose : +// ======================================================================= +void OpenGl_PriorityList::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + if (myIsBVHPrimitivesNeedsReset) + { + myBVHPrimitives.Assign (myArray); + myIsBVHPrimitivesNeedsReset = Standard_False; + } + + OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector(); + traverse (aSelector); + + const Standard_Integer aNbPriorities = myArray.Length(); + OpenGl_SequenceOfStructure::Iterator aStructIter; + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) + { + for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next()) + { + if (!aStructIter.Value()->IsCulled()) + { + aStructIter.Value()->Render (theWorkspace); + aStructIter.Value()->ResetCullingStatus(); + } + } + } +} +// ======================================================================= +// function : traverse +// purpose : +// ======================================================================= +void OpenGl_PriorityList::traverse (OpenGl_BVHTreeSelector& theSelector) const +{ + // handle a case when all objects are infinite + if (myBVHPrimitives.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 (;;) + { + 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; + ++aHead; + aStack[aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; + myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; + } + else if (isLeftChildIn + || isRightChildIn) + { + aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + } + else + { + if (aHead < 0) + { + return; + } + + aNode = aStack[aHead]; + --aHead; + } + } + else + { + if (theSelector.Intersect (aBVHTree->MinPoint (aNode), + aBVHTree->MaxPoint (aNode))) + { + Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); + myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled(); + if (aHead < 0) + { + return; + } + + aNode = aStack[aHead]; + --aHead; + } + } + } +} + +// ======================================================================= +// function : Append +// purpose : +// ======================================================================= Standard_Boolean OpenGl_PriorityList::Append (const OpenGl_PriorityList& theOther) { // the source priority list shouldn't have more priorities const Standard_Integer aNbPriorities = theOther.NbPriorities (); - if (aNbPriorities > NbPriorities ()) + if (aNbPriorities > NbPriorities()) + { return Standard_False; + } // add all structures to destination priority list - Standard_Integer aIdx = 0; - OpenGl_SequenceOfStructure::Iterator anIts; - for (; aIdx < aNbPriorities; aIdx++) + OpenGl_SequenceOfStructure::Iterator aStructIter; + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) { - const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aIdx); - for (anIts.Init (aSeq); anIts.More (); anIts.Next ()) - Add (anIts.Value (), aIdx); + const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aPriorityIter); + for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next()) + { + Add (aStructIter.Value(), aPriorityIter); + } } return Standard_True; } -//======================================================================= -//function : NbPriorities -//purpose : -//======================================================================= - +// ======================================================================= +// function : NbPriorities +// purpose : +// ======================================================================= Standard_Integer OpenGl_PriorityList::NbPriorities() const { return myArray.Length(); diff --git a/src/OpenGl/OpenGl_PriorityList.hxx b/src/OpenGl/OpenGl_PriorityList.hxx index cebdb1c741..dab5631f4f 100644 --- a/src/OpenGl/OpenGl_PriorityList.hxx +++ b/src/OpenGl/OpenGl_PriorityList.hxx @@ -22,6 +22,8 @@ #include #include +#include +#include class OpenGl_Structure; @@ -30,21 +32,27 @@ typedef NCollection_Array1 OpenGl_ArrayOfStructure; class OpenGl_PriorityList { - public: +public: - OpenGl_PriorityList (const Standard_Integer ANbPriorities = 11) : myArray(0,(ANbPriorities-1)), myNbStructures(0) {} + // Empty constructor. + OpenGl_PriorityList (const Standard_Integer theNbPriorities = 11); - virtual ~OpenGl_PriorityList () {} + //! Destructor. + virtual ~OpenGl_PriorityList(); - void Add (const OpenGl_Structure *AStructure, const Standard_Integer APriority); + void Add (const OpenGl_Structure* theStructure, + const Standard_Integer thePriority, + Standard_Boolean isForChangePriority = Standard_False); - //! Remove structure and returns its priority, if the structure is not found, - //! method returns negative value - Standard_Integer Remove (const OpenGl_Structure *AStructure); + //! Remove structure and returns its priority, if the structure is not found, method returns negative value + Standard_Integer Remove (const OpenGl_Structure* theStructure, + Standard_Boolean isForChangePriority = Standard_False); - Standard_Integer NbStructures () const { return myNbStructures; } + //! @return the number of structures + Standard_Integer NbStructures() const { return myNbStructures; } - void Render (const Handle(OpenGl_Workspace) &AWorkspace) const; + // Render all structures. + void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; //! Returns the number of available priority levels Standard_Integer NbPriorities() const; @@ -56,13 +64,33 @@ class OpenGl_PriorityList //! Returns array of OpenGL structures. const OpenGl_ArrayOfStructure& ArrayOfStructures() const { return myArray; } - protected: + //! Marks BVH tree for given priority list as dirty and + //! marks primitive set for rebuild. + void InvalidateBVHData(); - OpenGl_ArrayOfStructure myArray; - Standard_Integer myNbStructures; +protected: + + //! Traverses through BVH tree to determine which structures are in view volume. + void traverse (OpenGl_BVHTreeSelector& theSelector) const; + + //! Iterates through the hierarchical list of existing structures and renders them all. + void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const; + + //! Iterates through the hierarchical list of existing structures and renders only overlapping ones. + void renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const; + +protected: + + OpenGl_ArrayOfStructure myArray; + Standard_Integer myNbStructures; + mutable OpenGl_BVHClipPrimitiveSet myBVHPrimitives; // +#include +#include + //! Use this macro to output BVH profiling info //#define BVH_PRINT_INFO diff --git a/src/OpenGl/OpenGl_SceneGeometry.hxx b/src/OpenGl/OpenGl_SceneGeometry.hxx index f3af8b191b..dea84711ee 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -19,8 +19,11 @@ #include #include #include -#include -#include + +struct OpenGl_ElementNode; +class OpenGl_Group; +class OpenGl_Structure; +class OpenGl_PrimitiveArray; namespace OpenGl_Raytrace { diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index b0d8200478..2cb3ddcf12 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -37,14 +37,15 @@ class OpenGl_BndBoxPrs : public OpenGl_Element public: //! Main constructor - OpenGl_BndBoxPrs (const CALL_DEF_BOUNDBOX& theBndBox) - { - const float Xm = theBndBox.Pmin.x; - const float Ym = theBndBox.Pmin.y; - const float Zm = theBndBox.Pmin.z; - const float XM = theBndBox.Pmax.x; - const float YM = theBndBox.Pmax.y; - const float ZM = theBndBox.Pmax.z; + OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox) + { + const float Xm = theBndBox.CornerMin().x(); + const float Ym = theBndBox.CornerMin().y(); + const float Zm = theBndBox.CornerMin().z(); + const float XM = theBndBox.CornerMax().x(); + const float YM = theBndBox.CornerMax().y(); + const float ZM = theBndBox.CornerMax().z(); + myVerts[0] = OpenGl_Vec3 (Xm, Ym, Zm); myVerts[1] = OpenGl_Vec3 (Xm, Ym, ZM); myVerts[2] = OpenGl_Vec3 (Xm, YM, ZM); @@ -143,7 +144,8 @@ OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& th myNamedStatus(0), myZLayer(0), myIsRaytracable (Standard_False), - myModificationState (0) + myModificationState (0), + myIsCulled (Standard_True) { UpdateNamedStatus(); } @@ -212,6 +214,7 @@ void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTE myTransPers->pointX = ATransPers.Point.x; myTransPers->pointY = ATransPers.Point.y; myTransPers->pointZ = ATransPers.Point.z; + MarkAsNotCulled(); } // ======================================================================= @@ -323,12 +326,12 @@ void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& t CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine(); aContextLine.IsDef = 1; - aContextLine.Color = BoundBox.Color; + aContextLine.Color = HighlightColor; aContextLine.LineType = Aspect_TOL_SOLID; aContextLine.Width = 1.0f; myHighlightBox->UpdateAspectLine (Standard_True); - OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (BoundBox); + OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox); myHighlightBox->AddElement (aBndBoxPrs); } @@ -598,6 +601,9 @@ void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx) UpdateStateWithAncestorStructures(); UpdateRaytracableWithAncestorStructures(); } + + Is2dText = Standard_False; + IsForHighlight = Standard_False; } // ======================================================================= @@ -610,6 +616,8 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const if ( myNamedStatus & OPENGL_NS_HIDE ) return; + const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext(); + // Render named status const Standard_Integer named_status = AWorkspace->NamedStatus; AWorkspace->NamedStatus |= myNamedStatus; @@ -617,8 +625,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const // Is rendering in ADD or IMMEDIATE mode? const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0; - const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext(); - // Apply local transformation GLint matrix_mode = 0; const OpenGl_Matrix *local_trsf = NULL; @@ -678,12 +684,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const if (myAspectText) AWorkspace->SetAspectText(myAspectText); - // Apply highlight box - if (!myHighlightBox.IsNull()) - { - myHighlightBox->Render (AWorkspace); - } - // Apply highlight color const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor; if (myHighlightColor) @@ -800,6 +800,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const } } + // Apply highlight box + if (!myHighlightBox.IsNull()) + { + myHighlightBox->Render (AWorkspace); + } + // Restore named status AWorkspace->NamedStatus = named_status; } @@ -872,6 +878,7 @@ Standard_Integer OpenGl_Structure::GetZLayer () const return myZLayer; } +//! Dummy structure which just redirects to groups of another structure. class OpenGl_StructureShadow : public OpenGl_Structure { @@ -898,6 +905,10 @@ DEFINE_STANDARD_HANDLE(OpenGl_StructureShadow, OpenGl_Structure) IMPLEMENT_STANDARD_HANDLE (OpenGl_StructureShadow, OpenGl_Structure) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_StructureShadow, OpenGl_Structure) +//======================================================================= +//function : OpenGl_StructureShadow +//purpose : +//======================================================================= OpenGl_StructureShadow::OpenGl_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager, const Handle(OpenGl_Structure)& theStructure) : OpenGl_Structure (theManager) diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index fd7b3673ca..48569aefa0 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -140,6 +142,34 @@ public: virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; virtual void Release (const Handle(OpenGl_Context)& theGlCtx); + //! Marks structure as not overlapping view volume (as it is by default). + void ResetCullingStatus() const + { + if (!IsAlwaysRendered()) + { + myIsCulled = Standard_True; + } + } + + //! Marks structure as overlapping the current view volume one. + //! The method is called during traverse of BVH tree. + void MarkAsNotCulled() const { myIsCulled = Standard_False; } + + //! Returns Standard_False if the structure hits the current view volume, otherwise + //! returns Standard_True. The default value for all structures before each traverse + //! of BVH tree is Standard_True. + Standard_Boolean IsCulled() const { return myIsCulled; } + + //! Checks if the structure should be included into BVH tree or not. + const Standard_Boolean IsAlwaysRendered() const + { + return IsInfinite + || IsForHighlight + || IsMutable + || Is2dText + || TransformPersistence.Flag != 0; + } + //! This method releases GL resources without actual elements destruction. //! As result structure could be correctly destroyed layer without GL context //! (after last window was closed for example). @@ -212,6 +242,8 @@ protected: mutable Standard_Boolean myIsRaytracable; mutable Standard_Size myModificationState; + mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse. + public: DEFINE_STANDARD_RTTI(OpenGl_Structure) // Type definition diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index b1cbe18912..b3f2a122d1 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -164,6 +165,10 @@ class OpenGl_View : public MMgt_TShared void SetZLayerSettings (const Standard_Integer theLayerId, const Graphic3d_ZLayerSettings theSettings); + //! Changes the priority of a structure within its ZLayer + void ChangePriority (const OpenGl_Structure *theStructure, + const Standard_Integer theNewPriority); + void CreateBackgroundTexture (const Standard_CString AFileName, const Aspect_FillMethod AFillStyle); void SetBackgroundTextureStyle (const Aspect_FillMethod FillStyle); void SetBackgroundGradient (const Quantity_Color& AColor1, const Quantity_Color& AColor2, const Aspect_GradientFillMethod AType); @@ -190,6 +195,14 @@ class OpenGl_View : public MMgt_TShared //! Returns visualization mode for objects in the view. Visual3d_TypeOfSurfaceDetail SurfaceDetail() const { return mySurfaceDetail; } + //! Returns selector for BVH tree, providing a possibility to store information + //! about current view volume and to detect which objects are overlapping it. + OpenGl_BVHTreeSelector& BVHTreeSelector() { return myBVHSelector; } + + //! Marks BVH tree for given priority list as dirty and + //! marks primitive set for rebuild. + void InvalidateBVHData (const Standard_Integer theLayerId); + void GetMatrices (TColStd_Array2OfReal& theMatOrient, TColStd_Array2OfReal& theMatMapping) const; @@ -273,6 +286,9 @@ protected: StateInfo myLastViewMappingState; StateInfo myLastLightSourceState; + //! Is needed for selection of overlapping objects and storage of the current view volume + OpenGl_BVHTreeSelector myBVHSelector; + Standard_Size myModificationState; public: diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 99b2266010..59c1dfd7d6 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -383,6 +383,19 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, } } + 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(); + } + // Set OCCT state uniform variables const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager(); if (!aManager->IsEmpty()) @@ -429,6 +442,12 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, } } + if (isProjectionMatUpdateNeeded + || isOrientationMatUpdateNeeded) + { + myBVHSelector.SetViewVolume (myCamera); + } + // ==================================== // Step 2: Redraw background // ==================================== @@ -643,6 +662,15 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, } } +// ======================================================================= +// function : InvalidateBVHData +// purpose : +// ======================================================================= +void OpenGl_View::InvalidateBVHData (const Standard_Integer theLayerId) +{ + myZLayers.InvalidateBVHData (theLayerId); +} + /*----------------------------------------------------------------------*/ //ExecuteViewDisplay @@ -1033,6 +1061,16 @@ void OpenGl_View::SetZLayerSettings (const Standard_Integer theLayerId, myZLayers.Layer (theLayerId).SetLayerSettings (theSettings); } +//======================================================================= +//function : ChangePriority +//purpose : +//======================================================================= +void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure, + const Standard_Integer theNewPriority) +{ + Standard_Integer aLayerId = theStructure->GetZLayer(); + myZLayers.ChangePriority (theStructure, aLayerId, theNewPriority); +} //======================================================================= //function : RedrawScene diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index b6dd1662ae..61e4d13455 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -159,6 +159,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(Aspect_DisplayConnection)& theD myUseZBuffer (Standard_False), myUseDepthTest (Standard_True), myUseGLLight (Standard_True), + myIsCullingEnabled (Standard_False), // AspectLine_set (&myDefaultAspectLine), AspectLine_applied (NULL), @@ -560,6 +561,8 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, return; } + myIsCullingEnabled = theCView.IsCullingEnabled; + // release pending GL resources Handle(OpenGl_Context) aGlCtx = GetGlContext(); aGlCtx->ReleaseDelayed(); diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index d9f96340c6..42679495e3 100755 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -64,6 +64,7 @@ class OpenGl_AspectMarker; class OpenGl_AspectText; class OpenGl_FrameBuffer; class OpenGl_Structure; +class OpenGl_TriangleSet; class OpenGl_Element; class Image_PixMap; @@ -224,6 +225,9 @@ public: //! Returns currently applied polygon offset params. const TEL_POFFSET_PARAM& AppliedPolygonOffset() { return PolygonOffset_applied; } + //! @return true if clipping algorithm enabled + inline Standard_Boolean IsCullingEnabled() const { return myIsCullingEnabled; } + protected: //! Copy content of Back buffer to the Front buffer @@ -599,6 +603,7 @@ protected: //! @name protected fields Standard_Boolean myUseZBuffer; Standard_Boolean myUseDepthTest; Standard_Boolean myUseGLLight; + Standard_Boolean myIsCullingEnabled; //!< frustum culling flag protected: //! @name fields related to status diff --git a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx index 91792ce1b1..15dae2b425 100755 --- a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx +++ b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx @@ -13,13 +13,15 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include + #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/src/Prs3d/Prs3d_Presentation.cdl b/src/Prs3d/Prs3d_Presentation.cdl index 7f7ec9d6d4..4a59f66445 100644 --- a/src/Prs3d/Prs3d_Presentation.cdl +++ b/src/Prs3d/Prs3d_Presentation.cdl @@ -91,6 +91,12 @@ is ---Purpose: displays the whole content of the presentation in the specified color. BoundBox(me: mutable) is static; + SetIsForHighlight (me : mutable; + isForHighlight : Boolean from Standard) + is virtual; + ---Purpose: marks the structure representing wired structure needed for + -- highlight only so it won't be added to BVH tree. + ---Category: Global modification methods. SetShadingAspect(me: mutable; aShadingAspect: ShadingAspect from Prs3d); diff --git a/src/Prs3d/Prs3d_Presentation.cxx b/src/Prs3d/Prs3d_Presentation.cxx index 76bce4714e..a205f09122 100644 --- a/src/Prs3d/Prs3d_Presentation.cxx +++ b/src/Prs3d/Prs3d_Presentation.cxx @@ -288,6 +288,15 @@ Handle(Graphic3d_Group) Prs3d_Presentation::CurrentGroup () const } //======================================================================= +//======================================================================= +//function : SetIsForHighlight +//purpose : +//======================================================================= +void Prs3d_Presentation::SetIsForHighlight (const Standard_Boolean isForHighlight) +{ + Graphic3d_Structure::SetIsForHighlight (isForHighlight); +} + //function : Compute //purpose : //======================================================================= diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cdl b/src/PrsMgr/PrsMgr_PresentableObject.cdl index f4457f55b5..9b88fe54ff 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.cdl +++ b/src/PrsMgr/PrsMgr_PresentableObject.cdl @@ -277,6 +277,16 @@ is ---Purpose: Get clip planes. -- @return set of previously added clip planes for all display mode presentations. + SetMutable ( me : mutable; + theIsMutable : Boolean from Standard ) is virtual; + ---Purpose: Sets if the object has mutable nature (content or location will be changed regularly). + -- This method should be called before object displaying to take effect. + + IsMutable (me) returns Boolean from Standard; + ---C++: return const + ---Purpose: Returns true if object has mutable nature (content or location are be changed regularly). + -- Mutable object will be managed in different way than static onces (another optimizations). + UpdateClipping (me : mutable) is virtual protected; ---Purpose: General virtual method for internal update of presentation state -- when some modifications on list of clip planes occurs. Base @@ -287,8 +297,8 @@ fields myTypeOfPresentation3d: TypeOfPresentation3d from PrsMgr is protected; myLocation : Location from TopLoc is protected; myClipPlanes : SequenceOfHClipPlane from Graphic3d is protected; - --myTransformPersistence : TransModeFlags from Graphic3d; myTransformPersistence : CTransPersStruct from Graphic3d; + myIsMutable : Boolean from Standard is protected; friends class Presentation from PrsMgr, diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cxx b/src/PrsMgr/PrsMgr_PresentableObject.cxx index a392bc5709..b1535eb5ef 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.cxx +++ b/src/PrsMgr/PrsMgr_PresentableObject.cxx @@ -25,10 +25,11 @@ //======================================================================= //function : PrsMgr_PresentableObject -//purpose : +//purpose : //======================================================================= -PrsMgr_PresentableObject::PrsMgr_PresentableObject(const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d) - :myPresentations(),myTypeOfPresentation3d(aTypeOfPresentation3d) +PrsMgr_PresentableObject::PrsMgr_PresentableObject (const PrsMgr_TypeOfPresentation3d theType) +: myTypeOfPresentation3d (theType), + myIsMutable (Standard_False) { myTransformPersistence.Flag = 0; myTransformPersistence.Point.x = 0.0; @@ -294,6 +295,7 @@ void PrsMgr_PresentableObject::SetTransformPersistence (const Graphic3d_TransMod && !aPrs3d->Presentation().IsNull()) { aPrs3d->Presentation()->SetTransformPersistence (theFlag, thePoint); + aPrs3d->Presentation()->ReCompute(); } } } @@ -414,3 +416,37 @@ void PrsMgr_PresentableObject::UpdateClipping() aModedPrs.Presentation()->Presentation()->SetClipPlanes (myClipPlanes); } } + +// ======================================================================= +// function : SetMutable +// purpose : +// ======================================================================= +void PrsMgr_PresentableObject::SetMutable (const Standard_Boolean theIsMutable) +{ + if (myIsMutable == theIsMutable) + { + return; + } + + myIsMutable = theIsMutable; + for (Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter) + { + const PrsMgr_ModedPresentation& aModedPrs = myPresentations (aPrsIter); + if (aModedPrs.Presentation().IsNull() + || aModedPrs.Presentation()->Presentation().IsNull()) + { + continue; + } + + aModedPrs.Presentation()->Presentation()->SetMutable (theIsMutable); + } +} + +// ======================================================================= +// function : IsMutable +// purpose : +// ======================================================================= +const Standard_Boolean PrsMgr_PresentableObject::IsMutable() const +{ + return myIsMutable; +} diff --git a/src/PrsMgr/PrsMgr_Presentation.cxx b/src/PrsMgr/PrsMgr_Presentation.cxx index 11269ef39e..6343c1a151 100644 --- a/src/PrsMgr/PrsMgr_Presentation.cxx +++ b/src/PrsMgr/PrsMgr_Presentation.cxx @@ -52,6 +52,7 @@ PrsMgr_Presentation::PrsMgr_Presentation (const Handle(PrsMgr_PresentationManage myStructure = new PrsMgr_Prs (thePrsMgr->StructureManager(), this, thePrsObject->TypeOfPresentation3d()); myStructure->SetOwner (myPresentableObject); + myStructure->SetMutable (myPresentableObject->IsMutable()); } //======================================================================= @@ -68,15 +69,17 @@ void PrsMgr_Presentation::Display() //function : Display //purpose : //======================================================================= -void PrsMgr_Presentation::Display (const Standard_Boolean /*theIsHighlight*/) +void PrsMgr_Presentation::Display (const Standard_Boolean theIsHighlight) { if (!myStructure->IsDisplayed()) { + myStructure->SetIsForHighlight (theIsHighlight); myStructure->Display(); } else if (!myStructure->IsVisible()) { SetVisible (Standard_True); + myStructure->SetIsForHighlight (theIsHighlight); } } diff --git a/src/Standard/Standard_Real.hxx b/src/Standard/Standard_Real.hxx index 14f425b9c4..b70687c561 100644 --- a/src/Standard/Standard_Real.hxx +++ b/src/Standard/Standard_Real.hxx @@ -270,6 +270,20 @@ inline Standard_Integer RealToInt (const Standard_Real Value) : (Standard_Integer)Value; } +// ======================================================================= +// function : RealToShortReal +// purpose : Converts Standard_Real value to the nearest valid +// Standard_ShortReal. If input value is out of valid range +// for Standard_ShortReal, minimal or maximal +// Standard_ShortReal is returned. +// ======================================================================= +inline Standard_ShortReal RealToShortReal (const Standard_Real theVal) +{ + return theVal < -FLT_MAX ? -FLT_MAX + : theVal > FLT_MAX ? FLT_MAX + : (Standard_ShortReal)theVal; +} + //------------------------------------------------------------------- // Round : Returns the nearest integer of a real //------------------------------------------------------------------- diff --git a/src/V3d/V3d_View.cdl b/src/V3d/V3d_View.cdl index e90e475356..593d0083d3 100644 --- a/src/V3d/V3d_View.cdl +++ b/src/V3d/V3d_View.cdl @@ -1629,6 +1629,14 @@ is ---Level: Public ---Purpose: Returns reference to current rendering parameters and effect settings. + IsCullingEnabled (me) returns Boolean from Standard is static; + ---Level: Public + ---Purpose: @return flag value of objects culling mechanism + + SetFrustumCulling (me : mutable; theMode : Boolean from Standard) is static; + ---Level: Public + ---Purpose: Turn on/off automatic culling of objects outside frustrum (ON by default) + fields myOldMouseX : Real is protected; diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index 028e1c81e2..0d17f6ba6b 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -3392,3 +3392,23 @@ void V3d_View::Translate (const Handle(Graphic3d_Camera)& theCamera, theCamera->Transform (aPanTrsf); } + +// ======================================================================= +// function : IsCullingEnabled +// purpose : +// ======================================================================= +Standard_Boolean V3d_View::IsCullingEnabled() const +{ + Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView(); + return aView->IsCullingEnabled; +} + +// ======================================================================= +// function : SetFrustumCulling +// purpose : +// ======================================================================= +void V3d_View::SetFrustumCulling (const Standard_Boolean theToClip) +{ + Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView(); + aView->IsCullingEnabled = theToClip; +} diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 5fed471522..7698ebd1ff 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -2028,6 +2028,7 @@ int VRemove (Draw_Interpretor& theDI, ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto; Standard_Boolean isContextOnly = Standard_False; Standard_Boolean toRemoveAll = Standard_False; + Standard_Boolean toPrintInfo = Standard_True; Standard_Integer anArgIter = 1; for (; anArgIter < theArgNb; ++anArgIter) @@ -2042,6 +2043,10 @@ int VRemove (Draw_Interpretor& theDI, { toRemoveAll = Standard_True; } + else if (anArg == "-noinfo") + { + toPrintInfo = Standard_False; + } else if (!parseRedrawMode (anArg, aToUpdate)) { break; @@ -2133,11 +2138,13 @@ int VRemove (Draw_Interpretor& theDI, anIter.More(); anIter.Next()) { const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value())); - if (!anIO.IsNull()) { TheAISContext()->Remove (anIO, Standard_False); - theDI << anIter.Value().ToCString() << " was removed\n"; + if (toPrintInfo) + { + theDI << anIter.Value().ToCString() << " was removed\n"; + } } else { @@ -2145,10 +2152,12 @@ int VRemove (Draw_Interpretor& theDI, if (!aNisIO.IsNull()) { TheNISContext()->Remove (aNisIO); - theDI << anIter.Value().ToCString() << " was removed\n"; + if (toPrintInfo) + { + theDI << anIter.Value().ToCString() << " was removed\n"; + } } } - if (!isContextOnly) { GetMapOfAIS().UnBind2 (anIter.Value()); @@ -2854,19 +2863,31 @@ static int VDisplay2 (Draw_Interpretor& theDI, } ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto; + Standard_Integer isMutable = -1; for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) { - const TCollection_AsciiString aName = theArgVec[anArgIter]; + const TCollection_AsciiString aName = theArgVec[anArgIter]; + TCollection_AsciiString aNameCase = aName; + aNameCase.LowerCase(); if (parseRedrawMode (aName, aToUpdate)) { continue; } + else if (aNameCase == "-mutable") + { + isMutable = 1; + continue; + } else if (!GetMapOfAIS().IsBound2 (aName)) { // create the AIS_Shape from a name const Handle(AIS_InteractiveObject) aShape = GetAISShapeFromName (aName.ToCString()); if (!aShape.IsNull()) { + if (isMutable != -1) + { + aShape->SetMutable (isMutable == 1); + } GetMapOfAIS().Bind (aShape, aName); aCtx->Display (aShape, Standard_False); } @@ -2877,6 +2898,11 @@ static int VDisplay2 (Draw_Interpretor& theDI, if (anObj->IsKind (STANDARD_TYPE (AIS_InteractiveObject))) { Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anObj); + if (isMutable != -1) + { + aShape->SetMutable (isMutable == 1); + } + if (aShape->Type() == AIS_KOI_Datum) { aCtx->Display (aShape, Standard_False); @@ -2896,7 +2922,6 @@ static int VDisplay2 (Draw_Interpretor& theDI, aCtx->Redisplay (aShape, Standard_False); aCtx->Display (aShape, Standard_False); } - aShape.Nullify(); } else if (anObj->IsKind (STANDARD_TYPE (NIS_InteractiveObject))) { @@ -3088,14 +3113,19 @@ static int VAnimation (Draw_Interpretor& di, Standard_Integer argc, const char** GetMapOfAIS().Bind(myAisCrankArm,"c"); GetMapOfAIS().Bind(myAisPropeller,"d"); - TheAISContext()->SetColor(myAisCylinderHead, Quantity_NOC_INDIANRED); - TheAISContext()->SetColor(myAisEngineBlock , Quantity_NOC_RED); - TheAISContext()->SetColor(myAisPropeller , Quantity_NOC_GREEN); + myAisCylinderHead->SetMutable (Standard_True); + myAisEngineBlock ->SetMutable (Standard_True); + myAisCrankArm ->SetMutable (Standard_True); + myAisPropeller ->SetMutable (Standard_True); - TheAISContext()->Display(myAisCylinderHead,Standard_False); - TheAISContext()->Display(myAisEngineBlock,Standard_False ); - TheAISContext()->Display(myAisCrankArm,Standard_False ); - TheAISContext()->Display(myAisPropeller,Standard_False); + TheAISContext()->SetColor (myAisCylinderHead, Quantity_NOC_INDIANRED); + TheAISContext()->SetColor (myAisEngineBlock, Quantity_NOC_RED); + TheAISContext()->SetColor (myAisPropeller, Quantity_NOC_GREEN); + + TheAISContext()->Display (myAisCylinderHead, Standard_False); + TheAISContext()->Display (myAisEngineBlock, Standard_False); + TheAISContext()->Display (myAisCrankArm, Standard_False); + TheAISContext()->Display (myAisPropeller, Standard_False); TheAISContext()->Deactivate(myAisCylinderHead); TheAISContext()->Deactivate(myAisEngineBlock ); @@ -4215,9 +4245,10 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) __FILE__, visos, group); theCommands.Add("vdisplay", - "vdisplay [-noupdate|-update] name1 [name2] ... [name n]" + "vdisplay [-noupdate|-update] [-mutable] name1 [name2] ... [name n]" "\n\t\t: Displays named objects." "\n\t\t: Option -noupdate suppresses viewer redraw call." + "\n\t\t: Option -mutable enables optimizations for mutable objects." __FILE__,VDisplay2,group); theCommands.Add ("vupdate", @@ -4232,12 +4263,13 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) __FILE__, VErase, group); theCommands.Add("vremove", - "vremove [-noupdate|-update] [-context] [-all] [name1] ... [name n]" + "vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ... [name n]" "or vremove [-context] -all to remove all objects" "\n\t\t: Removes selected or named objects." "\n\t\t If -context is in arguments, the objects are not deleted" "\n\t\t from the map of objects and names." - "\n\t\t: Option -noupdate suppresses viewer redraw call.", + "\n\t\t: Option -noupdate suppresses viewer redraw call." + "\n\t\t: Option -noinfo suppresses displaying the list of removed objects.", __FILE__, VRemove, group); theCommands.Add("vdonly", diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index dd23be35c2..dd084484ad 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -2923,12 +2923,14 @@ static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const c Standard_Real aCenterY = (argc > 5) ? Draw::Atof (argv[4]) : 0.0; Standard_Real aCenterZ = (argc > 5) ? Draw::Atof (argv[5]) : 0.0; Standard_Real aRadius = (argc > 6) ? Draw::Atof (argv[6]) : 100.0; - Standard_Boolean toShowEdges = (argc > 7) ? Draw::Atoi (argv[7]) : Standard_False; + Standard_Boolean toShowEdges = (argc > 7) ? Draw::Atoi (argv[7]) == 1 : Standard_False; + Standard_Boolean toPrintInfo = (argc > 8) ? Draw::Atoi (argv[8]) == 1 : Standard_True; // remove AIS object with given name from map VDisplayAISObject (aShapeName, Handle(AIS_InteractiveObject)()); - std::cout << "Compute Triangulation...\n"; + if (toPrintInfo) + std::cout << "Compute Triangulation...\n"; Handle(AIS_Triangulation) aShape = new AIS_Triangulation (CalculationOfSphere (aCenterX, aCenterY, aCenterZ, aResolution, @@ -2967,12 +2969,15 @@ static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const c aColorsSize >>= 20; aTrianglesSize >>= 20; aPolyConnectSize >>= 20; - std::cout << "NumberOfPoints: " << aNumberPoints << "\n" - << "NumberOfTriangles: " << aNumberTriangles << "\n" - << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n" - << "Amount of memory for colors: " << aColorsSize << " Mb\n" - << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n" - << "Amount of graphic card memory required: " << aTotalSize << " Mb\n"; + if (toPrintInfo) + { + std::cout << "NumberOfPoints: " << aNumberPoints << "\n" + << "NumberOfTriangles: " << aNumberTriangles << "\n" + << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n" + << "Amount of memory for colors: " << aColorsSize << " Mb\n" + << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n" + << "Amount of graphic card memory required: " << aTotalSize << " Mb\n"; + } // Setting material properties, very important for desirable visual result! Graphic3d_MaterialAspect aMat (Graphic3d_NOM_PLASTIC); @@ -5283,7 +5288,7 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) __FILE__,VDrawText,group); theCommands.Add("vdrawsphere", - "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0]\n", + "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0] [ToPrintInfo=1]\n", __FILE__,VDrawSphere,group); theCommands.Add ("vsetlocation", diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index 2682f31748..8e3e8f2f40 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -86,7 +86,7 @@ public: public: Element (const Handle(VUserDrawObj)& theIObj, - CALL_DEF_BOUNDS* theBounds) + Graphic3d_BndBox4f* theBounds) : myIObj( theIObj ) { if (!myIObj.IsNull()) @@ -123,7 +123,7 @@ private: // Called by VUserDrawElement void Render(const Handle(OpenGl_Workspace)& theWorkspace) const; - void GetBounds(CALL_DEF_BOUNDS* theBounds); + void GetBounds(Graphic3d_BndBox4f* theBounds); GLfloat myCoords[6]; @@ -156,16 +156,21 @@ void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelec theSelection->Add(aSensitive); } -void VUserDrawObj::GetBounds(CALL_DEF_BOUNDS* theBounds) +void VUserDrawObj::GetBounds(Graphic3d_BndBox4f* theBounds) { if (theBounds) { - theBounds->XMin = myCoords[0]; - theBounds->YMin = myCoords[1]; - theBounds->ZMin = myCoords[2]; - theBounds->XMax = myCoords[3]; - theBounds->YMax = myCoords[4]; - theBounds->ZMax = myCoords[5]; + Graphic3d_Vec4 aMinPt (myCoords[0], myCoords[1], myCoords[2], 1.0f); + Graphic3d_Vec4 aMaxPt (myCoords[3], myCoords[4], myCoords[5], 1.0f); + if (!theBounds->IsValid()) + { + theBounds->Combine (Graphic3d_BndBox4f (aMinPt, aMaxPt)); + } + else + { + theBounds->CornerMin() = aMinPt; + theBounds->CornerMax() = aMaxPt; + } } } diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index f60b096966..f1d0263c2f 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -6603,6 +6603,53 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI, return 0; } +//======================================================================= +//function : VFrustumCulling +//purpose : enables/disables view volume's culling. +//======================================================================= +static int VFrustumCulling (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + Handle(V3d_View) aView = ViewerTest::CurrentView(); + if (aView.IsNull()) + { + std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n"; + return 1; + } + + if (theArgNb < 2) + { + theDI << (aView->IsCullingEnabled() ? "on" : "off"); + return 0; + } + else if (theArgNb != 2) + { + std::cout << theArgVec[0] << " Syntax error: Specify the mode\n"; + return 1; + } + + TCollection_AsciiString aModeStr (theArgVec[1]); + aModeStr.LowerCase(); + Standard_Boolean toEnable = 0; + if (aModeStr == "on") + { + toEnable = 1; + } + else if (aModeStr == "off") + { + toEnable = 0; + } + else + { + toEnable = Draw::Atoi (theArgVec[1]) != 0; + } + + aView->SetFrustumCulling (toEnable); + aView->Redraw(); + return 0; +} + //======================================================================= //function : ViewerCommands //purpose : @@ -6968,4 +7015,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "\n '-fsaa on|off' Enables/disables adaptive anti-aliasing" "\n '-gleam on|off' Enables/disables transparency shadow effects", __FILE__, VRenderParams, group); + theCommands.Add("vfrustumculling", + "vfrustumculling [toEnable]: enables/disables objects clipping", + __FILE__,VFrustumCulling,group); } diff --git a/src/Visual3d/Visual3d_View.cdl b/src/Visual3d/Visual3d_View.cdl index 0e7bbdf9ca..7f919c7aff 100644 --- a/src/Visual3d/Visual3d_View.cdl +++ b/src/Visual3d/Visual3d_View.cdl @@ -297,25 +297,6 @@ is ---Purpose: Sets the context in the view . ---Category: Methods to modify the class definition - SetTransform ( me : mutable; - AMatrix : Array2OfReal from TColStd ) - ---Level: Internal - ---Purpose: Sets the transformation matrix that is applied - -- to field of the view . - -- - -- is defined as a 4*4 real matrix. - -- - -- ------------------- - -- | a11 a12 a13 t1 | - -- | a21 a22 a23 t2 | - -- | a31 a32 a33 t3 | - -- | 0 0 0 1 | - -- ------------------- - -- - -- Category: Methods to modify the class definition - -- Warning: Raises TransformError if the matrix isn't a 4x4 matrix. - raises TransformError from Visual3d is static; - SetViewMappingDefault ( me : mutable ) is static; ---Level: Public diff --git a/src/Visual3d/Visual3d_View.cxx b/src/Visual3d/Visual3d_View.cxx index fb4f50174b..1834df728e 100644 --- a/src/Visual3d/Visual3d_View.cxx +++ b/src/Visual3d/Visual3d_View.cxx @@ -1189,8 +1189,7 @@ Standard_Integer Index = IsComputed (AStructure); << ", " << OldPriority << ", " << NewPriority << ")\n"; cout << flush; #endif - MyGraphicDriver->EraseStructure (MyCView, *(MyCOMPUTEDSequence.Value (Index)->CStructure())); - MyGraphicDriver->DisplayStructure (MyCView, *(MyCOMPUTEDSequence.Value (Index)->CStructure()), NewPriority); + MyGraphicDriver->ChangePriority (*(MyCOMPUTEDSequence.Value (Index)->CStructure()), MyCView, NewPriority); } else { @@ -1201,8 +1200,7 @@ Standard_Integer Index = IsComputed (AStructure); << ", " << OldPriority << ", " << NewPriority << ")\n"; cout << flush; #endif - MyGraphicDriver->EraseStructure (MyCView, *(AStructure->CStructure())); - MyGraphicDriver->DisplayStructure (MyCView, *(AStructure->CStructure()), NewPriority); + MyGraphicDriver->ChangePriority (*(AStructure->CStructure()), MyCView, NewPriority); } } @@ -1381,6 +1379,7 @@ Standard_Integer Index = IsComputed (AStructure); if (Answer == Visual3d_TOA_YES ) { if (IsDisplayed (AStructure)) return; + AStructure->CalculateBoundBox(); MyGraphicDriver->DisplayStructure (MyCView, *(AStructure->CStructure()), AStructure->DisplayPriority()); MyDisplayedStructure.Add (AStructure); if (AnUpdateMode == Aspect_TOU_ASAP) Update (); @@ -1628,6 +1627,14 @@ Standard_Integer Index = IsComputed (AStructure); MyCOMPUTEDSequence.Value (Index)->GraphicTransform (ATrsf); } + Standard_Integer aLayerId = AStructure->GetZLayer(); + if (!AStructure->IsMutable() + && !AStructure->CStructure()->IsForHighlight + && !AStructure->CStructure()->IsInfinite) + { + AStructure->CalculateBoundBox(); + MyGraphicDriver->InvalidateBVHData (MyCView, aLayerId); + } } void Visual3d_View::UnHighlight (const Handle(Graphic3d_Structure)& AStructure) { @@ -2089,6 +2096,13 @@ Graphic3d_SequenceOfStructure FooSequence; } void Visual3d_View::ReCompute (const Handle(Graphic3d_Structure)& AStructure) { + if (MyCView.IsCullingEnabled) + { + AStructure->CalculateBoundBox(); + Standard_Integer aLayerId = AStructure->DisplayPriority(); + MyGraphicDriver->InvalidateBVHData(MyCView, aLayerId); + } + if (!ComputedMode()) return; if (IsDeleted ()) return; diff --git a/tests/bugs/vis/bug24307_1 b/tests/bugs/vis/bug24307_1 new file mode 100644 index 0000000000..114bafee1a --- /dev/null +++ b/tests/bugs/vis/bug24307_1 @@ -0,0 +1,82 @@ +puts "========" +puts "OCC24307 Objects clipping algorithm using BVH performance test: Solid spheres test" +puts "========" + +# define objects' location parameters and their characteristics +set SPHERES_NUM 10 +set SPERE_RADIUS 100 +set SPHERE_FINENESS 10 +set PERCENT_OF_INNER_SPHERES 30 + +# window parameters +set SMALL_WIN_WIDTH 512 +set SMALL_WIN_HEIGHT 512 + +# other +array set aSphereNames {} + +set aWithoutClippingSnapshot $imagedir/${casename}_without.png +set aWithClippingSnapshot $imagedir/${casename}_with.png +set aDiffImage $imagedir/${casename}_diff.png + +pload VISUALIZATION MODELING +vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT +vactivate small_wnd +vfrustumculling 0 +vautozfit 0 +vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573 +vzrange 1 512 +vclear +vremove -all -noinfo + +puts [vdrawsphere tmp_sph $SPHERE_FINENESS] +vremove -noinfo tmp_sph + +set aInnerSpheresNum [expr $SPHERES_NUM * $PERCENT_OF_INNER_SPHERES / 100] +puts "" +set aDebugInfo "Total number of visible objects: " +append aDebugInfo $aInnerSpheresNum +puts $aDebugInfo +puts "" + +puts "Start displaying spheres without clipping..." +set aInnerWidthStep [expr $SMALL_WIN_WIDTH / ($aInnerSpheresNum + 1)] +set aInnerHeightStep [expr $SMALL_WIN_HEIGHT / ($aInnerSpheresNum + 1)] +set aOuterStep [expr $SPERE_RADIUS * 3 / ($SPHERES_NUM - $aInnerSpheresNum + 1)] +for {set i 0} {$i < $aInnerSpheresNum} {incr i} { + set aCurrName "inner_sph" + append aCurrName $i + set aX [expr - $SMALL_WIN_WIDTH / 2 + ($i + 1) * $aInnerWidthStep ] + set aY [expr - $SMALL_WIN_HEIGHT / 2 + ($i + 1) * $aInnerHeightStep ] + vdrawsphere $aCurrName $SPHERE_FINENESS $aX $aY 0 $SPERE_RADIUS 0 0 + set aSphereNames($i) $aCurrName +} +for {set i $aInnerSpheresNum} {$i < $SPHERES_NUM} {incr i} { + set aCurrName "outer_sph" + append aCurrName $i + set aX [expr - $SMALL_WIN_WIDTH - $SPERE_RADIUS * 3 + ($i - $aInnerSpheresNum + 1) * $aOuterStep ] + set aY [expr - $SMALL_WIN_HEIGHT - $SPERE_RADIUS * 3 + ($i - $aInnerSpheresNum + 1) * $aOuterStep ] + vdrawsphere $aCurrName $SPHERE_FINENESS $aX $aY 0 $SPERE_RADIUS 0 0 + set aSphereNames($i) $aCurrName +} +puts [vfps] +vdump $aWithoutClippingSnapshot +puts "All spheres were displayed." +puts "" + +verase + +puts "Start displaying spheres with clipping..." +vfrustumculling 1 +vdisplayall +puts [vfps] +vdump $aWithClippingSnapshot +puts "All spheres were displayed." +puts "" + +set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage] +if {$aDiffImageResult != 0} { + puts "ERROR : Test failed: there is a difference between images rendered with and without clipping" +} + +verase diff --git a/tests/bugs/vis/bug24307_2 b/tests/bugs/vis/bug24307_2 new file mode 100644 index 0000000000..8e2576770f --- /dev/null +++ b/tests/bugs/vis/bug24307_2 @@ -0,0 +1,86 @@ +puts "========" +puts "OCC24307 Objects clipping algorithm using BVH performance test: Simple boxes test" +puts "========" + +# object characteristics +set BOXES_NUM 10 +set BOX_SIZE 100 +set PERCENT_OF_INNER_BOXES 30 + +# window parameters +set SMALL_WIN_WIDTH 512 +set SMALL_WIN_HEIGHT 512 + +# other +array set aBoxNames {} + +set aWithoutClippingSnapshot $imagedir/${casename}_without.png +set aWithClippingSnapshot $imagedir/${casename}_with.png +set aDiffImage $imagedir/${casename}_diff.png + +pload VISUALIZATION MODELING +vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT +vactivate small_wnd +vfrustumculling 0 +vautozfit 0 +vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573 +vzrange 1 512 +vclear +vremove -all -noinfo + +set aInnerBoxesNum [expr $BOXES_NUM * $PERCENT_OF_INNER_BOXES / 100] +puts "" +set aDebugInfo "Total number of visible objects: " +append aDebugInfo $aInnerBoxesNum +puts $aDebugInfo +puts "" + +puts "Start boxes generation..." +set aInnerWidthStep [expr $SMALL_WIN_WIDTH / (2 * ($aInnerBoxesNum + 1))] +set aInnerHeightStep [expr $SMALL_WIN_HEIGHT / (2 * ($aInnerBoxesNum + 1))] +set aOuterStep [expr $BOX_SIZE * 3 / ($BOXES_NUM - $aInnerBoxesNum + 1)] +for {set i 0} {$i < $aInnerBoxesNum} {incr i} { + set aCurrName "inner_box" + append aCurrName $i + set aX [expr - $SMALL_WIN_WIDTH / 4 + ($i + 1) * $aInnerWidthStep ] + set aY [expr - $SMALL_WIN_HEIGHT / 4 + ($i + 1) * $aInnerHeightStep ] + box $aCurrName $aX $aY 0 $BOX_SIZE $BOX_SIZE $BOX_SIZE + set aBoxNames($i) $aCurrName +} +for {set i $aInnerBoxesNum} {$i < $BOXES_NUM} {incr i} { + set aCurrName "outer_box" + append aCurrName $i + set aX [expr - $SMALL_WIN_WIDTH - $BOX_SIZE * 3 + ($i - $aInnerBoxesNum + 1) * $aOuterStep] + set aY [expr - $SMALL_WIN_HEIGHT - $BOX_SIZE * 3 + ($i - $aInnerBoxesNum + 1) * $aOuterStep] + box $aCurrName $aX $aY 0 $BOX_SIZE $BOX_SIZE $BOX_SIZE + set aBoxNames($i) $aCurrName +} +puts "$BOXES_NUM boxes generated." +puts "" + +puts "Start displaying boxes without clipping..." +for {set i 0} {$i < $BOXES_NUM} {incr i} { + vdisplay -noupdate $aBoxNames($i) +} +puts [vfps] +vdump $aWithoutClippingSnapshot +puts "All boxes were displayed." +puts "" + +verase + +vfrustumculling 1 +puts "Start displaying boxes with clipping..." +for {set i 0} {$i < $BOXES_NUM} {incr i} { + vdisplay -noupdate $aBoxNames($i) +} +puts [vfps] +vdump $aWithClippingSnapshot +puts "All boxes were displayed." + +set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage] +if {$aDiffImageResult != 0} { + puts "ERROR : Test failed: there is a difference between images rendered with and without clipping" +} + +verase -- 2.20.1