From af989e9d1d8c5eb7b51db53dc2e887b4ff3fb5a2 Mon Sep 17 00:00:00 2001 From: vpa Date: Tue, 8 Dec 2015 09:11:46 +0300 Subject: [PATCH] Draft implementation of LOD API in OCCT: - implemented interfaces for LOD at OpenGl, Graphic3d and MeshVS levels; - added LOD managers at Graphic3d and OpenGl levels; - simple mechanism of LOD switching is implemented in LOD manager; - distance to COG metric is temporarily used; - the metric could be redefined using custom LOD selectors; - LODs are added to MeshVS_Mesh in Compute method and are listed as its data sources; - added commands meshgenlod and meshlod to generate LODs for mesh and its topological representation and bind them to its OpenGl structures. --- src/Graphic3d/FILES | 7 + src/Graphic3d/Graphic3d_CStructure.hxx | 10 + src/Graphic3d/Graphic3d_LOD.cxx | 39 ++ src/Graphic3d/Graphic3d_LOD.hxx | 96 +++ .../Graphic3d_LODDistanceSelector.cxx | 34 ++ .../Graphic3d_LODDistanceSelector.hxx | 38 ++ src/Graphic3d/Graphic3d_LODManager.cxx | 85 +++ src/Graphic3d/Graphic3d_LODManager.hxx | 75 +++ src/Graphic3d/Graphic3d_LODSelector.hxx | 38 ++ src/Graphic3d/Graphic3d_Structure.cxx | 27 + src/Graphic3d/Graphic3d_Structure.hxx | 9 + src/MeshVS/FILES | 4 + src/MeshVS/MeshVS_DataSource.hxx | 116 ++-- src/MeshVS/MeshVS_LODBuilder.cxx | 546 ++++++++++++++++++ src/MeshVS/MeshVS_LODBuilder.hxx | 66 +++ src/MeshVS/MeshVS_LODDataSource.cxx | 179 ++++++ src/MeshVS/MeshVS_LODDataSource.hxx | 93 +++ src/MeshVS/MeshVS_Mesh.cxx | 30 + src/MeshVS/MeshVS_Mesh.hxx | 17 +- src/MeshVS/MeshVS_MeshPrsBuilder.cxx | 31 +- src/MeshVS/MeshVS_MeshPrsBuilder.hxx | 123 ++-- src/OpenGl/FILES | 4 + src/OpenGl/OpenGl_LOD.cxx | 29 + src/OpenGl/OpenGl_LOD.hxx | 38 ++ src/OpenGl/OpenGl_LODManager.cxx | 77 +++ src/OpenGl/OpenGl_LODManager.hxx | 38 ++ src/OpenGl/OpenGl_Structure.cxx | 57 +- src/OpenGl/OpenGl_Structure.hxx | 16 +- src/Prs3d/Prs3d_Root.hxx | 17 +- src/TKMeshVS/EXTERNLIB | 1 + src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx | 372 ++++++++++++ tests/bugs/vis/bug26812 | 24 + 32 files changed, 2216 insertions(+), 120 deletions(-) create mode 100644 src/Graphic3d/Graphic3d_LOD.cxx create mode 100644 src/Graphic3d/Graphic3d_LOD.hxx create mode 100644 src/Graphic3d/Graphic3d_LODDistanceSelector.cxx create mode 100644 src/Graphic3d/Graphic3d_LODDistanceSelector.hxx create mode 100644 src/Graphic3d/Graphic3d_LODManager.cxx create mode 100644 src/Graphic3d/Graphic3d_LODManager.hxx create mode 100644 src/Graphic3d/Graphic3d_LODSelector.hxx create mode 100644 src/MeshVS/MeshVS_LODBuilder.cxx create mode 100644 src/MeshVS/MeshVS_LODBuilder.hxx create mode 100644 src/MeshVS/MeshVS_LODDataSource.cxx create mode 100644 src/MeshVS/MeshVS_LODDataSource.hxx create mode 100644 src/OpenGl/OpenGl_LOD.cxx create mode 100644 src/OpenGl/OpenGl_LOD.hxx create mode 100644 src/OpenGl/OpenGl_LODManager.cxx create mode 100644 src/OpenGl/OpenGl_LODManager.hxx create mode 100644 tests/bugs/vis/bug26812 diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index ef47d46dc2..701e205d9f 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -77,6 +77,13 @@ Graphic3d_InitialisationError.hxx Graphic3d_LevelOfTextureAnisotropy.hxx Graphic3d_ListIteratorOfListOfShortReal.hxx Graphic3d_ListOfShortReal.hxx +Graphic3d_LOD.hxx +Graphic3d_LOD.cxx +Graphic3d_LODSelector.hxx +Graphic3d_LODDistanceSelector.hxx +Graphic3d_LODDistanceSelector.cxx +Graphic3d_LODManager.hxx +Graphic3d_LODManager.cxx Graphic3d_MapIteratorOfMapOfStructure.hxx Graphic3d_MapOfObject.hxx Graphic3d_MapOfStructure.hxx diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index cc2bee3625..963f326fdf 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -28,6 +28,8 @@ class Graphic3d_GraphicDriver; class Graphic3d_StructureManager; +class Graphic3d_LOD; +class Graphic3d_LODManager; //! Low-level graphic structure interface class Graphic3d_CStructure : public Standard_Transient @@ -112,9 +114,16 @@ public: //! Create new group within this structure virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theStruct) = 0; + //! Create new LOD within this structure + virtual Handle(Graphic3d_LOD) NewLOD (const Handle(Graphic3d_Structure)& theStruct) = 0; + //! Remove group from this structure virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) = 0; + virtual Standard_Integer NbDetailLevels() const = 0; + + virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo) = 0; + public: int Id; @@ -157,6 +166,7 @@ protected: Graphic3d_SequenceOfGroup myGroups; Graphic3d_BndBox4f myBndBox; Graphic3d_SequenceOfHClipPlane myClipPlanes; + Handle(Graphic3d_LODManager) myLODManager; public: diff --git a/src/Graphic3d/Graphic3d_LOD.cxx b/src/Graphic3d/Graphic3d_LOD.cxx new file mode 100644 index 0000000000..badb32bcdd --- /dev/null +++ b/src/Graphic3d/Graphic3d_LOD.cxx @@ -0,0 +1,39 @@ +// Created on: 2015-10-29 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 + +IMPLEMENT_STANDARD_RTTIEXT (Graphic3d_LOD, Standard_Transient) + +//======================================================================= +// function : Destructor +// purpose : +//======================================================================= +Graphic3d_LOD::~Graphic3d_LOD() +{ + myGroups.Clear(); +} + +//======================================================================= +// function : SetRange +// purpose : +//======================================================================= +void Graphic3d_LOD::SetRange (const Standard_Real theFrom, const Standard_Real theTo) +{ + Standard_ASSERT_RAISE (theFrom < theTo, + "The upper boundary of the interval must be greater than lower one!"); + + myRange = Graphic3d_RangeOfLOD (theFrom, theTo); +} diff --git a/src/Graphic3d/Graphic3d_LOD.hxx b/src/Graphic3d/Graphic3d_LOD.hxx new file mode 100644 index 0000000000..d86bf8d5b0 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LOD.hxx @@ -0,0 +1,96 @@ +// Created on: 2015-10-29 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LOD_Header +#define _Graphic3d_LOD_Header + +#include +#include +#include +#include +#include +#include + +struct Graphic3d_RangeOfLOD +{ +public: + Graphic3d_RangeOfLOD (const Standard_Real theFrom, const Standard_Real theTo) + : myTo (theTo), + myFrom (theFrom) + { + Standard_ASSERT_RAISE (theFrom < theTo, + "The upper boundary of the interval must be greater than lower one!"); + } + + Standard_Boolean IsIn (const Standard_Real theVal) const + { + return (myFrom < theVal) && (theVal < myTo); + } + + Standard_Boolean IsLess (const Standard_Real theVal) const + { + return theVal < myFrom; + } + + Standard_Boolean IsGreater (const Standard_Real theVal) const + { + return myTo < theVal; + } + + bool operator < (const Graphic3d_RangeOfLOD& theOther) const + { + return myFrom < theOther.myFrom; + } + +private: + Standard_Real myFrom; + Standard_Real myTo; +}; + +class Graphic3d_LOD : public Standard_Transient +{ +public: + Standard_EXPORT virtual ~Graphic3d_LOD(); + + Standard_EXPORT void SetRange (const Standard_Real theFrom, const Standard_Real theTo); + + Standard_EXPORT const Graphic3d_RangeOfLOD& GetRange() const + { + return myRange; + } + + Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& /*theParentStruct*/) + { + return NULL; + }; + + const Graphic3d_SequenceOfGroup& GetDrawGroups() const + { + return myGroups; + } + + DEFINE_STANDARD_RTTIEXT (Graphic3d_LOD, Standard_Transient) + +protected: + Standard_EXPORT Graphic3d_LOD() : myRange (-DBL_MAX, DBL_MAX) {}; + +protected: + Graphic3d_SequenceOfGroup myGroups; + Graphic3d_RangeOfLOD myRange; +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_LOD, Standard_Transient) + +#endif // _Graphic3d_LOD_Header diff --git a/src/Graphic3d/Graphic3d_LODDistanceSelector.cxx b/src/Graphic3d/Graphic3d_LODDistanceSelector.cxx new file mode 100644 index 0000000000..44f7cc5007 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LODDistanceSelector.cxx @@ -0,0 +1,34 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 + +IMPLEMENT_STANDARD_RTTIEXT (Graphic3d_LODDistanceSelector, Graphic3d_LODSelector) + +//======================================================================= +// function : ComputeMetric +// purpose : +//======================================================================= +Standard_Real Graphic3d_LODDistanceSelector::ComputeMetric (const Handle(Graphic3d_CStructure)& theParentStructure, + const Handle(Graphic3d_Camera)& theCamera) +{ + const Graphic3d_BndBox4f& aBndBox = theParentStructure->BoundingBox(); + const Graphic3d_Vec4 aCenter = aBndBox.Center(); + const gp_Pnt aGpCenter = gp_Pnt (aCenter.x(), aCenter.y(), aCenter.z()); + return (theCamera->Eye().Distance (aGpCenter)) / theCamera->Scale(); +} diff --git a/src/Graphic3d/Graphic3d_LODDistanceSelector.hxx b/src/Graphic3d/Graphic3d_LODDistanceSelector.hxx new file mode 100644 index 0000000000..55677698f4 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LODDistanceSelector.hxx @@ -0,0 +1,38 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LODDistanceSelector_Header +#define _Graphic3d_LODDistanceSelector_Header + +#include + +class Graphic3d_CStructure; +class Graphic3d_Camera; + +class Graphic3d_LODDistanceSelector : public Graphic3d_LODSelector +{ +public: + Standard_EXPORT Graphic3d_LODDistanceSelector() {}; + Standard_EXPORT virtual ~Graphic3d_LODDistanceSelector() {}; + + Standard_EXPORT virtual Standard_Real ComputeMetric (const Handle(Graphic3d_CStructure)& theParentStructure, + const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (Graphic3d_LODDistanceSelector, Graphic3d_LODSelector) +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_LODDistanceSelector, Graphic3d_LODSelector) + +#endif // _Graphic3d_LODDistanceSelector_Header diff --git a/src/Graphic3d/Graphic3d_LODManager.cxx b/src/Graphic3d/Graphic3d_LODManager.cxx new file mode 100644 index 0000000000..1bdc02bb70 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LODManager.cxx @@ -0,0 +1,85 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 + +IMPLEMENT_STANDARD_RTTIEXT (Graphic3d_LODManager, Standard_Transient) + +//======================================================================= +// function : Creation +// purpose : +//======================================================================= +Graphic3d_LODManager::Graphic3d_LODManager (const Handle(Graphic3d_Structure)& theParentStructure) + : myCurrentLODIdx (-1), + mySelector (new Graphic3d_LODDistanceSelector()) +{ + myStructure = theParentStructure.operator->(); +} + +//======================================================================= +// function : GetCurrentLODIdx +// purpose : +//======================================================================= +Standard_Integer Graphic3d_LODManager::GetCurrentLODIdx (const Handle(Graphic3d_Camera)& theCamera) +{ + if (theCamera->WorldViewProjState() == myPrevCameraState && myCurrentLODIdx != -1) + return myCurrentLODIdx; + + myPrevCameraState = theCamera->WorldViewProjState(); + const Standard_Real aMetric = mySelector->ComputeMetric (myStructure->CStructure(), theCamera); + if (myLODs.Value (0)->GetRange().IsLess (aMetric)) + { + myCurrentLODIdx = -1; + } + else if (myLODs.Value (myLODs.Size() - 1)->GetRange().IsGreater (aMetric)) + { + myCurrentLODIdx = myLODs.Size() - 1; + } + else + { + for (Standard_Integer aLodIdx = 0; aLodIdx < myLODs.Size(); ++aLodIdx) + { + if (myLODs.Value (aLodIdx)->GetRange().IsIn (aMetric)) + { + myCurrentLODIdx = aLodIdx; + break; + } + } + } + + return myCurrentLODIdx; +} + +//======================================================================= +// function : SetRange +// purpose : +//======================================================================= +void Graphic3d_LODManager::SetRange (const Standard_Integer theLodIdx, + const Standard_Real theFrom, + const Standard_Real theTo) +{ + myLODs.ChangeValue (theLodIdx)->SetRange (theFrom, theTo); + sortLODs(); +} + +//======================================================================= +// function : GetCurrentGroups +// purpose : +//======================================================================= + const Graphic3d_SequenceOfGroup& Graphic3d_LODManager::GetCurrentGroups() const + { + return myLODs.Value (myCurrentLODIdx)->GetDrawGroups(); + } diff --git a/src/Graphic3d/Graphic3d_LODManager.hxx b/src/Graphic3d/Graphic3d_LODManager.hxx new file mode 100644 index 0000000000..7efbb09a59 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LODManager.hxx @@ -0,0 +1,75 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LODManager_Header +#define _Graphic3d_LODManager_Header + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Graphic3d_LODManager : public Standard_Transient +{ +public: + + Standard_EXPORT virtual ~Graphic3d_LODManager() {}; + + Standard_EXPORT void SetSelector (const Handle(Graphic3d_LODSelector)& theSelector) + { + mySelector = theSelector; + } + + Standard_EXPORT inline Standard_Integer NbOfDetailLevels() const + { + return myLODs.Size(); + } + + Standard_EXPORT void SetRange (const Standard_Integer theLodIdx, + const Standard_Real theFrom, + const Standard_Real theTo); + + Standard_EXPORT Standard_Integer GetCurrentLODIdx (const Handle(Graphic3d_Camera)& theCamera); + + Standard_EXPORT const Graphic3d_SequenceOfGroup& GetCurrentGroups() const; + + Standard_EXPORT virtual Handle(Graphic3d_LOD) AddNewLOD() = 0; + + DEFINE_STANDARD_RTTIEXT (Graphic3d_LODManager, Standard_Transient) + +protected: + Standard_EXPORT Graphic3d_LODManager (const Handle(Graphic3d_Structure)& theParentStructure); + + Standard_EXPORT virtual void sortLODs() {}; + +protected: + NCollection_Vector myLODs; + +private: + Standard_Integer myCurrentLODIdx; + Handle(Graphic3d_LODSelector) mySelector; + Graphic3d_StructurePtr myStructure; + Graphic3d_WorldViewProjState myPrevCameraState; +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_LODManager, Standard_Transient) + +#endif //_Graphic3d_LODManager_Header diff --git a/src/Graphic3d/Graphic3d_LODSelector.hxx b/src/Graphic3d/Graphic3d_LODSelector.hxx new file mode 100644 index 0000000000..000fe1fcc8 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LODSelector.hxx @@ -0,0 +1,38 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LODSelector_Header +#define _Graphic3d_LODSelector_Header + +#include +#include +#include + +class Graphic3d_CStructure; +class Graphic3d_Camera; + +class Graphic3d_LODSelector : public Standard_Transient +{ +public: + + virtual Standard_Real ComputeMetric (const Handle(Graphic3d_CStructure)& theParentStructure, + const Handle(Graphic3d_Camera)& theCamera) = 0; + + DEFINE_STANDARD_RTTI_INLINE (Graphic3d_LODSelector, Standard_Transient) +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_LODSelector, Standard_Transient) + +#endif // _Graphic3d_LODSelector_Header diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index a32663511a..9c8d889da6 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -1709,6 +1709,33 @@ Handle(Graphic3d_Group) Graphic3d_Structure::NewGroup() return myCStructure->NewGroup (this); } +//============================================================================= +//function : NewLOD +//purpose : +//============================================================================= +Handle(Graphic3d_LOD) Graphic3d_Structure::NewLOD() +{ + return myCStructure->NewLOD (this); +} + +//============================================================================= +//function : NbDetailLevels +//purpose : +//============================================================================= +Standard_Integer Graphic3d_Structure::NbDetailLevels() const +{ + return myCStructure->NbDetailLevels(); +} + +//============================================================================= +//function : SetDetailLevelRange +//purpose : +//============================================================================= +void Graphic3d_Structure::SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo) +{ + myCStructure->SetDetailLevelRange (theIdOfLOD, theFrom, theTo); +} + //============================================================================= //function : Remove //purpose : diff --git a/src/Graphic3d/Graphic3d_Structure.hxx b/src/Graphic3d/Graphic3d_Structure.hxx index 2fdc75f6e9..57332dbf50 100644 --- a/src/Graphic3d/Graphic3d_Structure.hxx +++ b/src/Graphic3d/Graphic3d_Structure.hxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ class Graphic3d_AspectFillArea3d; class Graphic3d_AspectText3d; class Graphic3d_AspectMarker3d; class Graphic3d_DataStructureManager; +class Graphic3d_LOD; class Bnd_Box; class gp_Pnt; class Graphic3d_Vector; @@ -259,6 +261,9 @@ public: //! Append new group to this structure. Standard_EXPORT Handle(Graphic3d_Group) NewGroup(); + + //! Append new LOD to this structure. + Standard_EXPORT Handle(Graphic3d_LOD) NewLOD(); //! Returns the highlight color for the Highlight method //! with the highlight method TOHM_COLOR or TOHM_BOUNDBOX. @@ -484,6 +489,10 @@ public: //! Returns the low-level structure const Handle(Graphic3d_CStructure)& CStructure() const; + Standard_EXPORT Standard_Integer NbDetailLevels() const; + + Standard_EXPORT void SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo); + friend class Graphic3d_Group; diff --git a/src/MeshVS/FILES b/src/MeshVS/FILES index 03957f44b9..d8e133a751 100755 --- a/src/MeshVS/FILES +++ b/src/MeshVS/FILES @@ -41,6 +41,10 @@ MeshVS_ElementalColorPrsBuilder.cxx MeshVS_ElementalColorPrsBuilder.hxx MeshVS_EntityType.hxx MeshVS_HArray1OfSequenceOfInteger.hxx +MeshVS_LODBuilder.hxx +MeshVS_LODBuilder.cxx +MeshVS_LODDataSource.hxx +MeshVS_LODDataSource.cxx MeshVS_MapIteratorOfMapOfTwoNodes.hxx MeshVS_MapOfTwoNodes.hxx MeshVS_Mesh.cxx diff --git a/src/MeshVS/MeshVS_DataSource.hxx b/src/MeshVS/MeshVS_DataSource.hxx index c02e0782a8..38687251aa 100644 --- a/src/MeshVS/MeshVS_DataSource.hxx +++ b/src/MeshVS/MeshVS_DataSource.hxx @@ -56,7 +56,7 @@ class MeshVS_DataSource : public MMgt_TShared public: - + //! Returns geometry information about node or element //! ID is the numerical identificator of node or element //! IsElement indicates this ID describe node ( if Standard_False ) or element ( if Standard_True ) @@ -67,33 +67,44 @@ public: //! NbNodes is number of nodes. It is recommended this parameter to be set to 1 for node. //! Type is type of node or element (from enumeration). It is recommended this parameter to be set to //! MeshVS_ET_Node for node. - Standard_EXPORT virtual Standard_Boolean GetGeom (const Standard_Integer ID, const Standard_Boolean IsElement, TColStd_Array1OfReal& Coords, Standard_Integer& NbNodes, MeshVS_EntityType& Type) const = 0; - + Standard_EXPORT virtual Standard_Boolean GetGeom (const Standard_Integer ID, + const Standard_Boolean IsElement, + TColStd_Array1OfReal& Coords, + Standard_Integer& NbNodes, + MeshVS_EntityType& Type) const = 0; + //! This method is similar to GetGeom, but returns only element or node type. - Standard_EXPORT virtual Standard_Boolean GetGeomType (const Standard_Integer ID, const Standard_Boolean IsElement, MeshVS_EntityType& Type) const = 0; - + Standard_EXPORT virtual Standard_Boolean GetGeomType (const Standard_Integer ID, + const Standard_Boolean IsElement, + MeshVS_EntityType& Type) const = 0; + //! This method returns topology information about 3D-element //! Returns false if element with ID isn't 3D or because other troubles - Standard_EXPORT virtual Standard_Boolean Get3DGeom (const Standard_Integer ID, Standard_Integer& NbNodes, Handle(MeshVS_HArray1OfSequenceOfInteger)& Data) const; - + Standard_EXPORT virtual Standard_Boolean Get3DGeom (const Standard_Integer ID, + Standard_Integer& NbNodes, + Handle(MeshVS_HArray1OfSequenceOfInteger)& Data) const; + //! This method returns pointer which represents element or node data structure. //! This address will be saved in MeshVS_MeshEntityOwner, so that you can access to data structure fast //! by the method Owner(). In the redefined method you can return NULL. //! ID is the numerical identificator of node or element //! IsElement indicates this ID describe node ( if Standard_False ) or element ( if Standard_True ) - Standard_EXPORT virtual Standard_Address GetAddr (const Standard_Integer ID, const Standard_Boolean IsElement) const = 0; - + Standard_EXPORT virtual Standard_Address GetAddr (const Standard_Integer ID, + const Standard_Boolean IsElement) const = 0; + //! This method returns information about nodes this element consist of. //! ID is the numerical identificator of element. //! NodeIDs is the output array of nodes IDs in correct order, //! the same as coordinates returned by GetGeom(). //! NbNodes is number of nodes (number of items set in NodeIDs). //! Returns False if element does not exist - Standard_EXPORT virtual Standard_Boolean GetNodesByElement (const Standard_Integer ID, TColStd_Array1OfInteger& NodeIDs, Standard_Integer& NbNodes) const = 0; - + Standard_EXPORT virtual Standard_Boolean GetNodesByElement (const Standard_Integer ID, + TColStd_Array1OfInteger& NodeIDs, + Standard_Integer& NbNodes) const = 0; + //! This method returns map of all nodes the object consist of. Standard_EXPORT virtual const TColStd_PackedMapOfInteger& GetAllNodes() const = 0; - + //! This method returns map of all elements the object consist of. Standard_EXPORT virtual const TColStd_PackedMapOfInteger& GetAllElements() const = 0; @@ -105,13 +116,21 @@ public: //! In the redefined method you can return normal with length more then 1, but in this case //! the appearance of element will be more bright than usual. For ordinary brightness you must return //! normal with length 1 - Standard_EXPORT virtual Standard_Boolean GetNormal (const Standard_Integer Id, const Standard_Integer Max, Standard_Real& nx, Standard_Real& ny, Standard_Real& nz) const; - + Standard_EXPORT virtual Standard_Boolean GetNormal (const Standard_Integer Id, + const Standard_Integer Max, + Standard_Real& nx, + Standard_Real& ny, + Standard_Real& nz) const; + //! This method return normal of node ranknode of face Id, //! which is using for smooth shading presentation. //! Returns false if normal isn't defined. - Standard_EXPORT virtual Standard_Boolean GetNodeNormal (const Standard_Integer ranknode, const Standard_Integer ElementId, Standard_Real& nx, Standard_Real& ny, Standard_Real& nz) const; - + Standard_EXPORT virtual Standard_Boolean GetNodeNormal (const Standard_Integer ranknode, + const Standard_Integer ElementId, + Standard_Real& nx, + Standard_Real& ny, + Standard_Real& nz) const; + //! This method puts components of normal vectors at each node of a mesh face (at each face of a mesh volume) //! into the output array. //! Returns false if some problem was detected during calculation of normals. @@ -123,13 +142,18 @@ public: //! volume: normals to all faces of the volume are computed (not for each node!). //! MaxNodes is maximal number of nodes an element can consist of. //! Normals contains the result. - Standard_EXPORT virtual Standard_Boolean GetNormalsByElement (const Standard_Integer Id, const Standard_Boolean IsNodal, const Standard_Integer MaxNodes, Handle(TColStd_HArray1OfReal)& Normals) const; - + Standard_EXPORT virtual Standard_Boolean GetNormalsByElement (const Standard_Integer Id, + const Standard_Boolean IsNodal, + const Standard_Integer MaxNodes, + Handle(TColStd_HArray1OfReal)& Normals) const; + //! This method returns map of all groups the object contains. Standard_EXPORT virtual void GetAllGroups (TColStd_PackedMapOfInteger& Ids) const; - + //! This method returns map of all group elements. - Standard_EXPORT virtual Standard_Boolean GetGroup (const Standard_Integer Id, MeshVS_EntityType& Type, TColStd_PackedMapOfInteger& Ids) const; + Standard_EXPORT virtual Standard_Boolean GetGroup (const Standard_Integer Id, + MeshVS_EntityType& Type, + TColStd_PackedMapOfInteger& Ids) const; //! This method returns pointer which represents group data structure. //! This address will be saved in MeshVS_MeshOwner, so that you can access to data structure fast @@ -156,7 +180,13 @@ public: //! Returns True if something is detected. //! It should be redefined if the advanced mesh selection is //! activated. Default implementation returns False. - Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, const Standard_Real X, const Standard_Real Y, const Standard_Real aTol, Handle(TColStd_HPackedMapOfInteger)& Nodes, Handle(TColStd_HPackedMapOfInteger)& Elements, Standard_Real& DMin); + Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, + const Standard_Real X, + const Standard_Real Y, + const Standard_Real aTol, + Handle(TColStd_HPackedMapOfInteger)& Nodes, + Handle(TColStd_HPackedMapOfInteger)& Elements, + Standard_Real& DMin); //! Returns maps of entities (nodes and elements) detected //! by mouse selection with rectangular box (XMin, YMin, XMax, YMax) @@ -164,45 +194,39 @@ public: //! Returns True if something is detected. //! It should be redefined if the advanced mesh selection is //! activated. Default implementation returns False. - Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, const Standard_Real XMin, const Standard_Real YMin, const Standard_Real XMax, const Standard_Real YMax, const Standard_Real aTol, Handle(TColStd_HPackedMapOfInteger)& Nodes, Handle(TColStd_HPackedMapOfInteger)& Elements); - + Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, + const Standard_Real XMin, + const Standard_Real YMin, + const Standard_Real XMax, + const Standard_Real YMax, + const Standard_Real aTol, + Handle(TColStd_HPackedMapOfInteger)& Nodes, + Handle(TColStd_HPackedMapOfInteger)& Elements); + //! Returns maps of entities (nodes and elements) detected //! by mouse selection with the polyline //! on the current veiw plane, with the tolerance aTol. //! Returns True if something is detected. //! It should be redefined if the advanced mesh selection is //! activated. Default implementation returns False. - Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, const TColgp_Array1OfPnt2d& Polyline, const Bnd_Box2d& aBox, const Standard_Real aTol, Handle(TColStd_HPackedMapOfInteger)& Nodes, Handle(TColStd_HPackedMapOfInteger)& Elements); - + Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, + const TColgp_Array1OfPnt2d& Polyline, + const Bnd_Box2d& aBox, + const Standard_Real aTol, + Handle(TColStd_HPackedMapOfInteger)& Nodes, + Handle(TColStd_HPackedMapOfInteger)& Elements); + //! Filter out the maps of mesh entities so as to keep //! only the entities that are allowed to be selected //! according to the current context. //! Returns True if any of the maps has been changed. //! It should be redefined if the advanced mesh selection is //! activated. Default implementation returns False. - Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, Handle(TColStd_HPackedMapOfInteger)& Nodes, Handle(TColStd_HPackedMapOfInteger)& Elements); - - - + Standard_EXPORT virtual Standard_Boolean GetDetectedEntities (const Handle(MeshVS_Mesh)& Prs, + Handle(TColStd_HPackedMapOfInteger)& Nodes, + Handle(TColStd_HPackedMapOfInteger)& Elements); DEFINE_STANDARD_RTTIEXT(MeshVS_DataSource,MMgt_TShared) - -protected: - - - - -private: - - - - }; - - - - - - #endif // _MeshVS_DataSource_HeaderFile diff --git a/src/MeshVS/MeshVS_LODBuilder.cxx b/src/MeshVS/MeshVS_LODBuilder.cxx new file mode 100644 index 0000000000..4bce494d02 --- /dev/null +++ b/src/MeshVS/MeshVS_LODBuilder.cxx @@ -0,0 +1,546 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT (MeshVS_LODBuilder, MeshVS_PrsBuilder) + +//======================================================================= +// function : Creation +// purpose : +//======================================================================= +MeshVS_LODBuilder::MeshVS_LODBuilder (const Handle(MeshVS_Mesh)& theParentMesh, + const MeshVS_DisplayModeFlags& theFlags, + const Handle(MeshVS_LODDataSource)& theDataSource, + const Standard_Integer theId, + const MeshVS_BuilderPriority& thePriority) + : MeshVS_PrsBuilder (theParentMesh, theFlags, theDataSource, theId, thePriority) +{} + +//======================================================================= +// function : Build +// purpose : +//======================================================================= +void MeshVS_LODBuilder::Build (const Handle(Prs3d_Presentation)& theBasePrs, + const TColStd_PackedMapOfInteger& theIDs, + TColStd_PackedMapOfInteger& /*theIDsToExclude*/, + const Standard_Boolean theIsElement, + const Standard_Integer theDisplayMode) const +{ + if (myParentMesh == NULL) + return; + + //if (!theIsElement) + //{ + // Standard_Boolean hasSelectFlag = ((aDispMode & MeshVS_DMF_SelectionPrs) != 0); + // Standard_Boolean hasHilightFlag = ((aDispMode & MeshVS_DMF_HilightPrs) != 0); + + // Standard_Real aCoordsBuf[3]; + // TColStd_Array1OfReal aCoords (*aCoordsBuf, 1, 3); + // Standard_Integer aNodesNb; + // MeshVS_EntityType aType; + + // TColStd_PackedMapOfInteger anIDs; + // anIDs.Assign (myNodeIdxs); + // if (!hasSelectFlag && !hasHilightFlag) + // { + // // subtract the hidden nodes and ids to exclude (to minimize allocated memory) + // Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = aMesh->GetHiddenNodes(); + // if (!aHiddenNodes.IsNull()) + // anIDs.Subtract (aHiddenNodes->Map()); + // } + + // Standard_Integer aSize = anIDs.Extent(); + // if (aSize > 0) + // { + // Handle(Graphic3d_ArrayOfPoints) aNodePoints = new Graphic3d_ArrayOfPoints (aSize); + // Standard_Integer aPntsNb = 0; + // for (TColStd_MapIteratorOfPackedMapOfInteger aNodeIdxsIter (myNodeIdxs); aNodeIdxsIter.More(); aNodeIdxsIter.Next()) + // { + // const Standard_Integer aKey = aNodeIdxsIter.Key(); + // if (GetGeom (aKey, Standard_False, aCoords, aNodesNb, aType)) + // { + // aPntsNb++; + // aNodePoints->AddVertex (aCoords(1), aCoords(2), aCoords(3)); + // } + // } + + // if (aPntsNb > 0) + // { + // Handle(Graphic3d_LOD) aNewLod = Prs3d_Root::NewLOD (aMainPrs); + // Handle(Graphic3d_Group) aLODGroup = aNewLod->NewGroup(); + // aLODGroup->AddPrimitiveArray (aNodePoints); + // } + // return; + // } + //} + if (theIsElement) + { + Standard_Integer aMaxNodesNb; + + Handle(MeshVS_MeshPrsBuilder) aBuilder = Handle(MeshVS_MeshPrsBuilder)::DownCast (myParentMesh->GetBuilder (1)); + if (aBuilder.IsNull()) + return; + Handle(MeshVS_Drawer) aDrawer = aBuilder->GetDrawer(); + if (aDrawer.IsNull() || + !aDrawer->GetInteger (MeshVS_DA_MaxFaceNodes, aMaxNodesNb) || + aMaxNodesNb <= 0) + return; + + //----------- extract useful display mode flags ---------- + Standard_Integer aDispStatus = (theDisplayMode & aBuilder->GetFlags()); + if ((aDispStatus & MeshVS_DMF_DeformedMask) != 0) + { + aDispStatus /= MeshVS_DMF_DeformedPrsWireFrame; + // This transformation turns deformed mesh flags to real display modes + } + aDispStatus &= MeshVS_DMF_OCCMask; + //-------------------------------------------------------- + + Standard_Real aShrinkCoef; + aDrawer->GetDouble (MeshVS_DA_ShrinkCoeff, aShrinkCoef); + + const Standard_Boolean isWireframe = theDisplayMode == MeshVS_DMF_WireFrame; + Standard_Boolean isShading = theDisplayMode == MeshVS_DMF_Shading; + Standard_Boolean isShrink = theDisplayMode == MeshVS_DMF_Shrink; + const Standard_Boolean hasHilightFlag = (aDispStatus & MeshVS_DMF_HilightPrs) != 0; + const Standard_Boolean hasSelFlag =(aDispStatus & MeshVS_DMF_SelectionPrs) != 0; + Standard_Boolean isMeshSmoothShading = Standard_False; + Standard_Boolean isMeshReflect, isMeshAllowOverlap, isReflect; + + aDrawer->GetBoolean (MeshVS_DA_Reflection, isMeshReflect); + aDrawer->GetBoolean (MeshVS_DA_IsAllowOverlapped, isMeshAllowOverlap); + isReflect = isMeshReflect && !hasHilightFlag; + aDrawer->GetBoolean (MeshVS_DA_SmoothShading, isMeshSmoothShading); + + // display mode for highlighted prs of groups + isShrink = isShrink && !hasHilightFlag; + isShading = isShading || hasHilightFlag; + + Graphic3d_MaterialAspect aMatAspect; + aDrawer->GetMaterial (MeshVS_DA_FrontMaterial, aMatAspect); + if (!isReflect) + { + aMatAspect.SetReflectionModeOff(Graphic3d_TOR_AMBIENT); + aMatAspect.SetReflectionModeOff(Graphic3d_TOR_DIFFUSE); + aMatAspect.SetReflectionModeOff(Graphic3d_TOR_SPECULAR); + aMatAspect.SetReflectionModeOff(Graphic3d_TOR_EMISSION); + } + Handle(Graphic3d_AspectFillArea3d ) aFill = MeshVS_Tool::CreateAspectFillArea3d (aDrawer, aMatAspect); + Handle(Graphic3d_AspectLine3d ) aBeam = MeshVS_Tool::CreateAspectLine3d (aDrawer); + + const Standard_Boolean isOverlapControl = + !isMeshAllowOverlap && (isWireframe || isShading) && !hasSelFlag; + + // subtract the hidden elements and ids to exclude (to minimize allocated memory) + TColStd_PackedMapOfInteger anIDs; + anIDs.Assign (theIDs); + Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems(); + if (!aHiddenElems.IsNull()) + anIDs.Subtract (aHiddenElems->Map()); + + Handle(MeshVS_HArray1OfSequenceOfInteger) aTopo; + + Standard_Boolean toShowEdges = Standard_True; + aDrawer->GetBoolean (MeshVS_DA_ShowEdges, toShowEdges); + + toShowEdges = isWireframe || toShowEdges; + + Standard_Integer* aNodesBuf = (Standard_Integer*)alloca (aMaxNodesNb * sizeof (Standard_Integer)); + Standard_Real* aCoordsBuf = (Standard_Real*)alloca (3 * aMaxNodesNb * sizeof (Standard_Real)); + + TColStd_Array1OfInteger aNodes (*aNodesBuf, 1, aMaxNodesNb); + TColStd_Array1OfReal aCoords (*aCoordsBuf, 1, 3 * aMaxNodesNb); + + Standard_Integer aNbFacePrimitives = 0; + Standard_Integer aNbVolmPrimitives = 0; + Standard_Integer aNbEdgePrimitives = 0; + Standard_Integer aNbLinkPrimitives = 0; + + MeshVS_EntityType aType; + + TColStd_MapIteratorOfPackedMapOfInteger anIdxIter (anIDs); + for (anIdxIter.Reset(); anIdxIter.More(); anIdxIter.Next()) + { + Standard_Integer aNbNodes = 0; + + if (!DataSource()->GetGeom (anIdxIter.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if (aType == MeshVS_ET_Volume) + { + if (DataSource()->Get3DGeom (anIdxIter.Key(), aNbNodes, aTopo)) + { + for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value(aFaceIdx); + + if (toShowEdges) // add edge segments + { + aNbEdgePrimitives += aFaceNodes.Length(); + } + + if (isShading || isShrink) // add volumetric cell triangles + { + if (!hasSelFlag) + aNbVolmPrimitives += aFaceNodes.Length() - 2; + } + } + } + } + else if (aType == MeshVS_ET_Link) + { + if (toShowEdges) + { + aNbLinkPrimitives += 1; // add link segment + } + } + else if (aType == MeshVS_ET_Face) + { + if (toShowEdges) + { + aNbEdgePrimitives += aNbNodes; // add edge segments + } + + if (!isOverlapControl || isShading) + { + if ((isShading || isShrink) && !hasSelFlag) + { + aNbFacePrimitives += aNbNodes - 2; // add face triangles + } + } + } + } + + // Here we do not use indices arrays because they are not effective for some mesh + // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D + // cell rendering (normal interpolation is not always applicable - flat shading), + // elemental coloring (color interpolation is impossible) + Handle(Graphic3d_ArrayOfTriangles) aVolmTriangles = + new Graphic3d_ArrayOfTriangles (aNbVolmPrimitives * 3, 0, isReflect); + Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = + new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0, isReflect); + + Handle(Graphic3d_ArrayOfSegments) aLinkSegments; + Handle(Graphic3d_ArrayOfSegments) aEdgeSegments; + + if (toShowEdges) + { + aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2); + aEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2); + } + + TColStd_PackedMapOfInteger aCustomElements; + + MeshVS_MapOfTwoNodes aLinkNodes; + + Quantity_Color anOldEdgeColor; + Quantity_Color anEdgeColor; + Quantity_Color anIntColor; + Aspect_InteriorStyle anIntType; + Aspect_TypeOfLine aLine; + Standard_Real aWidth; + + aFill->Values (anIntType, anIntColor, anEdgeColor, aLine, aWidth); + + // Forbid drawings of edges which overlap with some links + if (toShowEdges && isOverlapControl) + { + for (anIdxIter.Reset(); anIdxIter.More(); anIdxIter.Next()) + { + if (DataSource()->GetGeomType (anIdxIter.Key(), Standard_True, aType) && aType == MeshVS_ET_Link) + { + Standard_Integer aNbNodes; + + if (DataSource()->GetNodesByElement (anIdxIter.Key(), aNodes, aNbNodes) && aNbNodes == 2) + { + aLinkNodes.Add (MeshVS_TwoNodes (aNodes(1), aNodes(2))); + } + } + } + } + + NCollection_Map aSegmentMap; + + for (anIdxIter.Reset(); anIdxIter.More(); anIdxIter.Next()) + { + const Standard_Integer aKey = anIdxIter.Key(); + + Standard_Integer NbNodes; + if (!DataSource()->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) + continue; + + if (!DataSource()->GetNodesByElement (aKey, aNodes, NbNodes)) + continue; + + switch (aType) + { + case MeshVS_ET_Volume: + { + if (DataSource()->Get3DGeom (aKey, NbNodes, aTopo)) + { + // Add wire-frame presentation (draw edges for shading mode as well) + if (toShowEdges) + { + aBuilder->AddVolumePrs (aTopo, aCoords, NbNodes, + aEdgeSegments, isReflect, + isShrink, hasSelFlag, + aShrinkCoef); + } + + // Add shading presentation + if ((isShading || isShrink) && !hasSelFlag) + { + aBuilder->AddVolumePrs (aTopo, aCoords, NbNodes, + aVolmTriangles, isReflect, + isShrink, hasSelFlag, + aShrinkCoef); + } + } + } + break; + + case MeshVS_ET_Link: + { + if (toShowEdges) + { + aBuilder->AddLinkPrs (aCoords, aLinkSegments, isShrink || hasSelFlag, aShrinkCoef); + } + } + break; + + case MeshVS_ET_Face: + { + if (toShowEdges && isOverlapControl) + { + Standard_Integer Last = 0; + + MeshVS_TwoNodes aTwoNodes (aNodes(1)); + + for (Standard_Integer i = 1; i <= NbNodes; ++i) + { + if (i > 1) + aTwoNodes.First = aTwoNodes.Second; + + aTwoNodes.Second = (i < NbNodes) ? aNodes (i + 1) : aNodes (1); + + if (aLinkNodes.Contains (aTwoNodes)) + { + for (Standard_Integer aNodeIdx = Last + 1; aNodeIdx < i; ++aNodeIdx) + { + const Standard_Integer aNextIdx = aNodeIdx + 1; + + aEdgeSegments->AddVertex ( + aCoords (3 * aNodeIdx - 2), aCoords (3 * aNodeIdx - 1), aCoords (3 * aNodeIdx)); + aEdgeSegments->AddVertex( + aCoords (3 * aNextIdx - 2), aCoords (3 * aNextIdx - 1), aCoords (3 * aNextIdx)); + } + + Last = i; + } + } + + if (NbNodes - Last > 0) + { + for (Standard_Integer aNodeIdx = Last; aNodeIdx < NbNodes; ++aNodeIdx) + { + const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes; + + const MeshVS_NodePair aSegment (aNodes (aNodeIdx + 1), aNodes (aNextIdx + 1)); + + if (!aSegmentMap.Contains (aSegment)) + { + aEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1), + aCoords (3 * aNodeIdx + 2), + aCoords (3 * aNodeIdx + 3)); + + aEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1), + aCoords (3 * aNextIdx + 2), + aCoords (3 * aNextIdx + 3)); + + aSegmentMap.Add (aSegment); + } + } + } + } + + if (!isOverlapControl || isShading) + { + if (!isOverlapControl && toShowEdges) + { + aBuilder->AddFaceWirePrs (aCoords, NbNodes, aEdgeSegments, isShrink || hasSelFlag, aShrinkCoef); + } + + if ((isShading || isShrink) && !hasSelFlag) + { + aBuilder->AddFaceSolidPrs (DataSource(), aKey, aCoords, NbNodes, aMaxNodesNb, aFaceTriangles, isReflect, + isShrink || hasSelFlag, aShrinkCoef, isMeshSmoothShading); + } + } + } + break; + + default: + aCustomElements.Add (aKey); + } + } + + if (isShrink) + { + anOldEdgeColor = anEdgeColor; + aFill->SetEdgeColor (Quantity_NOC_BLACK); + } + + Standard_Boolean isSupressBackFaces = Standard_False; + if (!aDrawer.IsNull()) + { + aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, isSupressBackFaces); + } + drawArrays (theBasePrs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles, + !toShowEdges, hasSelFlag, isSupressBackFaces, aFill, aBeam); + } +} + +//================================================================ +// Function : drawArrays +// Purpose : +//================================================================ +void MeshVS_LODBuilder::drawArrays (const Handle(Prs3d_Presentation)& theBasePrs, + const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons, + const Handle(Graphic3d_ArrayOfPrimitives)& theLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad, + const Standard_Boolean theIsPolygonsEdgesOff, + const Standard_Boolean theIsSelected, + const Standard_Boolean theIsSupressBackFaces, + const Handle(Graphic3d_AspectFillArea3d)& theFillAsp, + const Handle(Graphic3d_AspectLine3d)& theLineAsp) const +{ + if (theFillAsp.IsNull()) + return; + + Standard_Boolean isFacePolygons = (!thePolygons.IsNull() && thePolygons->ItemNumber() > 0), + isVolumePolygons = (!theVolumesInShad.IsNull() && theVolumesInShad->ItemNumber() > 0), + isPolygons = isFacePolygons || isVolumePolygons, + isPolylines = (!theLines.IsNull() && theLines->ItemNumber() > 0), + isLinkPolylines = (!theLinkLines.IsNull() && theLinkLines->ItemNumber() > 0); + + Aspect_InteriorStyle aStyle; + Quantity_Color anIntColor, aBackColor, anEdgeColor; + Aspect_TypeOfLine aType; + Standard_Real aWidth; + + Handle(Graphic3d_LOD) aNewLod = theBasePrs->NewLOD(); + theFillAsp->Values (aStyle, anIntColor, aBackColor, anEdgeColor, aType, aWidth); + + if (isPolygons && theFillAsp->FrontMaterial().Transparency() < 0.01) + { + Handle (Graphic3d_Group) aGroup = aNewLod->NewGroup (theBasePrs); + + theFillAsp->SetEdgeOff(); + + if (anIntColor != aBackColor) + theFillAsp->SetDistinguishOn(); + else + theFillAsp->SetDistinguishOff(); + + aGroup->SetClosed (theIsSupressBackFaces); + Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*(theFillAsp.operator->())); + if (theIsSupressBackFaces) + { + aFillAsp->SuppressBackFace(); + } + aGroup->SetPrimitivesAspect (aFillAsp); + + if (isFacePolygons) + { + aGroup->AddPrimitiveArray (thePolygons); + } + + if (isVolumePolygons) + { + aGroup->AddPrimitiveArray (theVolumesInShad); + } + } + + if (isPolylines && !theIsPolygonsEdgesOff) + { + Handle (Graphic3d_Group) aLGroup = aNewLod->NewGroup (theBasePrs); + + theFillAsp->SetEdgeOff(); + if (theIsSelected) + aLGroup->SetPrimitivesAspect (theLineAsp); + else + { + aLGroup->SetPrimitivesAspect (theFillAsp); + aLGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (anEdgeColor, Aspect_TOL_SOLID, aWidth)); + } + aLGroup->AddPrimitiveArray (theLines); + theFillAsp->SetEdgeOn(); + } + + if (isLinkPolylines) + { + Handle (Graphic3d_Group) aBeamGroup = aNewLod->NewGroup (theBasePrs); + + theFillAsp->SetEdgeOff(); + if (!theIsSelected) + aBeamGroup->SetPrimitivesAspect (theFillAsp); + aBeamGroup->SetPrimitivesAspect (theLineAsp); + aBeamGroup->AddPrimitiveArray (theLinkLines); + theFillAsp->SetEdgeOn(); + } + + if (isPolygons && theFillAsp->FrontMaterial().Transparency() >= 0.01) + { + Handle (Graphic3d_Group) aGroup = aNewLod->NewGroup (theBasePrs); + + theFillAsp->SetEdgeOff(); + + if (anIntColor != aBackColor) + theFillAsp->SetDistinguishOn(); + else + theFillAsp->SetDistinguishOff(); + + aGroup->SetClosed (theIsSupressBackFaces); + Handle(Graphic3d_AspectFillArea3d) aFillAsp = new Graphic3d_AspectFillArea3d (*(theFillAsp.operator->())); + if (theIsSupressBackFaces) + { + aFillAsp->SuppressBackFace(); + } + aGroup->SetPrimitivesAspect (aFillAsp); + + if (isFacePolygons) + { + aGroup->AddPrimitiveArray (thePolygons); + } + + if (isVolumePolygons) + { + aGroup->AddPrimitiveArray (theVolumesInShad); + } + } +} diff --git a/src/MeshVS/MeshVS_LODBuilder.hxx b/src/MeshVS/MeshVS_LODBuilder.hxx new file mode 100644 index 0000000000..4639b1bf9f --- /dev/null +++ b/src/MeshVS/MeshVS_LODBuilder.hxx @@ -0,0 +1,66 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 _MeshVS_LODBuilder_Header +#define _MeshVS_LODBuilder_Header + +#include +#include +#include + +class MeshVS_LODBuilder : public MeshVS_PrsBuilder +{ +public: + + //! Creates builder with certain display mode flags, data source, ID and priority + Standard_EXPORT MeshVS_LODBuilder (const Handle(MeshVS_Mesh)& theParentMesh, + const MeshVS_DisplayModeFlags& theFlags = MeshVS_DMF_OCCMask, + const Handle(MeshVS_LODDataSource)& theDataSource = NULL, + const Standard_Integer theId = -1, + const MeshVS_BuilderPriority& thePriority = MeshVS_BP_Mesh); + + Standard_EXPORT virtual ~MeshVS_LODBuilder() {}; + + //! Builds presentation of certain type of data. + //! Prs is presentation object which this method constructs. + //! IDs is set of numeric identificators forming object appearance. + //! IDsToExclude is set of IDs to exclude from processing. If some entity + //! has been excluded, it is not processed by other builders. + //! IsElement indicates, IDs is identificators of nodes or elements. + //! DisplayMode is numeric constant describing display mode (see MeshVS_DisplayModeFlags.hxx) + Standard_EXPORT virtual void Build (const Handle(Prs3d_Presentation)& theBasePrs, + const TColStd_PackedMapOfInteger& theIDs, + TColStd_PackedMapOfInteger& theIDsToExclude, + const Standard_Boolean theIsElement, + const Standard_Integer theDisplayMode) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (MeshVS_LODBuilder, MeshVS_PrsBuilder) + +protected: + void drawArrays (const Handle(Prs3d_Presentation)& theBasePrs, + const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons, + const Handle(Graphic3d_ArrayOfPrimitives)& theLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad, + const Standard_Boolean theIsPolygonsEdgesOff, + const Standard_Boolean theIsSelected, + const Standard_Boolean theIsSupressBackFaces, + const Handle(Graphic3d_AspectFillArea3d)& theFillAsp, + const Handle(Graphic3d_AspectLine3d)& theLineAsp) const; +}; + +DEFINE_STANDARD_HANDLE (MeshVS_LODBuilder, MeshVS_PrsBuilder) + +#endif // _MeshVS_LODBuilder_Header diff --git a/src/MeshVS/MeshVS_LODDataSource.cxx b/src/MeshVS/MeshVS_LODDataSource.cxx new file mode 100644 index 0000000000..46ddb0830f --- /dev/null +++ b/src/MeshVS/MeshVS_LODDataSource.cxx @@ -0,0 +1,179 @@ +// Created on: 2015-10-23 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT (MeshVS_LODDataSource, MeshVS_DataSource) + +//======================================================================= +// function : MeshVS_LODDataSource +// purpose : +//======================================================================= +MeshVS_LODDataSource::MeshVS_LODDataSource (const Handle(StlMesh_Mesh)& theMesh) + : myTriangles (1, theMesh->Triangles().Length()), + myNodes (1, theMesh->Vertices().Length()) +{ + if (theMesh.IsNull()) + return; + + const TColgp_SequenceOfXYZ& aVerts = theMesh->Vertices(); + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aVerts.Length(); ++aNodeIdx) + { + myNodeIdxs.Add (aNodeIdx); + myNodes.ChangeValue (aNodeIdx) = aVerts (aNodeIdx); + } + + const StlMesh_SequenceOfMeshTriangle& aTriangles = theMesh->Triangles(); + for (Standard_Integer aTrgIdx = 1; aTrgIdx <= aTriangles.Length(); ++aTrgIdx) + { + myTriangleIdxs.Add (aTrgIdx); + const Handle(StlMesh_MeshTriangle)& aTriangle = aTriangles.Value (aTrgIdx); + Standard_Integer aNodeIdxs[3]; + Standard_Real aNormalX, aNormalY, aNormalZ; + aTriangle->GetVertexAndOrientation (aNodeIdxs[0], aNodeIdxs[1], aNodeIdxs[2], aNormalX, aNormalY, aNormalZ); + myTriangles.ChangeValue (aTrgIdx) = Poly_Triangle (aNodeIdxs[0], aNodeIdxs[1], aNodeIdxs[2]); + } +} + +//======================================================================= +// function : GetGeom +// purpose : Returns full info about the entity according to the index and type of element given +//======================================================================= +Standard_Boolean MeshVS_LODDataSource::GetGeom (const Standard_Integer theId, + const Standard_Boolean theIsElement, + TColStd_Array1OfReal& theCoords, + Standard_Integer& theNodesNb, + MeshVS_EntityType& theEntityType) const +{ + if (theId < 1) + return Standard_False; + + if (theIsElement) + { + if (theId > myTriangleIdxs.Extent() || theCoords.Length() < 9) + return Standard_False; + + Standard_Integer aNode1, aNode2, aNode3; + myTriangles.Value (theId).Get (aNode1, aNode2, aNode3); + gp_Pnt aPnts[3] = { myNodes.Value (aNode1), + myNodes.Value (aNode2), + myNodes.Value (aNode3) }; + for (Standard_Integer aPntIdx = 0, anIdx = 1; aPntIdx < 3; ++aPntIdx) + { + for (Standard_Integer aCoordIdx = 0; aCoordIdx < 3; aCoordIdx++) + { + theCoords (anIdx++) = aPnts[aPntIdx].XYZ().GetData()[aCoordIdx]; + } + } + + theNodesNb = 3; + theEntityType = MeshVS_ET_Face; + + return Standard_True; + } + else + { + if (theId > myNodeIdxs.Extent() || theCoords.Length() < 3) + return Standard_False; + + const gp_Pnt& aNode = myNodes.Value (theId); + theCoords (1) = aNode.X(); + theCoords (2) = aNode.Y(); + theCoords (3) = aNode.Z(); + + theNodesNb = 1; + theEntityType = MeshVS_ET_Node; + + return Standard_True; + } +} + +//======================================================================= +// function : GetGeomType +// purpose : Returns type of geometry according to the index and type of element given +//======================================================================= +Standard_Boolean MeshVS_LODDataSource::GetGeomType (const Standard_Integer /*theId*/, + const Standard_Boolean theIsElement, + MeshVS_EntityType& theEntityType) const +{ + theEntityType = theIsElement ? MeshVS_ET_Face : MeshVS_ET_Node; + return Standard_True; +} + +//======================================================================= +// function : GetAddr +// purpose : +//======================================================================= +Standard_Address MeshVS_LODDataSource::GetAddr (const Standard_Integer /*theId*/, + const Standard_Boolean /*theIsElement*/) const +{ + return NULL; +} + +//======================================================================= +// function : GetNodesByElement +// purpose : Returns nodes forming a triangle with id theId +//======================================================================= +Standard_Boolean MeshVS_LODDataSource::GetNodesByElement (const Standard_Integer theId, + TColStd_Array1OfInteger& theNodeIds, + Standard_Integer& theNodesNb) const +{ + if (theId < 1 || theId > myTriangleIdxs.Extent() || theNodeIds.Length() < 3) + return Standard_False; + + const Standard_Integer aLowerIdx = theNodeIds.Lower(); + myTriangles.Value (theId).Get (theNodeIds.ChangeValue (aLowerIdx), + theNodeIds.ChangeValue (aLowerIdx + 1), + theNodeIds.ChangeValue (aLowerIdx + 2)); + theNodesNb = 3; + return Standard_True; +} + +//======================================================================= +// function : GetAllNodes +// purpose : This method makes storing usless map excusable +//======================================================================= +const TColStd_PackedMapOfInteger& MeshVS_LODDataSource::GetAllNodes() const +{ + return myNodeIdxs; +} + +//======================================================================= +// function : GetAllElements +// purpose : This method makes storing usless map excusable +//======================================================================= +const TColStd_PackedMapOfInteger& MeshVS_LODDataSource::GetAllElements() const +{ + return myTriangleIdxs; +} diff --git a/src/MeshVS/MeshVS_LODDataSource.hxx b/src/MeshVS/MeshVS_LODDataSource.hxx new file mode 100644 index 0000000000..a3deb7967f --- /dev/null +++ b/src/MeshVS/MeshVS_LODDataSource.hxx @@ -0,0 +1,93 @@ +// Created on: 2015-10-23 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 _MeshVS_LODDataSource_Header +#define _MeshVS_LODDataSource_Header + +#include +#include +#include +#include +#include + +//! TODO: VPA: think how to avoid copying mesh data. Now it is done for returning useless maps +//! in GetAllElements() and GetAllNodes() because they must return const links. Moreover, +//! copying data allows to avoid cases when indexation in Poly_Triangluation inner +//! arrays starts from arbitrary numbers (if it is really possible). +class MeshVS_LODDataSource : public MeshVS_DataSource +{ +public: + + Standard_EXPORT MeshVS_LODDataSource (const Handle(StlMesh_Mesh)& theMesh); + + Standard_EXPORT virtual ~MeshVS_LODDataSource() {}; + + //! Returns geometry information about node or element + //! ID is the numerical identificator of node or element + //! IsElement indicates this ID describe node ( if Standard_False ) or element ( if Standard_True ) + //! Coords is an array of co-ordinates of node(s). + //! For node it is only 3 numbers: X, Y, Z in the strict order + //! For element it is 3*n numbers, where n is number of this element vertices + //! The order is strict also: X1, Y1, Z1, X2,...., where Xi, Yi, Zi are co-ordinates of vertices + //! NbNodes is number of nodes. It is recommended this parameter to be set to 1 for node. + //! Type is type of node or element (from enumeration). It is recommended this parameter to be set to + //! MeshVS_ET_Node for node. + Standard_EXPORT virtual Standard_Boolean GetGeom (const Standard_Integer theId, + const Standard_Boolean theIsElement, + TColStd_Array1OfReal& theCoords, + Standard_Integer& theNodesNb, + MeshVS_EntityType& theEntityType) const Standard_OVERRIDE; + + //! This method is similar to GetGeom, but returns only element or node type. + Standard_EXPORT virtual Standard_Boolean GetGeomType (const Standard_Integer theId, + const Standard_Boolean theIsElement, + MeshVS_EntityType& theEntityType) const Standard_OVERRIDE; + + //! This method returns pointer which represents element or node data structure. + //! This address will be saved in MeshVS_MeshEntityOwner, so that you can access to data structure fast + //! by the method Owner(). In the redefined method you can return NULL. + //! ID is the numerical identificator of node or element + //! IsElement indicates this ID describe node ( if Standard_False ) or element ( if Standard_True ) + Standard_EXPORT virtual Standard_Address GetAddr (const Standard_Integer theId, + const Standard_Boolean theIsElement) const Standard_OVERRIDE; + + //! This method returns information about nodes this element consist of. + //! ID is the numerical identificator of element. + //! NodeIDs is the output array of nodes IDs in correct order, + //! the same as coordinates returned by GetGeom(). + //! NbNodes is number of nodes (number of items set in NodeIDs). + //! Returns False if element does not exist + Standard_EXPORT virtual Standard_Boolean GetNodesByElement (const Standard_Integer theId, + TColStd_Array1OfInteger& theNodeIds, + Standard_Integer& theNodesNb) const Standard_OVERRIDE; + + //! This method returns map of all nodes the object consist of. + Standard_EXPORT virtual const TColStd_PackedMapOfInteger& GetAllNodes() const Standard_OVERRIDE; + + //! This method returns map of all elements the object consist of. + Standard_EXPORT virtual const TColStd_PackedMapOfInteger& GetAllElements() const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (MeshVS_LODDataSource, MeshVS_DataSource) + +private: + TColStd_PackedMapOfInteger myNodeIdxs; + TColStd_PackedMapOfInteger myTriangleIdxs; + TColgp_Array1OfPnt myNodes; + Poly_Array1OfTriangle myTriangles; +}; + +DEFINE_STANDARD_HANDLE (MeshVS_LODDataSource, MeshVS_DataSource) + +#endif // _MeshVS_LODDataSource_Header diff --git a/src/MeshVS/MeshVS_Mesh.cxx b/src/MeshVS/MeshVS_Mesh.cxx index c4c7a32ee7..a42705243a 100644 --- a/src/MeshVS/MeshVS_Mesh.cxx +++ b/src/MeshVS/MeshVS_Mesh.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,10 @@ void MeshVS_Mesh::Compute ( const Handle(PrsMgr_PresentationManager3d)& thePrsMg for ( Standard_Integer i=1; i<=len; i++ ) { Handle (MeshVS_PrsBuilder) aCurrent = myBuilders.Value ( i ); + if (!Handle(MeshVS_LODBuilder)::DownCast (aCurrent).IsNull()) + { + continue; + } if ( !aCurrent.IsNull() && aCurrent->TestFlags ( theMode ) ) { aCurrent->SetPresentationManager( thePrsMgr ); @@ -184,6 +189,22 @@ void MeshVS_Mesh::Compute ( const Handle(PrsMgr_PresentationManager3d)& thePrsMg } } + if (myLODDataSources.Size() > 0) + { + for (Standard_Integer aLodBldrIdx = 1; aLodBldrIdx <= myBuilders.Length(); ++aLodBldrIdx) + { + const Handle(MeshVS_LODBuilder) aLodBldr = Handle(MeshVS_LODBuilder)::DownCast (myBuilders.Value (aLodBldrIdx)); + if (aLodBldr.IsNull() || !aLodBldr->TestFlags (theMode)) + continue; + + const TColStd_PackedMapOfInteger aVertIdxs = aLodBldr->GetDataSource()->GetAllNodes(); + const TColStd_PackedMapOfInteger aTrgIdxs = aLodBldr->GetDataSource()->GetAllElements(); + if (HasNodes) + aLodBldr->Build (thePresentation, aVertIdxs, aNodesToExclude, Standard_False, theMode); + if (HasElements) + aLodBldr->Build (thePresentation, aTrgIdxs, aElemsToExclude, Standard_True, theMode); + } + } if ( ShowComputeTime ) { @@ -871,6 +892,15 @@ void MeshVS_Mesh::SetDataSource( const Handle(MeshVS_DataSource)& theDataSource myDataSource = theDataSource; } +//================================================================ +// Function : AddDataSource +// Purpose : +//================================================================ +void MeshVS_Mesh::AddDataSource (const Handle(MeshVS_DataSource)& theDataSource) +{ + myLODDataSources.Append (theDataSource); +} + //================================================================ // Function : HilightSelected // Purpose : diff --git a/src/MeshVS/MeshVS_Mesh.hxx b/src/MeshVS/MeshVS_Mesh.hxx index e726125457..6cbf7e6aef 100644 --- a/src/MeshVS/MeshVS_Mesh.hxx +++ b/src/MeshVS/MeshVS_Mesh.hxx @@ -127,7 +127,10 @@ public: //! Sets default builders' data source Standard_EXPORT void SetDataSource (const Handle(MeshVS_DataSource)& aDataSource); - + + //! Adds data source to define LOD + Standard_EXPORT void AddDataSource (const Handle(MeshVS_DataSource)& theDataSource); + //! Returns default builders' drawer Standard_EXPORT Handle(MeshVS_Drawer) GetDrawer() const; @@ -191,7 +194,6 @@ friend class MeshVS_PrsBuilder; protected: - MeshVS_DataMapOfIntegerOwner myNodeOwners; MeshVS_DataMapOfIntegerOwner myElementOwners; MeshVS_DataMapOfIntegerOwner my0DOwners; @@ -205,10 +207,8 @@ protected: Handle(MeshVS_Drawer) myHilightDrawer; Handle(SelectMgr_EntityOwner) myWholeMeshOwner; - private: - MeshVS_SequenceOfPrsBuilder myBuilders; Handle(MeshVS_PrsBuilder) myHilighter; Handle(TColStd_HPackedMapOfInteger) myHiddenElements; @@ -216,14 +216,7 @@ private: Handle(TColStd_HPackedMapOfInteger) mySelectableNodes; Handle(MeshVS_DataSource) myDataSource; MeshVS_MeshSelectionMethod mySelectionMethod; - - + NCollection_Vector myLODDataSources; }; - - - - - - #endif // _MeshVS_Mesh_HeaderFile diff --git a/src/MeshVS/MeshVS_MeshPrsBuilder.cxx b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx index 54a8e66288..c453300e2b 100644 --- a/src/MeshVS/MeshVS_MeshPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx @@ -719,7 +719,8 @@ void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal& // Function : AddFaceSolidPrs // Purpose : //================================================================ -void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer theID, +void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Handle(MeshVS_DataSource)& theDataSource, + const Standard_Integer theID, const TColStd_Array1OfReal& theCoords, const Standard_Integer theNbNodes, const Standard_Integer theMaxNodes, @@ -729,9 +730,7 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer const Standard_Real theShrinkingCoef, const Standard_Boolean theIsSmoothShading) const { - Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource(); - - if (aDataSource.IsNull()) + if (theDataSource.IsNull()) return; Standard_Real aCenterX = 0.0; @@ -754,7 +753,7 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer { for (Standard_Integer aNodeIdx = 1; aNodeIdx <= theNbNodes; ++aNodeIdx) { - if (!aDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ)) + if (!theDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ)) break; aVertexNormals.Append (gp_XYZ (aNormalX, aNormalY, aNormalZ)); @@ -763,7 +762,7 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer if (!theIsSmoothShading || aVertexNormals.Size() != theNbNodes) { - aDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ); + theDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ); } } @@ -816,6 +815,26 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer } } +//================================================================ +// Function : AddFaceSolidPrs +// Purpose : +//================================================================ +void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer theID, + const TColStd_Array1OfReal& theCoords, + const Standard_Integer theNbNodes, + const Standard_Integer theMaxNodes, + const Handle(Graphic3d_ArrayOfTriangles)& theTriangles, + const Standard_Boolean theIsShaded, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkingCoef, + const Standard_Boolean theIsSmoothShading) const +{ + Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource(); + AddFaceSolidPrs (aDataSource, theID, theCoords, theNbNodes, theMaxNodes, theTriangles, + theIsShaded, theIsShrinked, theShrinkingCoef, theIsSmoothShading); +} + + //================================================================ // Function : AddVolumePrs // Purpose : diff --git a/src/MeshVS/MeshVS_MeshPrsBuilder.hxx b/src/MeshVS/MeshVS_MeshPrsBuilder.hxx index acdd26d717..8bcb372f9a 100644 --- a/src/MeshVS/MeshVS_MeshPrsBuilder.hxx +++ b/src/MeshVS/MeshVS_MeshPrsBuilder.hxx @@ -44,64 +44,117 @@ DEFINE_STANDARD_HANDLE(MeshVS_MeshPrsBuilder, MeshVS_PrsBuilder) //! This class provides methods to compute base mesh presentation class MeshVS_MeshPrsBuilder : public MeshVS_PrsBuilder { - public: - //! Creates builder with certain display mode flags, data source, ID and priority - Standard_EXPORT MeshVS_MeshPrsBuilder(const Handle(MeshVS_Mesh)& Parent, const MeshVS_DisplayModeFlags& Flags = MeshVS_DMF_OCCMask, const Handle(MeshVS_DataSource)& DS = 0, const Standard_Integer Id = -1, const MeshVS_BuilderPriority& Priority = MeshVS_BP_Mesh); - + Standard_EXPORT MeshVS_MeshPrsBuilder(const Handle(MeshVS_Mesh)& Parent, + const MeshVS_DisplayModeFlags& Flags = MeshVS_DMF_OCCMask, + const Handle(MeshVS_DataSource)& DS = 0, + const Standard_Integer Id = -1, + const MeshVS_BuilderPriority& Priority = MeshVS_BP_Mesh); + //! Builds base mesh presentation by calling the methods below - Standard_EXPORT virtual void Build (const Handle(Prs3d_Presentation)& Prs, const TColStd_PackedMapOfInteger& IDs, TColStd_PackedMapOfInteger& IDsToExclude, const Standard_Boolean IsElement, const Standard_Integer DisplayMode) const Standard_OVERRIDE; - + Standard_EXPORT virtual void Build (const Handle(Prs3d_Presentation)& Prs, + const TColStd_PackedMapOfInteger& IDs, + TColStd_PackedMapOfInteger& IDsToExclude, + const Standard_Boolean IsElement, + const Standard_Integer DisplayMode) const Standard_OVERRIDE; + //! Builds nodes presentation - Standard_EXPORT virtual void BuildNodes (const Handle(Prs3d_Presentation)& Prs, const TColStd_PackedMapOfInteger& IDs, TColStd_PackedMapOfInteger& IDsToExclude, const Standard_Integer DisplayMode) const; - + Standard_EXPORT virtual void BuildNodes (const Handle(Prs3d_Presentation)& Prs, + const TColStd_PackedMapOfInteger& IDs, + TColStd_PackedMapOfInteger& IDsToExclude, + const Standard_Integer DisplayMode) const; + //! Builds elements presentation - Standard_EXPORT virtual void BuildElements (const Handle(Prs3d_Presentation)& Prs, const TColStd_PackedMapOfInteger& IDs, TColStd_PackedMapOfInteger& IDsToExclude, const Standard_Integer DisplayMode) const; - + Standard_EXPORT virtual void BuildElements (const Handle(Prs3d_Presentation)& Prs, + const TColStd_PackedMapOfInteger& IDs, + TColStd_PackedMapOfInteger& IDsToExclude, + const Standard_Integer DisplayMode) const; + //! Builds presentation of hilighted entity - Standard_EXPORT virtual void BuildHilightPrs (const Handle(Prs3d_Presentation)& Prs, const TColStd_PackedMapOfInteger& IDs, const Standard_Boolean IsElement) const; - + Standard_EXPORT virtual void BuildHilightPrs (const Handle(Prs3d_Presentation)& Prs, + const TColStd_PackedMapOfInteger& IDs, + const Standard_Boolean IsElement) const; + //! Add to array polygons or polylines representing volume - Standard_EXPORT static void AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo, const TColStd_Array1OfReal& Nodes, const Standard_Integer NbNodes, const Handle(Graphic3d_ArrayOfPrimitives)& Array, const Standard_Boolean IsReflected, const Standard_Boolean IsShrinked, const Standard_Boolean IsSelect, const Standard_Real ShrinkCoef); - + Standard_EXPORT static void AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo, + const TColStd_Array1OfReal& Nodes, + const Standard_Integer NbNodes, + const Handle(Graphic3d_ArrayOfPrimitives)& Array, + const Standard_Boolean IsReflected, + const Standard_Boolean IsShrinked, + const Standard_Boolean IsSelect, + const Standard_Real ShrinkCoef); + //! Calculate how many polygons or polylines are necessary to draw passed topology - Standard_EXPORT static void HowManyPrimitives (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo, const Standard_Boolean AsPolygons, const Standard_Boolean IsSelect, const Standard_Integer NbNodes, Standard_Integer& Vertices, Standard_Integer& Bounds); + Standard_EXPORT static void HowManyPrimitives (const Handle(MeshVS_HArray1OfSequenceOfInteger)& Topo, + const Standard_Boolean AsPolygons, + const Standard_Boolean IsSelect, + const Standard_Integer NbNodes, + Standard_Integer& Vertices, + Standard_Integer& Bounds); + //! Add to array of polylines some lines representing link + Standard_EXPORT void AddLinkPrs (const TColStd_Array1OfReal& theCoords, + const Handle(Graphic3d_ArrayOfSegments)& theLines, + const Standard_Boolean IsShrinked, + const Standard_Real ShrinkCoef) const; + //! Add to array of segments representing face's wire + Standard_EXPORT void AddFaceWirePrs (const TColStd_Array1OfReal& theCoords, + const Standard_Integer theNbNodes, + const Handle(Graphic3d_ArrayOfSegments)& theLines, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkingCoef) const; + //! Add to array of polygons a polygon representing face + Standard_EXPORT void AddFaceSolidPrs (const Handle(MeshVS_DataSource)& theDataSource, + const Standard_Integer ID, + const TColStd_Array1OfReal& theCoords, + const Standard_Integer theNbNodes, + const Standard_Integer theMaxNodes, + const Handle(Graphic3d_ArrayOfTriangles)& theTriangles, + const Standard_Boolean theIsReflected, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkCoef, + const Standard_Boolean theIsMeshSmoothShading) const; DEFINE_STANDARD_RTTIEXT(MeshVS_MeshPrsBuilder,MeshVS_PrsBuilder) protected: - - //! Add to array of polylines some lines representing link - Standard_EXPORT void AddLinkPrs (const TColStd_Array1OfReal& theCoords, const Handle(Graphic3d_ArrayOfSegments)& theLines, const Standard_Boolean IsShrinked, const Standard_Real ShrinkCoef) const; - - //! Add to array of segments representing face's wire - Standard_EXPORT void AddFaceWirePrs (const TColStd_Array1OfReal& theCoords, const Standard_Integer theNbNodes, const Handle(Graphic3d_ArrayOfSegments)& theLines, const Standard_Boolean theIsShrinked, const Standard_Real theShrinkingCoef) const; - //! Add to array of polygons a polygon representing face - Standard_EXPORT void AddFaceSolidPrs (const Standard_Integer ID, const TColStd_Array1OfReal& theCoords, const Standard_Integer theNbNodes, const Standard_Integer theMaxNodes, const Handle(Graphic3d_ArrayOfTriangles)& theTriangles, const Standard_Boolean theIsReflected, const Standard_Boolean theIsShrinked, const Standard_Real theShrinkCoef, const Standard_Boolean theIsMeshSmoothShading) const; - + Standard_EXPORT void AddFaceSolidPrs (const Standard_Integer ID, + const TColStd_Array1OfReal& theCoords, + const Standard_Integer theNbNodes, + const Standard_Integer theMaxNodes, + const Handle(Graphic3d_ArrayOfTriangles)& theTriangles, + const Standard_Boolean theIsReflected, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkCoef, + const Standard_Boolean theIsMeshSmoothShading) const; + //! Draw array of polygons and polylines in the certain order according to transparency - Standard_EXPORT void DrawArrays (const Handle(Prs3d_Presentation)& Prs, const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons, const Handle(Graphic3d_ArrayOfPrimitives)& theLines, const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines, const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad, const Standard_Boolean IsPolygonsEdgesOff, const Standard_Boolean IsSelected, const Handle(Graphic3d_AspectFillArea3d)& theFillAsp, const Handle(Graphic3d_AspectLine3d)& theLineAsp) const; - + Standard_EXPORT void DrawArrays (const Handle(Prs3d_Presentation)& Prs, + const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons, + const Handle(Graphic3d_ArrayOfPrimitives)& theLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad, + const Standard_Boolean IsPolygonsEdgesOff, + const Standard_Boolean IsSelected, + const Handle(Graphic3d_AspectFillArea3d)& theFillAsp, + const Handle(Graphic3d_AspectLine3d)& theLineAsp) const; + //! Default calculation of center of face or link. This method if useful for shrink mode presentation //! theCoords is array of nodes co-ordinates in the strict order X1, Y1, Z1, X2... //! NbNodes is number of nodes an element consist of //! xG, yG, zG are co-ordinates of center whose will be returned - Standard_EXPORT static void CalculateCenter (const TColStd_Array1OfReal& theCoords, const Standard_Integer NbNodes, Standard_Real& xG, Standard_Real& yG, Standard_Real& zG); - - - -private: - - - - + Standard_EXPORT static void CalculateCenter (const TColStd_Array1OfReal& theCoords, + const Standard_Integer NbNodes, + Standard_Real& xG, + Standard_Real& yG, + Standard_Real& zG); }; diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 67af2f8496..b21623bd73 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -110,6 +110,10 @@ OpenGl_GlCore44.hxx OpenGl_LayerList.cxx OpenGl_LayerList.hxx OpenGl_LayerFilter.hxx +OpenGl_LOD.hxx +OpenGl_LOD.cxx +OpenGl_LODManager.hxx +OpenGl_LODManager.cxx OpenGl_GraphicDriver.cxx OpenGl_GraphicDriver.hxx OpenGl_IndexBuffer.cxx diff --git a/src/OpenGl/OpenGl_LOD.cxx b/src/OpenGl/OpenGl_LOD.cxx new file mode 100644 index 0000000000..1e7aea9164 --- /dev/null +++ b/src/OpenGl/OpenGl_LOD.cxx @@ -0,0 +1,29 @@ +// Created on: 2015-10-29 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 + +IMPLEMENT_STANDARD_RTTIEXT (OpenGl_LOD, Graphic3d_LOD) + +//======================================================================= +// function : NewGroup +// purpose : +//======================================================================= +Handle(Graphic3d_Group) OpenGl_LOD::NewGroup (const Handle(Graphic3d_Structure)& theParentStruct) +{ + Handle(OpenGl_Group) aGroup = new OpenGl_Group (theParentStruct); + myGroups.Append (aGroup); + return aGroup; +} diff --git a/src/OpenGl/OpenGl_LOD.hxx b/src/OpenGl/OpenGl_LOD.hxx new file mode 100644 index 0000000000..fccafd4a70 --- /dev/null +++ b/src/OpenGl/OpenGl_LOD.hxx @@ -0,0 +1,38 @@ +// Created on: 2015-10-29 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LOD_Header +#define _OpenGl_LOD_Header + +#include +#include +#include +#include + +class OpenGl_LOD : public Graphic3d_LOD +{ +public: + + Standard_EXPORT OpenGl_LOD() : Graphic3d_LOD () {}; + Standard_EXPORT ~OpenGl_LOD() {}; + + Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theParentStruct) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (OpenGl_LOD, Graphic3d_LOD) +}; + +DEFINE_STANDARD_HANDLE (OpenGl_LOD, Graphic3d_LOD) + +#endif // _OpenGl_LOD_Header diff --git a/src/OpenGl/OpenGl_LODManager.cxx b/src/OpenGl/OpenGl_LODManager.cxx new file mode 100644 index 0000000000..27003856b6 --- /dev/null +++ b/src/OpenGl/OpenGl_LODManager.cxx @@ -0,0 +1,77 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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 + +IMPLEMENT_STANDARD_RTTIEXT (OpenGl_LODManager, Graphic3d_LODManager) + +namespace +{ + // Comparison operator for sorting LODs + class CompareLODS + { + public: + + CompareLODS (const NCollection_Vector& theLODs) + : myLODs (theLODs) {} + + Standard_Boolean operator() (const Handle(Graphic3d_LOD)& theLeft, const Handle(Graphic3d_LOD)& theRight) const + { + return theLeft->GetRange() < theRight->GetRange(); + } + + private: + void operator = (const CompareLODS&); + + private: + const NCollection_Vector& myLODs; + }; +} + +//======================================================================= +// function : Creation +// purpose : +//======================================================================= +OpenGl_LODManager::OpenGl_LODManager (const Handle(Graphic3d_Structure)& theParentStructure) + : Graphic3d_LODManager (theParentStructure) +{ + Standard_ASSERT_RAISE (!theParentStructure.IsNull(), + "Parent structure of LOD manager is null!"); +} + +//======================================================================= +// function : AddNewLOD +// purpose : +//======================================================================= +Handle(Graphic3d_LOD) OpenGl_LODManager::AddNewLOD() +{ + Handle(Graphic3d_LOD) aNewLOD = new OpenGl_LOD(); + myLODs.Append (aNewLOD); + sortLODs(); + return aNewLOD; +} + +//======================================================================= +// function : sortLODs +// purpose : +//======================================================================= +void OpenGl_LODManager::sortLODs() +{ + std::sort (myLODs.begin(), myLODs.end(), CompareLODS (myLODs)); +} diff --git a/src/OpenGl/OpenGl_LODManager.hxx b/src/OpenGl/OpenGl_LODManager.hxx new file mode 100644 index 0000000000..5072e29f8f --- /dev/null +++ b/src/OpenGl/OpenGl_LODManager.hxx @@ -0,0 +1,38 @@ +// Created on: 2015-11-25 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-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_LODManager_Header +#define _OpenGl_LODManager_Header + +#include + +class OpenGl_LODManager : public Graphic3d_LODManager +{ +public: + Standard_EXPORT OpenGl_LODManager (const Handle(Graphic3d_Structure)& theParentStructure); + + Standard_EXPORT virtual ~OpenGl_LODManager() {}; + + Standard_EXPORT virtual Handle(Graphic3d_LOD) AddNewLOD() Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (OpenGl_LODManager, Graphic3d_LODManager) + +protected: + Standard_EXPORT virtual void sortLODs() Standard_OVERRIDE; +}; + +DEFINE_STANDARD_HANDLE (OpenGl_LODManager, Graphic3d_LODManager) + +#endif // _OpenGl_LODManager_Header diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 31d7a4de41..f766b0f3e5 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -26,6 +28,7 @@ #include #include +#include IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure) @@ -423,6 +426,19 @@ Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Struc return aGroup; } +// ======================================================================= +// function : NewLOD +// purpose : +// ======================================================================= +Handle(Graphic3d_LOD) OpenGl_Structure::NewLOD (const Handle(Graphic3d_Structure)& theStruct) +{ + if (myLODManager.IsNull()) + { + myLODManager = new OpenGl_LODManager (theStruct); + } + return myLODManager->AddNewLOD(); +} + // ======================================================================= // function : RemoveGroup // purpose : @@ -503,7 +519,8 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp myInstancedStructure->renderGeometry (theWorkspace, theHasClosed); } - for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) + const Graphic3d_SequenceOfGroup& aGroups = DrawGroups(); + for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next()) { theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed(); aGroupIter.Value()->Render (theWorkspace); @@ -542,6 +559,9 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con return; } + if (!myLODManager.IsNull() && myLODManager->GetCurrentLODIdx (theWorkspace->View()->Camera()) == -1) + return; + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); // Render named status @@ -762,3 +782,38 @@ Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3 { return new OpenGl_StructureShadow (theManager, this); } + +//======================================================================= +//function : SetDetailLevelRange +//purpose : +//======================================================================= +void OpenGl_Structure::SetDetailLevelRange (const Standard_Integer theIdOfLOD, + const Standard_Real theFrom, + const Standard_Real theTo) +{ + Standard_ASSERT_RAISE (theFrom < theTo, + "The upper boundary of the interval must be greater than lower one!"); + + if (theIdOfLOD < 0 || theIdOfLOD > myLODManager->NbOfDetailLevels()) + return; + + myLODManager->SetRange (theIdOfLOD, theFrom, theTo); +} + +//======================================================================= +//function : DrawGroups +//purpose : +//======================================================================= +const Graphic3d_SequenceOfGroup& OpenGl_Structure::DrawGroups() const +{ + return myLODManager.IsNull() ? myGroups : myLODManager->GetCurrentGroups(); +} + +//======================================================================= +//function : NbDetailLevels +//purpose : +//======================================================================= +Standard_Integer OpenGl_Structure::NbDetailLevels() const +{ + return myLODManager->NbOfDetailLevels(); +} diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index 6a4f2157c5..53ada6de98 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -35,8 +35,10 @@ class OpenGl_Structure; class OpenGl_GraphicDriver; +class OpenGl_LOD; typedef NCollection_List OpenGl_ListOfStructure; +typedef NCollection_Vector OpenGl_VectorOfLODs; //! Implementation of low-level graphic structure. class OpenGl_Structure : public Graphic3d_CStructure @@ -98,16 +100,20 @@ public: //! Create new group within this structure Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theStruct) Standard_OVERRIDE; + //! Create new LOD within this structure + Standard_EXPORT virtual Handle(Graphic3d_LOD) NewLOD (const Handle(Graphic3d_Structure)& theStruct) Standard_OVERRIDE; + //! Remove group from this structure Standard_EXPORT virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) Standard_OVERRIDE; + Standard_EXPORT virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD, + const Standard_Real theFrom, + const Standard_Real theTo) Standard_OVERRIDE; + public: //! @return graphic groups - virtual const Graphic3d_SequenceOfGroup& DrawGroups() const - { - return myGroups; - } + virtual const Graphic3d_SequenceOfGroup& DrawGroups() const; //! Access graphic driver OpenGl_GraphicDriver* GlDriver() const @@ -197,6 +203,8 @@ public: //! Is the structure ray-tracable (contains ray-tracable elements)? Standard_Boolean IsRaytracable() const; + Standard_EXPORT virtual Standard_Integer NbDetailLevels() const Standard_OVERRIDE; + protected: Standard_EXPORT virtual ~OpenGl_Structure(); diff --git a/src/Prs3d/Prs3d_Root.hxx b/src/Prs3d/Prs3d_Root.hxx index 011a8c7400..c7c5d05c2e 100644 --- a/src/Prs3d/Prs3d_Root.hxx +++ b/src/Prs3d/Prs3d_Root.hxx @@ -22,6 +22,7 @@ #include class Graphic3d_Group; +class Graphic3d_LOD; class Prs3d_Presentation; @@ -44,22 +45,6 @@ public: //! objects in the display. //! A group also contains the attributes whose ranges are limited to the primitives in it. Standard_EXPORT static Handle(Graphic3d_Group) NewGroup (const Handle(Prs3d_Presentation)& Prs3d); - - - - -protected: - - - - - -private: - - - - - }; diff --git a/src/TKMeshVS/EXTERNLIB b/src/TKMeshVS/EXTERNLIB index c9eebc5d24..3455499568 100644 --- a/src/TKMeshVS/EXTERNLIB +++ b/src/TKMeshVS/EXTERNLIB @@ -4,3 +4,4 @@ TKService TKernel TKG3d TKG2d +TKSTL diff --git a/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx b/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx index b0ac14a3b4..237c8f5744 100644 --- a/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx +++ b/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName, const Handle(AIS_InteractiveObject)& theAISObj, Standard_Boolean theReplaceIfExists = Standard_True); +extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(); static Standard_Integer writestl (Draw_Interpretor& di, Standard_Integer argc, const char** argv) @@ -1202,6 +1204,358 @@ static Standard_Integer meshinfo(Draw_Interpretor& di, return 0; } +#include +#include +#include +#include +#include +#include +#include +#include +//======================================================================= +//function : VGenLods +//purpose : Generates sequence of LODs for the shape given +//======================================================================= +static int MeshGenLods (Draw_Interpretor& theDI, + Standard_Integer theArgNum, + const char** theArgs) +{ + if (theArgNum < 3) + { + std::cout << "Error! Wrong number of arguments. See usage:\n"; + theDI.PrintHelp (theArgs[0]); + return 1; + } + + Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext(); + if (aCtx.IsNull()) + { + std::cout << "Error! No opened viewer." << std::endl; + return 1; + } + + Standard_CString aShapeName = theArgs[1]; + const TopoDS_Shape aShape = DBRep::Get (aShapeName); + if (aShape.IsNull()) + { + std::cout << "Error! No shape with the name " << aShapeName << "." << std::endl; + return 1; + } + const Standard_Integer aLodsNb = Draw::Atoi (theArgs[2]); + if (aLodsNb <= 0) + { + std::cout << "Error! Incorrect amount of LODs passed: " << aLodsNb << "." << std::endl; + std::cout << "Must be greater than zero." << std::endl; + return 1; + } + Standard_Boolean toPrintInfo = Standard_False; + TCollection_AsciiString aSavePath = ""; + Handle(MeshVS_Mesh) aMesh = NULL; + if (theArgNum > 3) + { + for (Standard_Integer anArgIdx = 3; anArgIdx < theArgNum; ++anArgIdx) + { + TCollection_AsciiString anArg (theArgs[anArgIdx]); + anArg.LowerCase(); + if (anArg == "-debug") + { + toPrintInfo = Standard_True; + } + else if (anArg == "-mesh") + { + aMesh = Handle(MeshVS_Mesh)::DownCast (GetMapOfAIS().Find2 (theArgs[++anArgIdx])); + } + else if (anArg == "-save") + { + aSavePath = TCollection_AsciiString (theArgs[++anArgIdx]); + } + } + } + + // Determine max deflection of a shape + Handle(Poly_Triangulation) aFaceTrg; + TopLoc_Location aFaceLoc; + Standard_Real aMaxDefl = 0.0; + for (TopExp_Explorer anExplorer (aShape, TopAbs_FACE); anExplorer.More(); anExplorer.Next()) + { + TopoDS_Face aCurFace = TopoDS::Face (anExplorer.Current()); + aFaceTrg = BRep_Tool::Triangulation (aCurFace, aFaceLoc); + if (!aFaceTrg.IsNull()) + { + if (aFaceTrg->Deflection() > aMaxDefl) + aMaxDefl = aFaceTrg->Deflection(); + } + } + + BRepTools::Clean (aShape); + BRepMesh_FastDiscret::Parameters aMeshParams; + aMeshParams.Deflection = aMaxDefl; + aMeshParams.Angle = 0.5; + aMeshParams.Relative = Standard_False; + aMeshParams.InParallel = Standard_False; + aMeshParams.MinSize = Precision::Confusion(); + aMeshParams.InternalVerticesMode = Standard_True; + aMeshParams.ControlSurfaceDeflection = Standard_True; + aMeshParams.AdaptiveMin = Standard_False; + BRepMesh_IncrementalMesh aBaseMesher (aShape, aMeshParams); + aBaseMesher.Perform(); + ViewerTest_AutoUpdater anAutoUpd (aCtx, ViewerTest::CurrentView()); + + + // compute the shape for each LOD + TopoDS_Shape* aLodShapes = new TopoDS_Shape[aLodsNb]; + BRepBuilderAPI_Copy aMainCopyAlgo; + aMainCopyAlgo.Perform (aShape, Standard_True, Standard_True); + aLodShapes[0] = aMainCopyAlgo.Shape(); + Standard_Real aDeflDecrFactor = aMaxDefl / aLodsNb; + for (Standard_Integer aLodIdx = 1; aLodIdx < aLodsNb; ++aLodIdx) + { + BRepBuilderAPI_Copy aCopyAlgo; + aCopyAlgo.Perform (aShape, Standard_True, Standard_True); + aLodShapes[aLodIdx] = aCopyAlgo.Shape(); + BRepTools::Clean (aLodShapes[aLodIdx]); + BRepMesh_FastDiscret::Parameters aParams; + aParams.Deflection = aMaxDefl - aLodIdx * aDeflDecrFactor; + aParams.Angle = 0.5; + aParams.Relative = Standard_False; + aParams.InParallel = Standard_False; + aParams.MinSize = Precision::Confusion(); + aParams.InternalVerticesMode = Standard_True; + aParams.ControlSurfaceDeflection = Standard_True; + aParams.AdaptiveMin = Standard_False; + BRepMesh_IncrementalMesh aMesher (aLodShapes[aLodIdx], aParams); + aMesher.Perform(); + if (toPrintInfo) + { + Standard_Integer aStatus = aMesher.GetStatusFlags(); + std::cout << "LOD #" << aLodIdx << " meshing status: "; + if (!aStatus) + std::cout << " OK" << std::endl; + else + { + for (Standard_Integer aBitIdx = 0; aBitIdx < 4; ++aBitIdx) + { + if ((aStatus >> aBitIdx) & 1) + { + switch (aBitIdx + 1) + { + case 1: + std::cout << " OpenWire "; + break; + case 2: + std::cout << " SelfIntersectingWire "; + break; + case 3: + std::cout << " Failure "; + break; + case 4: + std::cout << " ReMesh "; + break; + } + } + } + std::cout << std::endl; + } + } + } + + if (toPrintInfo) + { + std::cout << std::endl; + for (Standard_Integer aLodIdx = 0; aLodIdx < aLodsNb; ++aLodIdx) + { + std::cout << "LOD #" << aLodIdx + 1 << " info:" << std::endl; + if (aLodShapes[aLodIdx].IsNull()) + { + std::cout << "The shape is null!" << std::endl; + } + + Handle(Poly_Triangulation) aCurTrg; + TopLoc_Location aCurLoc; + Standard_Real aDefl = 0.0; + Standard_Integer aTrgsNb = 0, aNodesNb = 0; + for (TopExp_Explorer aShapeExp (aLodShapes[aLodIdx], TopAbs_FACE); aShapeExp.More(); aShapeExp.Next()) + { + TopoDS_Face aCurFace = TopoDS::Face (aShapeExp.Current()); + aCurTrg = BRep_Tool::Triangulation (aCurFace, aCurLoc); + if (!aCurTrg.IsNull()) + { + aTrgsNb += aCurTrg->NbTriangles(); + aNodesNb += aCurTrg->NbNodes(); + if (aCurTrg->Deflection() > aDefl) + aDefl = aCurTrg->Deflection(); + } + } + std::cout << "deflection : " << aDefl << std::endl; + std::cout << "triangles nb: " << aTrgsNb << std::endl; + std::cout << "nodes nb : " << aNodesNb << std::endl; + std::cout << std::endl; + } + } + + if (!aMesh.IsNull() && aSavePath != "") + { + if (aSavePath.Value (aSavePath.Length()) != '/') + { + aSavePath = aSavePath + "/"; + } + aSavePath = aSavePath + aShapeName + "_LOD"; + for (Standard_Integer aLodIdx = 0; aLodIdx < aLodsNb; ++aLodIdx) + { + StlAPI_Writer aWriter; + aWriter.ASCIIMode() = Standard_False; + TCollection_AsciiString aPath = aSavePath + aLodIdx + ".stl"; + StlAPI_ErrorStatus aStatus = aWriter.Write (aLodShapes[aLodIdx], aPath.ToCString()); + switch (aStatus) + { + case StlAPI_CannotOpenFile: + std::cout << "Error! Cannot create/open a file with the name: " << aPath << std::endl; + break; + case StlAPI_StatusOK: + default: + std::cout << "LOD" << aLodIdx << " was written sucessfully to the file " << aPath << std::endl; + } + } + } + + return 0; +} + +#include +static int MeshLod (Draw_Interpretor& theDI, + Standard_Integer theArgNum, + const char** theArgs) +{ + struct DetailLevelData + { + public: + DetailLevelData() + : myMesh (NULL), + myFrom (-DBL_MAX), + myTo (DBL_MAX) {} + + public: + Handle(StlMesh_Mesh) myMesh; + Standard_Real myFrom; + Standard_Real myTo; + }; + + if (theArgNum < 3) + { + std::cout << "Error! Wrong number of arguments. See usage:\n"; + theDI.PrintHelp (theArgs[0]); + return 1; + } + + Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext(); + if (aCtx.IsNull()) + { + std::cout << "Error! No opened viewer." << std::endl; + return 1; + } + + Standard_CString aShapeName = theArgs[1]; + if (GetMapOfAIS().IsBound2 (aShapeName)) + { + std::cout << "Error! The context already has an interactive object with the name " << aShapeName << "." << std::endl; + return 1; + } + const TCollection_AsciiString aPathToLODInfo = Draw::Atoi (theArgs[2]); + if (aPathToLODInfo == "") + { + std::cout << "Error! Path to LOD info must not be empty!" << std::endl; + return 1; + } + + std::ifstream aLODInfoFile (theArgs[2]); + NCollection_List myLODDataList; + Handle(StlMesh_Mesh) aLargestMesh; + for (std::string aLODInfoStr; getline (aLODInfoFile, aLODInfoStr);) + { + DetailLevelData aData; + std::istringstream aStream (aLODInfoStr); + std::vector aTokens; + std::copy (std::istream_iterator (aStream), + std::istream_iterator(), + std::back_inserter (aTokens)); + for (Standard_Integer aTokenIdx = 0; aTokenIdx < aTokens.size(); ++aTokenIdx) + { + if (aTokens[aTokenIdx] == "-path") + { + OSD_Path aFile (aTokens[++aTokenIdx].c_str()); + Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1); + Handle(StlMesh_Mesh) aSTLMesh = RWStl::ReadFile (aFile, aProgress); + if (aSTLMesh.IsNull()) + { + std::cout << "Error! Can not read LOD located at the path: " << aTokens[aTokenIdx] << std::endl; + return 1; + } + aData.myMesh = aSTLMesh; + if (aLargestMesh.IsNull() || aSTLMesh->Triangles().Length() > aLargestMesh->Triangles().Length()) + { + aLargestMesh = aSTLMesh; + } + } + else if (aTokens[aTokenIdx] == "-from") + { + aData.myFrom = Draw::Atof (aTokens[++aTokenIdx].c_str()); + } + else if (aTokens[aTokenIdx] == "-to") + { + aData.myTo = Draw::Atof (aTokens[++aTokenIdx].c_str()); + } + } + myLODDataList.Append (aData); + } + + if (aLargestMesh.IsNull()) + { + std::cout << "Error! No meshes found in lod info file!" << std::endl; + return 1; + } + + Handle(MeshVS_Mesh) anOriginMesh = new MeshVS_Mesh(); + Handle(XSDRAWSTLVRML_DataSource) anOriginDataSource = new XSDRAWSTLVRML_DataSource (aLargestMesh); + anOriginMesh->SetDataSource (anOriginDataSource); + Handle(MeshVS_MeshPrsBuilder) anOriginBuilder = new MeshVS_MeshPrsBuilder (anOriginMesh.operator->()); + anOriginMesh->AddBuilder (anOriginBuilder, Standard_True); + anOriginMesh->GetDrawer()->SetColor (MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW); + + for (NCollection_List::Iterator aLodDataIter (myLODDataList); aLodDataIter.More(); aLodDataIter.Next()) + { + Handle(MeshVS_LODDataSource) aLod = new MeshVS_LODDataSource (aLodDataIter.Value().myMesh); + anOriginMesh->AddDataSource (aLod); + Handle(MeshVS_LODBuilder) aLODBuilder = new MeshVS_LODBuilder (anOriginMesh.operator->()); + aLODBuilder->SetDataSource (aLod); + aLODBuilder->SetDrawer (anOriginBuilder->GetDrawer()); + anOriginMesh->AddBuilder (aLODBuilder); + } + + // Hide all nodes by default + Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger(); + Standard_Integer aLen = aLargestMesh->Vertices().Length(); + for (Standard_Integer anIndex = 1; anIndex <= aLen; ++anIndex) + aNodes->ChangeMap().Add (anIndex); + anOriginMesh->SetHiddenNodes (aNodes); + anOriginMesh->SetSelectableNodes (aNodes); + + VDisplayAISObject (aShapeName, anOriginMesh); + aCtx->Deactivate (anOriginMesh); + + Standard_Integer aLodIdx = 0; + for (NCollection_List::Iterator aLodDataIter (myLODDataList); aLodDataIter.More(); aLodDataIter.Next()) + { + anOriginMesh->Presentation()->SetDetailLevelRange (aLodIdx, aLodDataIter.Value().myFrom, aLodDataIter.Value().myTo); + } + + Draw::Set (aShapeName, new XSDRAWSTLVRML_DrawableMesh (anOriginMesh)); + Handle(V3d_View) aView = ViewerTest::CurrentView(); + if (!aView.IsNull()) + aView->FitAll(); + + return 0; +} + //----------------------------------------------------------------------------- void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands) @@ -1232,6 +1586,24 @@ void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands) theCommands.Add ("meshdeform", "display deformed mesh", __FILE__, meshdeform, g ); theCommands.Add ("mesh_edge_width", "set width of edges", __FILE__, mesh_edge_width, g ); theCommands.Add ("meshinfo", "displays the number of nodes and triangles", __FILE__, meshinfo, g ); + theCommands.Add ("meshgenlods", + "meshgenlods shapeName lodsNb [-save pathToFolder] [-mesh meshName] [-debug]" + "\n\t\t: Generates sequence of LODs for the shape with shapeName in amount of lodsNb." + "\n\t\t: lodsNb means the exact amount of physical LODs to generate, e.g. the main" + "\n\t\t: object's presentation is not considered as a separate level of detail here." + "\n\t\t: [-debug] enables printing of meshing status and each LOD's info.", + __FILE__, MeshGenLods, g); + theCommands.Add ("meshlod", + "meshlod shapeName pathToFileWithLodInfo" + "\n\t\t: Creates an object with the name shapeName that has LODs described in file stored at" + "\n\t\t: pathToFileWithLodInfo. Each string in the file is a full description of LOD. It must" + "\n\t\t: be filled using the following form:" + "\n\t\t: -path pathToLOD [-from fromRange] [-to toRange], where" + "\n\t\t: pathToLOD is a path to STL file with LOD mesh, fromRange and toRange define a depth" + "\n\t\t: range where the LOD will be visible. Each of range parameters is optional, but in this" + "\n\t\t: case, it will be equal to positive and negative max double correspondingly." + "\n\t\t: It is assumed that ranges are non-overlapping segments of the real axis." + __FILE__, MeshLod, g); } //============================================================================== diff --git a/tests/bugs/vis/bug26812 b/tests/bugs/vis/bug26812 new file mode 100644 index 0000000000..cb93e21b9d --- /dev/null +++ b/tests/bugs/vis/bug26812 @@ -0,0 +1,24 @@ +set aPathToData "" +set aTmpFolder "" + +pload ALL +vinit +meshlod m $aTmpFolder/lod_data.txt + +########################################################################## +# to generate brep file for LODs generaion, it is requred to use +# iges shapes. the following sequence of commands creates both +# stl and brep files for the iges shape +########################################################################## +igesbrep $aPathToData/iges/bearing.iges res * +vdisplay res +# write created brep to file +save res $aTmpFolder/bearing.brep +trinfo res +# copy maximal deflection value, then re-mesh the shape with proper +# deflection +tclean res +incmesh res $maxDeflection +# save corresponding stl with the same triangulation as will be used +# for generaion of LODs +writestl res $aTmpFolder/bearing.stl -- 2.39.5