From: vpa Date: Fri, 6 Nov 2015 04:15:03 +0000 (+0300) Subject: Draft implementation of LOD API in OCCT: X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=a370cc65373fe367f5c4fdf75c3af546228031cb;p=occt-copy.git Draft implementation of LOD API in OCCT: - implemented interfaces for LOD at OpenGl, Graphic3d and MeshVS levels; - simple mechanism of LOD switching was added to OpenGl_Structure::Render method; - distance to COG metric is temporarily used; - added commands meshgenlod and meshlod to generate LODs for mesh and its topological representation and bind them to its OpenGl structures. --- diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index f373a1a9f4..ae7e43c780 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -77,6 +77,8 @@ Graphic3d_InitialisationError.hxx Graphic3d_LevelOfTextureAnisotropy.hxx Graphic3d_ListIteratorOfListOfShortReal.hxx Graphic3d_ListOfShortReal.hxx +Graphic3d_LOD.hxx +Graphic3d_LOD.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 126835e07e..b9cadc5376 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -28,6 +28,7 @@ class Graphic3d_GraphicDriver; class Graphic3d_StructureManager; +class Graphic3d_LOD; //! Low-level graphic structure interface class Graphic3d_CStructure : public Standard_Transient @@ -112,9 +113,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 GetDetailLevelsNb() const = 0; + + virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo) = 0; + public: int Id; diff --git a/src/Graphic3d/Graphic3d_LOD.cxx b/src/Graphic3d/Graphic3d_LOD.cxx new file mode 100644 index 0000000000..1871d17c6c --- /dev/null +++ b/src/Graphic3d/Graphic3d_LOD.cxx @@ -0,0 +1,68 @@ +// 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 + +//======================================================================= +// function : Destructor +// purpose : +//======================================================================= +Graphic3d_LOD::~Graphic3d_LOD() +{ + myGroups.Clear(); + myParent.Nullify(); +} + +//======================================================================= +// function : SetParent +// purpose : +//======================================================================= +void Graphic3d_LOD::SetParent (const Handle(Graphic3d_Structure)& theParent) +{ + myParent = theParent; +} + +//======================================================================= +// function : SetRange +// purpose : +//======================================================================= +void Graphic3d_LOD::SetRange (const Standard_Real /*theFrom*/, const Standard_Real /*theTo*/) +{ + return; +} + +//======================================================================= +// function : NewGroup +// purpose : +//======================================================================= +Handle(Graphic3d_Group) Graphic3d_LOD::NewGroup() +{ + return NULL; +} + +//======================================================================= +// function : ComputeMetrics +// purpose : +//======================================================================= +Standard_Real Graphic3d_LOD::ComputeMetrics (const Handle(Graphic3d_Camera)& theCamera) const +{ + if (myParent.IsNull()) + return std::numeric_limits::max(); + + Graphic3d_BndBox4f aBndBox = myParent->CStructure()->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_LOD.hxx b/src/Graphic3d/Graphic3d_LOD.hxx new file mode 100644 index 0000000000..3882cf3240 --- /dev/null +++ b/src/Graphic3d/Graphic3d_LOD.hxx @@ -0,0 +1,47 @@ +// 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 + +class Graphic3d_LOD : public Standard_Transient +{ +public: + Standard_EXPORT Graphic3d_LOD() {}; + Standard_EXPORT virtual ~Graphic3d_LOD(); + + Standard_EXPORT virtual void SetRange (const Standard_Real theFrom, const Standard_Real theTo); + Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup(); + + Standard_EXPORT Standard_Real ComputeMetrics (const Handle(Graphic3d_Camera)& theCamera) const; + Standard_EXPORT void SetParent (const Handle(Graphic3d_Structure)& theParent); + + DEFINE_STANDARD_RTTI (Graphic3d_LOD, Standard_Transient) + +protected: + Graphic3d_SequenceOfGroup myGroups; + Handle(Graphic3d_Structure) myParent; +}; + +DEFINE_STANDARD_HANDLE (Graphic3d_LOD, Standard_Transient) + +#endif // _Graphic3d_LOD_Header diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx index 655499a29b..05e481a6cc 100644 --- a/src/Graphic3d/Graphic3d_Structure.cxx +++ b/src/Graphic3d/Graphic3d_Structure.cxx @@ -1743,6 +1743,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 : GetDetailLevelsNb +//purpose : +//============================================================================= +Standard_Integer Graphic3d_Structure::GetDetailLevelsNb() const +{ + return myCStructure->GetDetailLevelsNb(); +} + +//============================================================================= +//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 b86f0078f0..088126f4f2 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. @@ -492,6 +497,10 @@ public: //! Returns the low-level structure const Handle(Graphic3d_CStructure)& CStructure() const; + Standard_EXPORT Standard_Integer GetDetailLevelsNb() 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..7654ee848b 100755 --- a/src/MeshVS/FILES +++ b/src/MeshVS/FILES @@ -41,6 +41,8 @@ MeshVS_ElementalColorPrsBuilder.cxx MeshVS_ElementalColorPrsBuilder.hxx MeshVS_EntityType.hxx MeshVS_HArray1OfSequenceOfInteger.hxx +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 354479165e..74c18beec9 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_RTTI(MeshVS_DataSource,MMgt_TShared) - -protected: - - - - -private: - - - - }; - - - - - - #endif // _MeshVS_DataSource_HeaderFile diff --git a/src/MeshVS/MeshVS_LODDataSource.cxx b/src/MeshVS/MeshVS_LODDataSource.cxx new file mode 100644 index 0000000000..36bb712124 --- /dev/null +++ b/src/MeshVS/MeshVS_LODDataSource.cxx @@ -0,0 +1,684 @@ +// 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 + +//======================================================================= +// 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; +} + +//======================================================================= +// function : ComputePrs +// purpose : +//======================================================================= +void MeshVS_LODDataSource::ComputePrs (const Handle(AIS_InteractiveObject) theMesh) +{ + Handle(MeshVS_Mesh) aMesh = Handle(MeshVS_Mesh)::DownCast (theMesh); + if (aMesh.IsNull()) + return; + + Standard_Boolean hasNodes = !myNodeIdxs.IsEmpty(); + Standard_Boolean hasTrgs = !myTriangleIdxs.IsEmpty(); + Handle(Prs3d_Presentation) aMainPrs = theMesh->Presentation(); + const Standard_Integer aDispMode = theMesh->DisplayMode(); + + //if (hasNodes) + //{ + // 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 (hasTrgs) + { + Standard_Integer aMaxNodesNb; + + Handle(MeshVS_MeshPrsBuilder) aBuilder = Handle(MeshVS_MeshPrsBuilder)::DownCast (aMesh->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 = (aDispMode & 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 = aDispMode == MeshVS_DMF_WireFrame; + Standard_Boolean isShading = aDispMode == MeshVS_DMF_Shading; + Standard_Boolean isShrink = aDispMode == 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 (myTriangleIdxs); + Handle(TColStd_HPackedMapOfInteger) aHiddenElems = aMesh->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 (!GetGeom (anIdxIter.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if (aType == MeshVS_ET_Volume) + { + if (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 (GetGeomType (anIdxIter.Key(), Standard_True, aType) && aType == MeshVS_ET_Link) + { + Standard_Integer aNbNodes; + + if (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 (!GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) + continue; + + if (!GetNodesByElement (aKey, aNodes, NbNodes)) + continue; + + switch (aType) + { + case MeshVS_ET_Volume: + { + if (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 (this, 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 (aMainPrs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles, + !toShowEdges, hasSelFlag, isSupressBackFaces, aFill, aBeam); + } +} + +//================================================================ +// Function : DrawArrays +// Purpose : +//================================================================ +void MeshVS_LODDataSource::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 = Prs3d_Root::NewLOD (theBasePrs); + theFillAsp->Values (aStyle, anIntColor, aBackColor, anEdgeColor, aType, aWidth); + + if (isPolygons && theFillAsp->FrontMaterial().Transparency() < 0.01) + { + Handle (Graphic3d_Group) aGroup = aNewLod->NewGroup(); + + 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(); + + 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(); + + 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(); + + 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_LODDataSource.hxx b/src/MeshVS/MeshVS_LODDataSource.hxx new file mode 100644 index 0000000000..f3282c40d7 --- /dev/null +++ b/src/MeshVS/MeshVS_LODDataSource.hxx @@ -0,0 +1,107 @@ +// 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; + + Standard_EXPORT void ComputePrs (const Handle(AIS_InteractiveObject) theMesh); + + DEFINE_STANDARD_RTTI (MeshVS_LODDataSource, MeshVS_DataSource) + +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; + +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_MeshPrsBuilder.cxx b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx index bd7a373dd3..2903368f69 100644 --- a/src/MeshVS/MeshVS_MeshPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx @@ -717,7 +717,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, @@ -727,9 +728,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; @@ -752,7 +751,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)); @@ -761,7 +760,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); } } @@ -814,6 +813,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 7f51737d55..5ed7754dd9 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_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; + //! 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_RTTI(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 650941a09c..f2d843b72a 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -111,6 +111,9 @@ OpenGl_GlCore44.hxx OpenGl_LayerList.cxx OpenGl_LayerList.hxx OpenGl_LayerFilter.hxx +OpenGl_LOD.hxx +OpenGl_LOD.lxx +OpenGl_LOD.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..5016d3086a --- /dev/null +++ b/src/OpenGl/OpenGl_LOD.cxx @@ -0,0 +1,47 @@ +// 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 + +//======================================================================= +// function : Construction +// purpose : +//======================================================================= +OpenGl_LOD::OpenGl_LOD() +: Graphic3d_LOD (), + myRange (-DBL_MAX, DBL_MAX) {} + +//======================================================================= +// function : SetRange +// purpose : +//======================================================================= +void OpenGl_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 = OpenGl_RangeOfLOD (theFrom, theTo); +} + +//======================================================================= +// function : NewGroup +// purpose : +//======================================================================= +Handle(Graphic3d_Group) OpenGl_LOD::NewGroup() +{ + Handle(OpenGl_Group) aGroup = new OpenGl_Group (myParent); + 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..cf410e8b1c --- /dev/null +++ b/src/OpenGl/OpenGl_LOD.hxx @@ -0,0 +1,92 @@ +// 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 + +struct OpenGl_RangeOfLOD +{ +public: + OpenGl_RangeOfLOD (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!"); + + myTo = theTo; + myFrom = theFrom; + } + + Standard_Boolean IsIn (const Standard_Real theVal) const + { + return (myFrom < theVal) && (theVal < myTo); + } + + Standard_Boolean IsLess (const Standard_Real theVal) const + { + return myFrom < theVal; + } + + Standard_Boolean IsGreater (const Standard_Real theVal) const + { + return myTo < theVal; + } + + bool operator < (const OpenGl_RangeOfLOD& theOther) const + { + return myFrom < theOther.myFrom; + } + +private: + Standard_Real myFrom; + Standard_Real myTo; +}; + +class OpenGl_LOD : public Graphic3d_LOD +{ +public: + + Standard_EXPORT OpenGl_LOD(); + Standard_EXPORT ~OpenGl_LOD() {}; + + Standard_EXPORT virtual void SetRange (const Standard_Real theFrom, const Standard_Real theTo) Standard_OVERRIDE; + + inline const OpenGl_RangeOfLOD& GetRange() const + { + return myRange; + } + + Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup() Standard_OVERRIDE; + + const Graphic3d_SequenceOfGroup& DrawGroups() const + { + return myGroups; + } + + DEFINE_STANDARD_RTTI (OpenGl_LOD, Graphic3d_LOD) + +private: + OpenGl_RangeOfLOD myRange; +}; + +DEFINE_STANDARD_HANDLE (OpenGl_LOD, Graphic3d_LOD) + +#include + +#endif // _OpenGl_LOD_Header diff --git a/src/OpenGl/OpenGl_LOD.lxx b/src/OpenGl/OpenGl_LOD.lxx new file mode 100644 index 0000000000..b896d2c7bc --- /dev/null +++ b/src/OpenGl/OpenGl_LOD.lxx @@ -0,0 +1,22 @@ +// 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. + +struct IsLessLOD +{ + inline bool operator() (const Handle(OpenGl_LOD)& theLod1, const Handle(OpenGl_LOD)& theLod2) const + { + return theLod1->GetRange() < theLod2->GetRange(); + } +}; diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 69d2e4dac3..686009e75a 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -127,7 +128,8 @@ OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& th myIsRaytracable (Standard_False), myModificationState (0), myIsCulled (Standard_True), - myIsMirrored (Standard_False) + myIsMirrored (Standard_False), + myCurrentLodId (-1) { // } @@ -431,6 +433,18 @@ 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) +{ + Handle(OpenGl_LOD) aLOD = new OpenGl_LOD(); + aLOD->SetParent (theStruct); + myLODVec.Append (aLOD); + return aLOD; +} + // ======================================================================= // function : RemoveGroup // purpose : @@ -525,6 +539,15 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con return; } + Handle(OpenGl_LOD) aLODToRender = NULL; + if (myLODVec.Size() > 0) + { + findCurrentLOD (theWorkspace); + if (myCurrentLodId == -1) + return; + aLODToRender = myLODVec.Value (myCurrentLodId); + } + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); // Render named status @@ -647,7 +670,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con } // Render groups - const Graphic3d_SequenceOfGroup& aGroups = DrawGroups(); + const Graphic3d_SequenceOfGroup& aGroups = !aLODToRender.IsNull() ? aLODToRender->DrawGroups() : DrawGroups(); for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next()) { aGroupIter.Value()->Render (theWorkspace); @@ -764,3 +787,65 @@ Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3 { return new OpenGl_StructureShadow (theManager, this); } + +//======================================================================= +//function : binSearchLOD +//purpose : +//======================================================================= +Standard_Integer OpenGl_Structure::binSearchLOD (const Standard_Integer theFirst, + const Standard_Integer theLast, + const Standard_Real theMetrics) const +{ + if (theFirst > theLast) + return -1; + else + { + Standard_Integer aMid = (theFirst + theLast) / 2; + + if (myLODVec.Value (aMid)->GetRange().IsIn (theMetrics)) + return aMid; + else + if (myLODVec.Value (aMid)->GetRange().IsLess (theMetrics)) + return binSearchLOD (aMid + 1, theLast, theMetrics); + else + return binSearchLOD (theFirst, aMid - 1, theMetrics); + } +} + +//======================================================================= +//function : findCurrentLOD +//purpose : +//======================================================================= +void OpenGl_Structure::findCurrentLOD (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + Standard_Real aMetric = myLODVec.Value (0)->ComputeMetrics (theWorkspace->View()->Camera()); + std::cout << aMetric << std::endl; + if (myCurrentLodId != -1 && myLODVec.Value (myCurrentLodId)->GetRange().IsIn (aMetric)) + return; + + if (myLODVec.Last()->GetRange().IsGreater (aMetric)) + { + myCurrentLodId = myLODVec.Size() - 1; + return; + } + + myCurrentLodId = binSearchLOD (0, (Standard_Integer)myLODVec.Size() - 1, aMetric); +} + +//======================================================================= +//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 > myLODVec.Size()) + return; + + myLODVec.Value( theIdOfLOD)->SetRange (theFrom, theTo); + std::sort (myLODVec.begin(), myLODVec.end(), IsLessLOD()); +} diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index bca38b091c..78dedba7df 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,9 +100,16 @@ public: //! Create new group within this structure Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theStruct); + //! 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_EXPORT virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD, + const Standard_Real theFrom, + const Standard_Real theTo) Standard_OVERRIDE; + public: //! @return graphic groups @@ -192,6 +201,11 @@ public: //! Is the structure ray-tracable (contains ray-tracable elements)? Standard_Boolean IsRaytracable() const; + Standard_EXPORT virtual Standard_Integer GetDetailLevelsNb() const Standard_OVERRIDE + { + return (Standard_Integer)myLODVec.Size(); + } + protected: Standard_EXPORT virtual ~OpenGl_Structure(); @@ -199,6 +213,10 @@ protected: //! Updates ray-tracable status for structure and its parents. void UpdateStateIfRaytracable (const Standard_Boolean toCheck = Standard_True) const; +private: + void findCurrentLOD (const Handle(OpenGl_Workspace)& theWorkspace) const; + Standard_Integer binSearchLOD (const Standard_Integer theFirst, const Standard_Integer theLast, const Standard_Real theMetrics) const; + protected: OpenGl_Matrix* myTransformation; @@ -219,6 +237,10 @@ protected: Standard_Boolean myIsMirrored; //!< Used to tell OpenGl to interpret polygons in clockwise order. +private: + mutable OpenGl_VectorOfLODs myLODVec; + mutable Standard_Integer myCurrentLodId; + public: DEFINE_STANDARD_RTTI(OpenGl_Structure, Graphic3d_CStructure) // Type definition diff --git a/src/Prs3d/Prs3d_Root.cxx b/src/Prs3d/Prs3d_Root.cxx index 516705011b..a9530394b4 100644 --- a/src/Prs3d/Prs3d_Root.cxx +++ b/src/Prs3d/Prs3d_Root.cxx @@ -25,3 +25,12 @@ Handle (Graphic3d_Group) Prs3d_Root::NewGroup (const Handle (Prs3d_Presentation) { return Prs3d->NewGroup(); } + +//======================================================================= +//function : CreateLOD +//purpose : +//======================================================================= +Handle(Graphic3d_LOD) Prs3d_Root::NewLOD (const Handle (Prs3d_Presentation)& theParentPrs) +{ + return theParentPrs->NewLOD(); +} diff --git a/src/Prs3d/Prs3d_Root.hxx b/src/Prs3d/Prs3d_Root.hxx index 011a8c7400..ed35e2c548 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; @@ -45,21 +46,7 @@ public: //! 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: - - - - - + Standard_EXPORT static Handle(Graphic3d_LOD) NewLOD (const Handle (Prs3d_Presentation)& theParentPrs); }; 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 c5ef90770e..25aabbc931 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,296 @@ 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_IncrementalMesh aBaseMesher; + aBaseMesher.SetShape (aShape); + aBaseMesher.SetDeflection (aMaxDefl); + aBaseMesher.SetRelative (Standard_False); + aBaseMesher.SetAngle (0.5); + aBaseMesher.SetParallel (Standard_False); + aBaseMesher.SetMinSize (Precision::Confusion()); + aBaseMesher.SetInternalVerticesMode (Standard_True); + aBaseMesher.SetControlSurfaceDeflection (Standard_True); + 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_IncrementalMesh aMesher; + aMesher.SetShape (aLodShapes[aLodIdx]); + aMesher.SetDeflection (aMaxDefl - aLodIdx * aDeflDecrFactor); + aMesher.SetRelative (Standard_False); + aMesher.SetAngle (0.5); + aMesher.SetParallel (Standard_False); + aMesher.SetMinSize (Precision::Confusion()); + aMesher.SetInternalVerticesMode (Standard_True); + aMesher.SetControlSurfaceDeflection (Standard_True); + 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; +} + +static int MeshLod (Draw_Interpretor& theDI, + Standard_Integer theArgNum, + const char** theArgs) +{ + if (theArgNum < 6) + { + 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! No interactive object with the name " << aShapeName << "." << std::endl; + return 1; + } + Handle(MeshVS_Mesh) aMesh = Handle(MeshVS_Mesh)::DownCast (GetMapOfAIS().Find2 (aShapeName)); + if (aMesh.IsNull()) + { + std::cout << "Error! No mesh with the name " << aShapeName << "." << std::endl; + return 1; + } + const TCollection_AsciiString aPathToLOD = Draw::Atoi (theArgs[3]); + if (aPathToLOD == "") + { + std::cout << "Error! Path to LOD must not be empty!" << std::endl; + return 1; + } + Standard_Real aFromRange = -DBL_MAX; + Standard_Real aToRange = DBL_MAX; + for (Standard_Integer anArgIdx = 4; anArgIdx < theArgNum; ++anArgIdx) + { + TCollection_AsciiString anArg (theArgs[anArgIdx]); + anArg.LowerCase(); + if (anArg == "-from") + { + aFromRange = Draw::Atof (theArgs[++anArgIdx]); + } + else if (anArg == "-to") + { + aToRange = Draw::Atof (theArgs[++anArgIdx]); + } + } + if (aFromRange > aToRange) + { + std::cout << "Error! From range must be less than to! Current values are:" << std::endl; + std::cout << "from: " << aFromRange << "; to: " << aToRange << std::endl; + return 1; + } + + OSD_Path aFile (theArgs[3]); + 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: " << aPathToLOD << std::endl; + return 1; + } + + Handle(MeshVS_LODDataSource) aLod = new MeshVS_LODDataSource (aSTLMesh); + aLod->ComputePrs (aMesh); + Standard_Integer aIdOfLod = aMesh->Presentation()->GetDetailLevelsNb(); + aMesh->Presentation()->SetDetailLevelRange (aIdOfLod - 1, aFromRange, aToRange); + + return 0; +} + //----------------------------------------------------------------------------- void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands) @@ -1232,6 +1524,17 @@ 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 [-path pathToLOD] [-from rangeFrom] [-to rangeTo]" + "\n\t\t: Adds LOD to the shape with shapeName. It will be visible in range [rangeFrom; rangeTo]." + __FILE__, MeshLod, g); } //============================================================================== diff --git a/tests/bugs/vis/bug26812 b/tests/bugs/vis/bug26812 new file mode 100644 index 0000000000..d9ba0e5469 --- /dev/null +++ b/tests/bugs/vis/bug26812 @@ -0,0 +1,35 @@ +set aPathToData "" +set aTmpFolder "" + +pload ALL +vinit +# restore $aPathToData/occ/fuse.brep f +# vdisplay f +# restore $aTmpFolder/bearing.brep f +meshfromstl m $aTmpFolder/bearing.stl +# restore $aTmpFolder/bearing.brep f +# vdisplay f +# meshfromstl f $aPathToData/stl/bearing.stl +vfit +# meshgenlods f 2 -debug -mesh m -save D:/OCCT-tests/LOD +meshlod m -path $aTmpFolder/f_LOD0.stl -from 0.5 -to 1 +meshlod m -path $aTmpFolder/f_LOD1.stl -from 1 -to 3 + + +########################################################################## +# 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