From 37ac4a67fce594613302fd194186a3bf8bf910d0 Mon Sep 17 00:00:00 2001 From: dbp Date: Thu, 24 Jul 2014 13:21:54 +0400 Subject: [PATCH] 0024926: MeshVS - improve generation of primitive arrays Remove redundant code. Fix GCC compilation warnings. Bug fix in MeshVS_ElementalColorPrsBuilder. --- src/MeshVS/FILES | 1 + .../MeshVS_ElementalColorPrsBuilder.cxx | 358 +++++--- src/MeshVS/MeshVS_MeshPrsBuilder.cdl | 45 +- src/MeshVS/MeshVS_MeshPrsBuilder.cxx | 822 +++++++++++------- src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl | 36 +- src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx | 425 +++++---- src/MeshVS/MeshVS_SymmetricPairHasher.hxx | 23 + src/MeshVS/MeshVS_VectorPrsBuilder.cxx | 110 ++- 8 files changed, 1136 insertions(+), 684 deletions(-) create mode 100644 src/MeshVS/MeshVS_SymmetricPairHasher.hxx diff --git a/src/MeshVS/FILES b/src/MeshVS/FILES index ad727f3c3b..d85be04329 100755 --- a/src/MeshVS/FILES +++ b/src/MeshVS/FILES @@ -7,3 +7,4 @@ MeshVS_TwoColors.hxx MeshVS_TwoColors.cxx MeshVS_TwoNodes.hxx MeshVS_SelectionModeFlags.hxx +MeshVS_SymmetricPairHasher.hxx diff --git a/src/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx b/src/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx index acf3d6b667..5206f9fef0 100644 --- a/src/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -47,7 +49,7 @@ #include #include #include - +#include //================================================================ // Function : Constructor MeshVS_ElementalColorPrsBuilder @@ -210,8 +212,7 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& } Graphic3d_MaterialAspect aMaterial[2]; - Standard_Integer i; - for ( i=0; i<2; i++ ) + for (Standard_Integer i = 0; i < 2; i++) { // OCC20644 "plastic" is most suitable here, as it is "non-physic" // so TelUpdateMaterial() from OpenGl_attri.c uses the interior @@ -257,129 +258,227 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Handle ( Graphic3d_Group ) aGGroup = Prs3d_Root::CurrentGroup ( Prs ); Prs3d_Root::NewGroup ( Prs ); Handle ( Graphic3d_Group ) aLGroup = Prs3d_Root::CurrentGroup ( Prs ); + Prs3d_Root::NewGroup ( Prs ); + Handle ( Graphic3d_Group ) aSGroup = Prs3d_Root::CurrentGroup ( Prs ); + + Standard_Integer aNbFacePrimitives = 0; + Standard_Integer aNbVolmPrimitives = 0; + Standard_Integer aNbEdgePrimitives = 0; + Standard_Integer aNbLinkPrimitives = 0; + + for (it.Reset(); it.More(); it.Next()) + { + Standard_Integer aNbNodes = 0; + + if (!aColIter.Value().Contains (it.Key())) + continue; + + if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if (aType == MeshVS_ET_Volume) + { + if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo)) + { + for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx); - Handle (Graphic3d_ArrayOfPolygons) aPolyGArr = new Graphic3d_ArrayOfPolygons - ( aMaxFaceNodes*aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D, 0, IsReflect ); + if (anEdgeOn) // add edge segments + { + aNbEdgePrimitives += aFaceNodes.Length(); + } + + if (IsReflect) // add volumetric cell triangles + { + aNbVolmPrimitives += aFaceNodes.Length() - 2; + } + } + } + } + else if (aType == MeshVS_ET_Link) + { + if (anEdgeOn) + { + aNbLinkPrimitives += aNbNodes - 1; // add link segments + } + } + else if (aType == MeshVS_ET_Face) + { + if (anEdgeOn) + { + aNbEdgePrimitives += aNbNodes; // add edge segments + } + + 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) aFaceTriangles = new Graphic3d_ArrayOfTriangles ( + (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, IsReflect ); Standard_Boolean IsPolyG = Standard_False; - Handle (Graphic3d_ArrayOfPolylines) aPolyLArr = new Graphic3d_ArrayOfPolylines - ( 2*aSize, aSize ); + Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2); + Handle (Graphic3d_ArrayOfSegments) aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2); Standard_Boolean IsPolyL = Standard_False; // OCC20644 NOTE: aColIter.Key() color is then scaled by TelUpdateMaterial() in OpenGl_attri.c // using the material reflection coefficients. This affects the visual result. - Handle(Graphic3d_AspectFillArea3d) anAsp = + Handle(Graphic3d_AspectFillArea3d) aFillAspect = new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aColIter.Key(), anEdgeColor, anEdgeType, anEdgeWidth, aMaterial[0], aMaterial[1] ); - Handle(Graphic3d_AspectLine3d) anLAsp = + Handle(Graphic3d_AspectLine3d) aLinkAspect = new Graphic3d_AspectLine3d ( aColIter.Key(), aLineType, aLineWidth ); - anAsp->SetDistinguishOff (); - anAsp->SetInteriorColor ( aColIter.Key() ); + Handle(Graphic3d_AspectLine3d) anEdgeAspect = + new Graphic3d_AspectLine3d ( anEdgeColor, anEdgeType, anEdgeWidth ); + + aFillAspect->SetDistinguishOff (); + aFillAspect->SetInteriorColor ( aColIter.Key() ); if (anEdgeOn) - anAsp->SetEdgeOn(); + aFillAspect->SetEdgeOn(); else - anAsp->SetEdgeOff(); + aFillAspect->SetEdgeOff(); - for( it.Reset(); it.More(); it.Next() ) + for (it.Reset(); it.More(); it.Next()) { Standard_Integer aKey = it.Key(); - if( aColIter.Value().Contains( aKey ) ) + + if (aColIter.Value().Contains (aKey)) { - if ( !aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) ) + if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) continue; - - if( aType == MeshVS_ET_Face ) - { - aPolyGArr->AddBound ( NbNodes ); - if( IsExcludingOn() ) - IDsToExclude.Add( aKey ); - } - else if( aType == MeshVS_ET_Link ) + + if (aType != MeshVS_ET_Face && aType != MeshVS_ET_Link && aType != MeshVS_ET_Volume) { - aPolyLArr->AddBound ( NbNodes ); - if( IsExcludingOn() ) - IDsToExclude.Add( aKey ); + aCustomElements.Add (aKey); + continue; } - else if( aType == MeshVS_ET_Volume ) + + if (IsExcludingOn()) + IDsToExclude.Add (aKey); + + if (aType == MeshVS_ET_Volume) { - if( IsExcludingOn() ) - IDsToExclude.Add( aKey ); - if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) ) + if (!aSource->Get3DGeom (aKey, NbNodes, aTopo)) { - MeshVS_MeshPrsBuilder::AddVolumePrs( aTopo, aCoords, NbNodes, aPolyGArr, IsReflect, Standard_False, Standard_False, 1.0 ); - IsPolyG = Standard_True; - } - else continue; + } + + MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords, + NbNodes, aFaceTriangles, IsReflect, Standard_False, Standard_False, 1.0); + + if (anEdgeOn) + { + MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords, + NbNodes, anEdgeSegments, IsReflect, Standard_False, Standard_False, 1.0); + } + + IsPolyG = Standard_True; } - else + else if (aType == MeshVS_ET_Face) { - aCustomElements.Add( aKey ); - continue; - } + // Preparing normals + Handle(TColStd_HArray1OfReal) aNormals; + Standard_Boolean aHasNormals = IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals); - // Preparing normal(s) to show reflections if requested - Handle(TColStd_HArray1OfReal) aNormals; - Standard_Boolean hasNormals = IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ); + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) + { + for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx) + { + if (IsReflect) + { + aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1), + aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2), + aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3), + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1) : 0.0, + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2) : 0.0, + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3) : 1.0); + } + else + { + aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1), + aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2), + aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3)); + } + } + } - // Adding vertices (with normals if necessary) - for ( i=1; i<=NbNodes; i++ ) - if ( aType == MeshVS_ET_Face ) + if (anEdgeOn) { - if ( IsReflect ) + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) { - hasNormals ? aPolyGArr->AddVertex ( aCoords(3 * i - 2), - aCoords(3 * i - 1), - aCoords(3 * i ), - aNormals->Value(3 * i - 2), - aNormals->Value(3 * i - 1), - aNormals->Value(3 * i ) ) : - aPolyGArr->AddVertex ( aCoords(3 * i - 2), - aCoords(3 * i - 1), - aCoords(3 * i ), - 0., - 0., - 1. ); + const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes; + + anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1), + aCoords (3 * aNodeIdx + 2), + aCoords (3 * aNodeIdx + 3)); + + anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1), + aCoords (3 * aNextIdx + 2), + aCoords (3 * aNextIdx + 3)); } - else - aPolyGArr->AddVertex ( aCoords(3 * i - 2), - aCoords(3 * i - 1), - aCoords(3 * i ) ); - IsPolyG = Standard_True; } - else if ( aType == MeshVS_ET_Link ) + + IsPolyG = Standard_True; + } + else if (aType == MeshVS_ET_Link) + { + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 1; ++aNodeIdx) { - aPolyLArr->AddVertex ( aCoords(3*i-2), aCoords(3*i-1), aCoords(3*i) ); + const Standard_Integer aNextIdx = aNodeIdx + 1; + + aLinkSegments->AddVertex (aCoords (3 * aNodeIdx + 1), + aCoords (3 * aNodeIdx + 2), + aCoords (3 * aNodeIdx + 3)); + + aLinkSegments->AddVertex (aCoords (3 * aNextIdx + 1), + aCoords (3 * aNextIdx + 2), + aCoords (3 * aNextIdx + 3)); + IsPolyL = Standard_True; } + } } } - if ( IsPolyG ) + if (IsPolyG) { - aGGroup->SetPrimitivesAspect ( anAsp ); - aGGroup->AddPrimitiveArray ( aPolyGArr ); + aFillAspect->SetEdgeOff(); + aGGroup->SetPrimitivesAspect (aFillAspect); + aGGroup->AddPrimitiveArray (aFaceTriangles); + + if (anEdgeOn) + { + aFillAspect->SetEdgeOff(); + aSGroup->AddPrimitiveArray (anEdgeSegments); + aSGroup->SetGroupPrimitivesAspect (anEdgeAspect); + } } - if ( IsPolyL ) + if (IsPolyL) { - anAsp->SetEdgeOff(); - aLGroup->SetPrimitivesAspect ( anAsp ); - aLGroup->SetPrimitivesAspect ( anLAsp ); - aLGroup->AddPrimitiveArray ( aPolyLArr ); + aFillAspect->SetEdgeOff(); + aLGroup->SetPrimitivesAspect (aFillAspect); + aLGroup->SetPrimitivesAspect (aLinkAspect); + aLGroup->AddPrimitiveArray (aLinkSegments); if (anEdgeOn) - anAsp->SetEdgeOn(); + aFillAspect->SetEdgeOn(); else - anAsp->SetEdgeOff(); + aFillAspect->SetEdgeOff(); } - if( !aCustomElements.IsEmpty() ) - CustomBuild( Prs, aCustomElements, IDsToExclude, DisplayMode ); + if (!aCustomElements.IsEmpty()) + CustomBuild(Prs, aCustomElements, IDsToExclude, DisplayMode); } Graphic3d_MaterialAspect aMaterial2[2]; - for ( i=0; i<2; i++ ) + for (Standard_Integer i = 0; i < 2; i++) { // OCC20644 "plastic" is most suitable here, as it is "non-physic" // so TelUpdateMaterial() from OpenGl_attri.c uses the interior @@ -422,13 +521,42 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& { Prs3d_Root::NewGroup ( Prs ); Handle ( Graphic3d_Group ) aGroup2 = Prs3d_Root::CurrentGroup ( Prs ); + Prs3d_Root::NewGroup ( Prs ); + Handle ( Graphic3d_Group ) aGroup3 = Prs3d_Root::CurrentGroup ( Prs ); Standard_Integer aSize = aColIter2.Value().Extent(); if ( aSize<=0 ) continue; - Handle (Graphic3d_ArrayOfPolygons) aPolyArr = new Graphic3d_ArrayOfPolygons - ( aMaxFaceNodes*aSize, aSize, 0, IsReflect ); + Standard_Integer aNbFacePrimitives = 0; + Standard_Integer aNbEdgePrimitives = 0; + + for (it.Reset(); it.More(); it.Next()) + { + Standard_Integer aNbNodes = 0; + + if (!aColIter2.Value().Contains (it.Key())) + continue; + + if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if ( aType == MeshVS_ET_Face && aNbNodes > 0 ) + { + if (anEdgeOn) + { + aNbEdgePrimitives += aNbNodes; // add edge segments + } + + aNbFacePrimitives += aNbNodes - 2; // add face triangles + } + } + + Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles + (aNbFacePrimitives * 3, 0, IsReflect); + + Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments + (aNbEdgePrimitives * 2); MeshVS_TwoColors aTC = aColIter2.Key(); Quantity_Color aMyIntColor, aMyBackColor; @@ -442,12 +570,13 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& anAsp->SetDistinguishOn (); anAsp->SetInteriorColor ( aMyIntColor ); anAsp->SetBackInteriorColor ( aMyBackColor ); - if (anEdgeOn) + /*if (anEdgeOn) anAsp->SetEdgeOn(); else - anAsp->SetEdgeOff(); + anAsp->SetEdgeOff();*/ - aGroup2->SetPrimitivesAspect ( anAsp ); + Handle(Graphic3d_AspectLine3d) anEdgeAspect = + new Graphic3d_AspectLine3d (anEdgeColor, anEdgeType, anEdgeWidth); for( it.Reset(); it.More(); it.Next() ) { @@ -460,43 +589,60 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& if( IsExcludingOn() ) IDsToExclude.Add( aKey ); - if ( aType == MeshVS_ET_Face && NbNodes > 0 ) + if (aType == MeshVS_ET_Face && NbNodes > 0) { // Preparing normal(s) to show reflections if requested Handle(TColStd_HArray1OfReal) aNormals; // OCC21720 Always passing normals to OpenGL to make materials work // For OpenGL: "No normals" -> "No lighting" -> "no materials taken into account" - Standard_Boolean hasNormals = /*IsReflect &&*/ - aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ); + Standard_Boolean aHasNormals = /*IsReflect &&*/ + aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals); - aPolyArr->AddBound ( NbNodes ); + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) + { + for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx) + { + if (IsReflect) + { + aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1), + aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2), + aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3), + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1) : 0.0, + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2) : 0.0, + aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3) : 1.0); + } + else + { + aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1), + aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2), + aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3)); + } + } + } - for ( i=1; i<=NbNodes; i++ ) + if (anEdgeOn) { - if ( IsReflect ) + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) { - hasNormals ? aPolyArr->AddVertex ( aCoords(3 * i - 2), - aCoords(3 * i - 1), - aCoords(3 * i ), - aNormals->Value(3 * i - 2), - aNormals->Value(3 * i - 1), - aNormals->Value(3 * i ) ) : - aPolyArr->AddVertex ( aCoords(3 * i - 2), - aCoords(3 * i - 1), - aCoords(3 * i ), - 0., - 0., - 1. ); + const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes; + + anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1), + aCoords (3 * aNodeIdx + 2), + aCoords (3 * aNodeIdx + 3)); + + anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1), + aCoords (3 * aNextIdx + 2), + aCoords (3 * aNextIdx + 3)); } - else - aPolyArr->AddVertex ( aCoords(3*i-2), - aCoords(3*i-1), - aCoords(3*i ) ); } } } } - aGroup2->AddPrimitiveArray ( aPolyArr ); + + aGroup2->AddPrimitiveArray (aFaceTriangles); + aGroup2->SetGroupPrimitivesAspect (anAsp); + aGroup3->AddPrimitiveArray (anEdgeSegments); + aGroup3->SetGroupPrimitivesAspect (anEdgeAspect); } } diff --git a/src/MeshVS/MeshVS_MeshPrsBuilder.cdl b/src/MeshVS/MeshVS_MeshPrsBuilder.cdl index 50c3ec2873..6cb0dc2f00 100644 --- a/src/MeshVS/MeshVS_MeshPrsBuilder.cdl +++ b/src/MeshVS/MeshVS_MeshPrsBuilder.cdl @@ -37,8 +37,10 @@ uses AspectMarker3d from Graphic3d, Array1OfReal from TColStd, ArrayOfPolylines from Graphic3d, + ArrayOfSegments from Graphic3d, ArrayOfPolygons from Graphic3d, ArrayOfPrimitives from Graphic3d, + ArrayOfTriangles from Graphic3d, PackedMapOfInteger from TColStd is @@ -76,29 +78,30 @@ is ---Purpose: Builds presentation of hilighted entity AddLinkPrs ( me; theCoords : Array1OfReal from TColStd; - theLines : ArrayOfPolylines from Graphic3d; + theLines : ArrayOfSegments from Graphic3d; IsShrinked : Boolean; ShrinkCoef : Real ) is protected; ---Purpose: Add to array of polylines some lines representing link - AddFaceWirePrs ( me; theCoords : Array1OfReal from TColStd; - NbNodes : Integer; - theLines : ArrayOfPolylines from Graphic3d; - IsShrinked : Boolean; - ShrinkCoef : Real + AddFaceWirePrs ( me; + theCoords : Array1OfReal from TColStd; + theNbNodes : Integer; + theLines : ArrayOfSegments from Graphic3d; + theIsShrinked : Boolean; + theShrinkingCoef : Real ) is protected; - ---Purpose: Add to array of polylines some lines representing face's wire - - AddFaceSolidPrs ( me; ID : Integer; - theCoords : Array1OfReal from TColStd; - NbNodes : Integer; - MaxNodes : Integer; - thePolygons : ArrayOfPolygons from Graphic3d; - IsReflected : Boolean; - IsShrinked : Boolean; - ShrinkCoef : Real; - IsMeshSmoothShading : Boolean + ---Purpose: Add to array of segments representing face's wire + + AddFaceSolidPrs ( me; ID : Integer; + theCoords : Array1OfReal from TColStd; + theNbNodes : Integer; + theMaxNodes : Integer; + theTriangles : ArrayOfTriangles from Graphic3d; + theIsReflected : Boolean; + theIsShrinked : Boolean; + theShrinkCoef : Real; + theIsMeshSmoothShading : Boolean ) is protected; ---Purpose: Add to array of polygons a polygon representing face @@ -120,10 +123,10 @@ is ---Purpose: Calculate how many polygons or polylines are necessary to draw passed topology DrawArrays ( me; Prs : Presentation from Prs3d; - thePolygons : ArrayOfPolygons from Graphic3d; - theLines : ArrayOfPolylines from Graphic3d; - theLinkLines : ArrayOfPolylines from Graphic3d; - theVolumesInShad : ArrayOfPolygons from Graphic3d; + thePolygons : ArrayOfPrimitives from Graphic3d; + theLines : ArrayOfPrimitives from Graphic3d; + theLinkLines : ArrayOfPrimitives from Graphic3d; + theVolumesInShad : ArrayOfPrimitives from Graphic3d; IsPolygonsEdgesOff : Boolean; IsSelected : Boolean; theFillAsp : AspectFillArea3d from Graphic3d; diff --git a/src/MeshVS/MeshVS_MeshPrsBuilder.cxx b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx index c4c748c807..a3edb3b570 100644 --- a/src/MeshVS/MeshVS_MeshPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_MeshPrsBuilder.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -49,6 +51,10 @@ #include #include #include +#include + +#include +#include //================================================================ // Function : Constructor MeshVS_MeshPrsBuilder @@ -120,7 +126,7 @@ void MeshVS_MeshPrsBuilder::BuildNodes ( const Handle(Prs3d_Presentation)& Prs, anIDs.Assign( IDs ); if ( !HasSelectFlag && !HasHilightFlag ) { - // subtract the hidden nodes and ids to exclude (to minimise allocated memory) + // subtract the hidden nodes and ids to exclude (to minimize allocated memory) Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = myParentMesh->GetHiddenNodes(); if ( !aHiddenNodes.IsNull() ) anIDs.Subtract( aHiddenNodes->Map() ); @@ -164,9 +170,9 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs TColStd_PackedMapOfInteger& IDsToExclude, const Standard_Integer DisplayMode ) const { - Standard_Integer maxnodes; + Standard_Integer maxnodes; - Handle (MeshVS_DataSource) aSource = GetDataSource(); + Handle(MeshVS_DataSource) aSource = GetDataSource(); if ( aSource.IsNull() ) return; @@ -200,7 +206,7 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs IsReflect = ( IsMeshReflect && !HasHilightFlag ); aDrawer->GetBoolean ( MeshVS_DA_SmoothShading, IsMeshSmoothShading ); - // display mode for hilighted prs of groups + // display mode for highlighted prs of groups IsShrink = ( IsShrink && !HasHilightFlag ); IsShading = ( IsShading || HasHilightFlag ); @@ -221,14 +227,7 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs Standard_Boolean IsOverlapControl = !IsMeshAllowOverlap && ( IsWireFrame || IsShading ) && !HasSelectFlag; - Handle (Graphic3d_ArrayOfPolygons) aPolygons, aVolumes; - Handle (Graphic3d_ArrayOfPolylines) aPolylines, aLinkPolylines; - - Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0, - PolylineVerticesFor3D = 0, PolylineBoundsFor3D = 0, - NbNodes; - - // subtract the hidden elements and ids to exclude (to minimise allocated memory) + // subtract the hidden elements and ids to exclude (to minimize allocated memory) TColStd_PackedMapOfInteger anIDs; anIDs.Assign( IDs ); Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems(); @@ -238,180 +237,276 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo; TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); - for( ; it.More(); it.Next() ) + + Standard_Boolean showEdges = Standard_True; + aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges ); + + showEdges = IsWireFrame || showEdges; + + Standard_Integer* aNodesBuf = (Standard_Integer*) alloca (maxnodes * sizeof (Standard_Integer)); + Standard_Real* aCoordsBuf = (Standard_Real*) alloca (3 * maxnodes * sizeof (Standard_Real)); + + TColStd_Array1OfInteger aNodes (*aNodesBuf, 1, maxnodes); + TColStd_Array1OfReal aCoords (*aCoordsBuf, 1, 3 * maxnodes); + + Standard_Integer aNbFacePrimitives = 0; + Standard_Integer aNbVolmPrimitives = 0; + Standard_Integer aNbEdgePrimitives = 0; + Standard_Integer aNbLinkPrimitives = 0; + + MeshVS_EntityType aType; + + for (it.Reset(); it.More(); it.Next()) { - Standard_Integer aKey = it.Key(); - if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) ) + Standard_Integer aNbNodes = 0; + + if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if (aType == MeshVS_ET_Volume) + { + if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo)) + { + for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx); + + if (showEdges) // add edge segments + { + aNbEdgePrimitives += aFaceNodes.Length(); + } + + if (IsShading || IsShrink) // add volumetric cell triangles + { + if (!HasSelectFlag) + aNbVolmPrimitives += aFaceNodes.Length() - 2; + } + } + } + } + else if (aType == MeshVS_ET_Link) + { + if (showEdges) + { + aNbLinkPrimitives += 1; // add link segment + } + } + else if (aType == MeshVS_ET_Face) { - if( !HasSelectFlag ) - HowManyPrimitives( aTopo, Standard_True, HasSelectFlag, NbNodes, - PolygonVerticesFor3D, PolygonBoundsFor3D ); - HowManyPrimitives( aTopo, Standard_False, HasSelectFlag, NbNodes, - PolylineVerticesFor3D, PolylineBoundsFor3D ); + if (showEdges) + { + aNbEdgePrimitives += aNbNodes; // add edge segments + } + + if (!IsOverlapControl || IsShading) + { + if ((IsShading || IsShrink) && !HasSelectFlag) + { + aNbFacePrimitives += aNbNodes - 2; // add face triangles + } + } } } - Standard_Integer Extent = anIDs.Extent(); + // 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); - if ( IsReflect ) - { - aPolygons = new Graphic3d_ArrayOfPolygons - ( maxnodes*Extent, Extent, 0, Standard_True ); - aVolumes = new Graphic3d_ArrayOfPolygons - ( PolygonVerticesFor3D, PolygonBoundsFor3D, 0, Standard_True ); - } - else + Handle (Graphic3d_ArrayOfSegments) aLinkSegments; + Handle (Graphic3d_ArrayOfSegments) aEdgeSegments; + + if (showEdges) { - aPolygons = new Graphic3d_ArrayOfPolygons( maxnodes*Extent, Extent ); - aVolumes = new Graphic3d_ArrayOfPolygons ( PolygonVerticesFor3D, PolygonBoundsFor3D ); + aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2); + aEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2); } Standard_Integer howMany = 1; if ( IsOverlapControl ) howMany = 2; - Standard_Boolean showEdges = Standard_True; - aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges ); - - showEdges = IsWireFrame || showEdges; - if ( showEdges ) - { - aPolylines = new Graphic3d_ArrayOfPolylines ( ( maxnodes+1 )*Extent + PolylineVerticesFor3D, - howMany * Extent + PolylineBoundsFor3D ); - aLinkPolylines = new Graphic3d_ArrayOfPolylines ( 2*Extent, Extent ); - } - - MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real)); - TColStd_Array1OfReal aCoords( aCoordsBuf, 1, 3*maxnodes ); - MeshVS_EntityType aType; - TColStd_PackedMapOfInteger aCustomElements; Quantity_Color anOldEdgeColor; + Quantity_Color anEdgeColor; + Quantity_Color anIntColor; Aspect_InteriorStyle anIntType; - Quantity_Color anIntColor, anEdgeColor; Aspect_TypeOfLine aLine; Standard_Real aWidth; - MeshVS_TwoNodes aTwoNodes; - aFill->Values ( anIntType, anIntColor, anEdgeColor, aLine, aWidth ); + aFill->Values (anIntType, anIntColor, anEdgeColor, aLine, aWidth); MeshVS_MapOfTwoNodes aLinkNodes; - if ( showEdges && IsOverlapControl ) - // Forbid drawings of edges, which overlap with some links - for( it.Reset(); it.More(); it.Next() ) + + // Forbid drawings of edges which overlap with some links + if (showEdges && IsOverlapControl) + { + for (it.Reset(); it.More(); it.Next()) { - Standard_Integer aKey = it.Key(); - if ( aSource->GetGeomType ( aKey, Standard_True, aType ) && - aType == MeshVS_ET_Link ) + if (aSource->GetGeomType (it.Key(), Standard_True, aType) && aType == MeshVS_ET_Link) { - MeshVS_Buffer aNodesBuf (maxnodes * sizeof(Standard_Integer)); - TColStd_Array1OfInteger aNodes (aNodesBuf, 1, maxnodes); - Standard_Integer nbNodes; - if ( aSource->GetNodesByElement( aKey, aNodes, nbNodes ) && - nbNodes == 2 ) + Standard_Integer aNbNodes; + + if (aSource->GetNodesByElement (it.Key(), aNodes, aNbNodes) && aNbNodes == 2) { - aTwoNodes.First = aNodes(1); - aTwoNodes.Second = aNodes(2); - aLinkNodes.Add ( aTwoNodes ); + aLinkNodes.Add (MeshVS_TwoNodes (aNodes(1), aNodes(2))); } } } + } + + NCollection_Map aSegmentMap; - for( it.Reset(); it.More(); it.Next() ) + for (it.Reset(); it.More(); it.Next()) { - Standard_Integer aKey = it.Key(); + const Standard_Integer aKey = it.Key(); - if ( ! aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) ) + Standard_Integer NbNodes; + if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) continue; - switch ( aType ) + if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes)) + continue; + + switch (aType) { - case MeshVS_ET_Volume : - if( IsExcludingOn() ) + case MeshVS_ET_Volume: + { + if (IsExcludingOn()) IDsToExclude.Add (aKey); - if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) ) + + if (aSource->Get3DGeom (aKey, NbNodes, aTopo)) { - // !!! TO DO: Overlap control - // add wireframe presentation (draw edges for shading mode as well) - if ( showEdges ) - AddVolumePrs ( aTopo, aCoords, NbNodes, aPolylines, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef ); - - // add shading presentation - if ( ( IsShading || IsShrink ) && !HasSelectFlag ) - AddVolumePrs ( aTopo, aCoords, NbNodes, aVolumes, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef ); + // Add wire-frame presentation (draw edges for shading mode as well) + if (showEdges) + { + AddVolumePrs (aTopo, aCoords, NbNodes, + aEdgeSegments, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef); + } + + // Add shading presentation + if ((IsShading || IsShrink) && !HasSelectFlag) + { + AddVolumePrs (aTopo, aCoords, NbNodes, + aVolmTriangles, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef); + } } - break; + } + break; - case MeshVS_ET_Link : - if( IsExcludingOn() ) + case MeshVS_ET_Link: + { + if (IsExcludingOn()) IDsToExclude.Add (aKey); - if ( showEdges ) - AddLinkPrs ( aCoords, aLinkPolylines, IsShrink || HasSelectFlag, aShrinkCoef ); - break; - case MeshVS_ET_Face : - if( IsExcludingOn() ) - IDsToExclude.Add (aKey); - if ( showEdges && IsOverlapControl ) + if (showEdges) { - MeshVS_Buffer aNodesBuf (NbNodes * sizeof(Standard_Integer)); - TColStd_Array1OfInteger aNodes (aNodesBuf, 1, NbNodes); - if ( !aSource->GetNodesByElement( aKey, aNodes, NbNodes ) ) - continue; + AddLinkPrs (aCoords, aLinkSegments, IsShrink || HasSelectFlag, aShrinkCoef); + } + } + break; + case MeshVS_ET_Face: + { + if (IsExcludingOn()) + IDsToExclude.Add (aKey); + + if (showEdges && IsOverlapControl) + { Standard_Integer Last = 0; - for ( Standard_Integer i=1; i<=NbNodes; i++ ) + + MeshVS_TwoNodes aTwoNodes (aNodes (1)); + + for (Standard_Integer i = 1; i <= NbNodes; ++i) { - if ( i==1 ) - aTwoNodes.First = aNodes(i); - else + if (i > 1) aTwoNodes.First = aTwoNodes.Second; - aTwoNodes.Second = ( iAddBound ( i-Last ); - for (Standard_Integer j = Last+1; j<=i; j++) - aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) ); - Last = i; + 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 ) + + if (NbNodes - Last > 0) { - aPolylines->AddBound ( NbNodes-Last+1 ); - for (Standard_Integer j = Last+1; j<=NbNodes; j++) - aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) ); + 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)); - aPolylines->AddVertex ( aCoords(1), aCoords(2), aCoords(3) ); + aSegmentMap.Add (aSegment); + } + } } } - if ( !IsOverlapControl || IsShading ) + if (!IsOverlapControl || IsShading) { - if ( !IsOverlapControl && showEdges ) - AddFaceWirePrs(aCoords, NbNodes, aPolylines, - IsShrink || HasSelectFlag, aShrinkCoef ); - if ( ( IsShading || IsShrink ) && !HasSelectFlag ) - AddFaceSolidPrs(aKey, aCoords, NbNodes, maxnodes, aPolygons, - IsReflect, IsShrink || HasSelectFlag, - aShrinkCoef, IsMeshSmoothShading ); + if (!IsOverlapControl && showEdges) + { + AddFaceWirePrs (aCoords, NbNodes, + aEdgeSegments, IsShrink || HasSelectFlag, aShrinkCoef); + } + + if ((IsShading || IsShrink) && !HasSelectFlag) + { + AddFaceSolidPrs (aKey, aCoords, NbNodes, maxnodes, aFaceTriangles, IsReflect, + IsShrink || HasSelectFlag, aShrinkCoef, IsMeshSmoothShading); + } } - break; + } + break; default: - aCustomElements.Add( aKey ); - break; + { + aCustomElements.Add (aKey); + } } } - if ( IsShrink ) + if (IsShrink) { anOldEdgeColor = anEdgeColor; - aFill->SetEdgeColor ( Quantity_NOC_BLACK ); + aFill->SetEdgeColor (Quantity_NOC_BLACK); } - DrawArrays ( Prs, aPolygons, aPolylines, aLinkPolylines, aVolumes, + //std::cout << "Actual extents: " << std::endl + // << "Face tris: " << aFaceTriangles->ItemNumber() << " from " << aNbFacePrimitives << std::endl + // << "Volm tris: " << aVolmTriangles->ItemNumber() << " from " << aNbVolmPrimitives << std::endl + // << "Face segs: " << aEdgeSegments->ItemNumber() << " from " << aNbEdgePrimitives << std::endl + // << "Link segs: " << aLinkSegments->ItemNumber() << " from " << aNbLinkPrimitives << std::endl; + + DrawArrays ( Prs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles, !showEdges, HasSelectFlag, aFill, aBeam ); if ( !aCustomElements.IsEmpty() ) @@ -542,126 +637,186 @@ void MeshVS_MeshPrsBuilder::BuildHilightPrs ( const Handle(Prs3d_Presentation)& // Function : AddLinkPrs // Purpose : //================================================================ -void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal& theCoords, - const Handle(Graphic3d_ArrayOfPolylines)& theLines, - const Standard_Boolean IsShrinked, - const Standard_Real ShrinkCoef) const +void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal& theCoords, + const Handle(Graphic3d_ArrayOfSegments)& theSegments, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkCoef) const { - Standard_Real x1 = theCoords(1); - Standard_Real y1 = theCoords(2); - Standard_Real z1 = theCoords(3); - Standard_Real x2 = theCoords(4); - Standard_Real y2 = theCoords(5); - Standard_Real z2 = theCoords(6); - Standard_Real xG, yG, zG; - - if ( IsShrinked ) + Standard_Real aX1 = theCoords (1); + Standard_Real aY1 = theCoords (2); + Standard_Real aZ1 = theCoords (3); + Standard_Real aX2 = theCoords (4); + Standard_Real aY2 = theCoords (5); + Standard_Real aZ2 = theCoords (6); + + if (theIsShrinked) { - xG = (x1+x2)/2.0; - yG = (y1+y2)/2.0; - zG = (z1+z2)/2.0; - x1 = (x1 - xG) * ShrinkCoef + xG; - x2 = 2.0*xG - x1; - y1 = (y1 - yG) * ShrinkCoef + yG; - y2 = 2.0*yG - y1; - z1 = (z1 - zG) * ShrinkCoef + zG; - z2 = 2.0*zG - z1; + const Standard_Real xG = (aX1 + aX2) * 0.5; + const Standard_Real yG = (aY1 + aY2) * 0.5; + const Standard_Real zG = (aZ1 + aZ2) * 0.5; + + aX1 = (aX1 - xG) * theShrinkCoef + xG; + aY1 = (aY1 - yG) * theShrinkCoef + yG; + aZ1 = (aZ1 - zG) * theShrinkCoef + zG; + + aX2 = 2.0 * xG - aX1; + aY2 = 2.0 * yG - aY1; + aZ2 = 2.0 * zG - aZ1; } - theLines->AddBound ( 2 ); - theLines->AddVertex ( x1, y1, z1 ); - theLines->AddVertex ( x2, y2, z2 ); + + theSegments->AddVertex (aX1, aY1, aZ1); + theSegments->AddVertex (aX2, aY2, aZ2); } //================================================================ // Function : AddFaceWirePrs // Purpose : //================================================================ -void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal& theCoords, - const Standard_Integer NbNodes, - const Handle(Graphic3d_ArrayOfPolylines)& theLines, - const Standard_Boolean IsShrinked, - const Standard_Real ShrinkCoef) const +void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal& theCoords, + const Standard_Integer theNbNodes, + const Handle(Graphic3d_ArrayOfSegments)& theSegments, + const Standard_Boolean theIsShrinked, + const Standard_Real theShrinkingCoef) const { - Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, startX=0., startY=0., startZ=0.; - theLines->AddBound ( NbNodes+1 ); - if ( IsShrinked ) - CalculateCenter( theCoords, NbNodes, xG, yG, zG ); + Standard_Real aCenterX = 0.0; + Standard_Real aCenterY = 0.0; + Standard_Real aCenterZ = 0.0; - for ( Standard_Integer k=1; k<=NbNodes; k++) + if (theIsShrinked) { - X = theCoords(3*k-2); - Y = theCoords(3*k-1); - Z = theCoords(3*k); - if ( IsShrinked ) - { - X = (X - xG) * ShrinkCoef + xG; - Y = (Y - yG) * ShrinkCoef + yG; - Z = (Z - zG) * ShrinkCoef + zG; - } - if( k==1 ) + CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ); + } + + NCollection_Vector aNodes (theNbNodes); + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx) + { + gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1), + theCoords (3 * aNodeIdx + 2), + theCoords (3 * aNodeIdx + 3)); + + if (theIsShrinked) { - startX = X; startY = Y; startZ = Z; + aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX); + aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY); + aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ); } - theLines->AddVertex ( X, Y, Z ); + + aNodes.Append (aPnt); + } + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx) + { + theSegments->AddVertex (aNodes.Value (aNodeIdx).X(), + aNodes.Value (aNodeIdx).Y(), + aNodes.Value (aNodeIdx).Z()); + + const Standard_Integer aNextIdx = (aNodeIdx + 1) % theNbNodes; + + theSegments->AddVertex (aNodes.Value (aNextIdx).X(), + aNodes.Value (aNextIdx).Y(), + aNodes.Value (aNextIdx).Z()); } - theLines->AddVertex( startX, startY, startZ ); } //================================================================ // Function : AddFaceSolidPrs // Purpose : //================================================================ -void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer ID, - const TColStd_Array1OfReal& theCoords, - const Standard_Integer NbNodes, - const Standard_Integer MaxNodes, - const Handle(Graphic3d_ArrayOfPolygons)& thePolygons, - const Standard_Boolean IsReflected, - const Standard_Boolean IsShrinked, - const Standard_Real ShrinkCoef, - const Standard_Boolean IsMeshSmoothShading) const +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 ) aDS = myParentMesh->GetDataSource(); - if ( aDS.IsNull() ) + Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource(); + + if (aDataSource.IsNull()) return; - Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, nx = 0., ny = 0., nz = 0.; - thePolygons->AddBound ( NbNodes ); - if ( IsShrinked ) - CalculateCenter( theCoords, NbNodes, xG, yG, zG ); + Standard_Real aCenterX = 0.0; + Standard_Real aCenterY = 0.0; + Standard_Real aCenterZ = 0.0; + Standard_Real aNormalX = 0.0; + Standard_Real aNormalY = 0.0; + Standard_Real aNormalZ = 0.0; - Standard_Boolean allNormals = Standard_True; - Standard_Integer k; + if (theIsShrinked) + { + CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ); + } - if( IsReflected ) + NCollection_Vector aVertexNormals (theMaxNodes); + + if (theIsShaded) { - if( IsMeshSmoothShading ) - for( k=1; k<=NbNodes && allNormals; k++ ) - allNormals = aDS->GetNodeNormal (k, ID, nx, ny, nz); - if( !IsMeshSmoothShading || !allNormals ) - aDS->GetNormal( ID, MaxNodes, nx, ny, nz ); + if (theIsSmoothShading) + { + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= theNbNodes; ++aNodeIdx) + { + if (!aDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ)) + break; + + aVertexNormals.Append (gp_XYZ (aNormalX, aNormalY, aNormalZ)); + } + } + + if (!theIsSmoothShading || aVertexNormals.Size() != theNbNodes) + { + aDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ); + } } - for ( k=1; k<=NbNodes; k++) + NCollection_Vector aNodes (theMaxNodes); + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx) { - X = theCoords(3*k-2); - Y = theCoords(3*k-1); - Z = theCoords(3*k); - if ( IsShrinked ) + gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1), + theCoords (3 * aNodeIdx + 2), + theCoords (3 * aNodeIdx + 3)); + + if (theIsShrinked) { - X = (X - xG) * ShrinkCoef + xG; - Y = (Y - yG) * ShrinkCoef + yG; - Z = (Z - zG) * ShrinkCoef + zG; + aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX); + aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY); + aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ); } - if ( IsReflected ) + aNodes.Append (aPnt); + } + + // Triangulate polygon + for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes - 2; ++aNodeIdx) + { + for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) { - if( IsMeshSmoothShading && allNormals ) - aDS->GetNodeNormal (k, ID, nx, ny, nz); - thePolygons->AddVertex ( X, Y, Z, nx, ny, nz ); + if (theIsShaded) + { + if (theIsSmoothShading && aVertexNormals.Size() == theNbNodes) + { + aNormalX = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(); + aNormalY = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(); + aNormalZ = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z(); + } + + theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(), + aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(), + aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z(), + aNormalX, + aNormalY, + aNormalZ); + } + else + { + theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(), + aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(), + aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z()); + } } - else - thePolygons->AddVertex ( X, Y, Z ); } } @@ -669,171 +824,178 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer ID, // Function : AddVolumePrs // Purpose : //================================================================ -void MeshVS_MeshPrsBuilder::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) +void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo, + const TColStd_Array1OfReal& theNodes, + const Standard_Integer theNbNodes, + const Handle(Graphic3d_ArrayOfPrimitives)& theArray, + const Standard_Boolean theIsShaded, + const Standard_Boolean theIsShrinked, + const Standard_Boolean theIsSelected, + const Standard_Real theShrinkCoef) { - Standard_Real c[3]; c[0] = c[1] = c[2] = 0.0; - Standard_Integer low = Nodes.Lower(), n=NbNodes; + Standard_Real aCenter[] = { 0.0, 0.0, 0.0 }; - if( Topo.IsNull() || Array.IsNull() ) + Standard_Integer aLow = theNodes.Lower(); + + if (theTopo.IsNull() || theArray.IsNull()) return; - if( IsShrinked ) + if (theIsShrinked) { - for( Standard_Integer i=0; i<3*n; i++ ) - c[i%3] += Nodes.Value( low + i ); + for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3 * theNbNodes; ++aNodeIdx) + { + aCenter[aNodeIdx % 3] += theNodes.Value (aLow + aNodeIdx); + } - c[0] /= n; - c[1] /= n; - c[2] /= n; + aCenter[0] /= theNbNodes; + aCenter[1] /= theNbNodes; + aCenter[2] /= theNbNodes; } - Standard_Boolean IsPolygons = Array->IsKind( STANDARD_TYPE( Graphic3d_ArrayOfPolygons ) ); - Standard_Real x[2], y[2], z[2]; - Standard_Integer ind; - gp_Vec norm; + Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles)); - if( IsPolygons ) - { - for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ ) + if (aIsPolygons) + { + for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) { - const TColStd_SequenceOfInteger& aSeq = Topo->Value( i ); - - Standard_Integer m = aSeq.Length(); - Array->AddBound( m ); + const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); + const Standard_Integer aNbPolyNodes = aFaceNodes.Length(); - norm.SetCoord( 0, 0, 0 ); - if( IsReflected ) + Standard_Real* aPolyNodesBuf = (Standard_Real*) alloca ((3 * aNbPolyNodes + 1) * sizeof (Standard_Real)); + TColStd_Array1OfReal aPolyNodes (*aPolyNodesBuf, 0, 3 * aNbPolyNodes); + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes; ++aNodeIdx) { - MeshVS_Buffer PolyNodesBuf (3*m*sizeof(Standard_Real)); - TColStd_Array1OfReal PolyNodes( PolyNodesBuf, 0, 3*m ); - PolyNodes.SetValue( 0, m ); - for( Standard_Integer j=1; j<=m; j++ ) - { - ind = aSeq.Value( j ); - PolyNodes.SetValue( 3*j-2, Nodes.Value( low+3*ind ) ); - PolyNodes.SetValue( 3*j-1, Nodes.Value( low+3*ind+1 ) ); - PolyNodes.SetValue( 3*j, Nodes.Value( low+3*ind+2 ) ); + Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1); + + Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0); + Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1); + Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2); + + if (theIsShrinked) + { + aX = aCenter[0] + theShrinkCoef * (aX - aCenter[0]); + aY = aCenter[1] + theShrinkCoef * (aY - aCenter[1]); + aZ = aCenter[2] + theShrinkCoef * (aZ - aCenter[2]); } - // compute normal - // if( !MeshVS_Tool::GetNormal( PolyNodes, norm ) ) - // norm.SetCoord( 0, 0, 0 ); - MeshVS_Tool::GetAverageNormal( PolyNodes, norm ); + aPolyNodes.SetValue (3 * aNodeIdx + 1, aX); + aPolyNodes.SetValue (3 * aNodeIdx + 2, aY); + aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ); } + + gp_Vec aNorm; - Standard_Real nx = norm.X(), ny = norm.Y(), nz = norm.Z(); - - - for( Standard_Integer j=1; j<=m; j++ ) + if (theIsShaded) { - ind = aSeq.Value( j ); - x[0] = Nodes.Value( low + 3*ind ); - y[0] = Nodes.Value( low + 3*ind+1 ); - z[0] = Nodes.Value( low + 3*ind+2 ); + aPolyNodes.SetValue (0, aNbPolyNodes); + + if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm)) + { + aNorm.SetCoord (0.0, 0.0, 1.0); + } + } - if( IsShrinked ) + for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes - 2; ++aNodeIdx) // triangulate polygon + { + for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle { - x[0] = c[0] + ShrinkCoef * ( x[0]-c[0] ); - y[0] = c[1] + ShrinkCoef * ( y[0]-c[1] ); - z[0] = c[2] + ShrinkCoef * ( z[0]-c[2] ); + if (theIsShaded) + { + theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3), + aNorm.X(), + aNorm.Y(), + aNorm.Z()); + } + else + { + theArray->AddVertex (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); + } } - - if( IsReflected ) - Array->AddVertex( x[0], y[0], z[0], nx, ny, nz ); - else - Array->AddVertex( x[0], y[0], z[0] ); } } } - else if( IsSelect ) + else if (theIsSelected) { - for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ ) + for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) { - const TColStd_SequenceOfInteger& aSeq = Topo->Value( i ); - Standard_Real pc[3]; pc[0] = pc[1] = pc[2] = 0; - Standard_Integer j,m; - for( j=1, m=aSeq.Length(); j<=m; j++ ) + const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); + + Standard_Real aFaceCenter[] = { 0.0, 0.0, 0.0 }; + + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aFaceNodes.Length(); ++aNodeIdx) { - ind = aSeq.Value( j ); - for( Standard_Integer k=0; k<3; k++ ) - pc[k] += Nodes.Value( low + 3*ind+k ); + for (Standard_Integer aAxisIdx = 0; aAxisIdx < 3; ++aAxisIdx) + { + aFaceCenter[aAxisIdx] += theNodes.Value (aLow + 3 * aFaceNodes.Value (aNodeIdx) + aAxisIdx); + } } - pc[0] /= m; - pc[1] /= m; - pc[2] /= m; - Array->AddBound( m+1 ); - for( j=1, m=aSeq.Length(); j<=m+1; j++ ) + aFaceCenter[0] /= aFaceNodes.Length(); + aFaceCenter[1] /= aFaceNodes.Length(); + aFaceCenter[2] /= aFaceNodes.Length(); + + for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx) { - ind = aSeq.Value( (j-1)%m + 1 ); - x[0] = Nodes.Value( low + 3*ind ); - y[0] = Nodes.Value( low + 3*ind+1 ); - z[0] = Nodes.Value( low + 3*ind+2 ); - x[0] = pc[0] + ShrinkCoef * ( x[0]-pc[0] ); - y[0] = pc[1] + ShrinkCoef * ( y[0]-pc[1] ); - z[0] = pc[2] + ShrinkCoef * ( z[0]-pc[2] ); - Array->AddVertex( x[0], y[0], z[0] ); + for (Standard_Integer aSubIdx = 0; aSubIdx < 2; ++aSubIdx) // add segment + { + Standard_Integer anIdx = aFaceNodes.Value ((aNodeIdx + aSubIdx) % aNbNodes + 1); + + Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0); + Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1); + Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2); + + theArray->AddVertex (aFaceCenter[0] + theShrinkCoef * (aX - aFaceCenter[0]), + aFaceCenter[1] + theShrinkCoef * (aY - aFaceCenter[1]), + aFaceCenter[2] + theShrinkCoef * (aZ - aFaceCenter[2])); + } } } } else { - Standard_Integer F, S=0, k; + // Find all pairs of nodes (edges) to draw (will be drawn only once) + NCollection_Map aEdgeMap; - // Find all pairs of nodes (edges) to draw; - // map is used to ensure that each edge will be drawn only once - TColStd_PackedMapOfInteger aMap; - for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ ) + for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) { - const TColStd_SequenceOfInteger& aSeq = Topo->Value( i ); - for( Standard_Integer j=1, m=aSeq.Length(); j<=m; j++ ) + const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); + + for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx) { - if( j==1 ) - F = aSeq.Value( j ); - else - F = S; + const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes; - S = j::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next()) { - F = low + 3*(anIt.Key()%NbNodes); - S = low + 3*(anIt.Key()/NbNodes); - - x[0] = Nodes.Value( F ); - y[0] = Nodes.Value( F+1 ); - z[0] = Nodes.Value( F+2 ); - x[1] = Nodes.Value( S ); - y[1] = Nodes.Value( S+1 ); - z[1] = Nodes.Value( S+2 ); - - if( IsShrinked ) - for( k=0; k<2; k++ ) + const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first; + const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second; + + Standard_Real aX[] = { theNodes.Value (anIdx1 + 0), theNodes.Value (anIdx2 + 0) }; + Standard_Real aY[] = { theNodes.Value (anIdx1 + 1), theNodes.Value (anIdx2 + 1) }; + Standard_Real aZ[] = { theNodes.Value (anIdx1 + 2), theNodes.Value (anIdx2 + 2) }; + + if (theIsShrinked) + { + for (Standard_Integer anAxisIdx = 0; anAxisIdx < 2; ++anAxisIdx) { - x[k] = c[0] + ShrinkCoef * ( x[k]-c[0] ); - y[k] = c[1] + ShrinkCoef * ( y[k]-c[1] ); - z[k] = c[2] + ShrinkCoef * ( z[k]-c[2] ); + aX[anAxisIdx] = aCenter[0] + theShrinkCoef * (aX[anAxisIdx] - aCenter[0]); + aY[anAxisIdx] = aCenter[1] + theShrinkCoef * (aY[anAxisIdx] - aCenter[1]); + aZ[anAxisIdx] = aCenter[2] + theShrinkCoef * (aZ[anAxisIdx] - aCenter[2]); } + } - Array->AddBound( 2 ); - Array->AddVertex( x[0], y[0], z[0] ); - Array->AddVertex( x[1], y[1], z[1] ); + theArray->AddVertex (aX[0], aY[0], aZ[0]); + theArray->AddVertex (aX[1], aY[1], aZ[1]); } } } @@ -877,10 +1039,10 @@ void MeshVS_MeshPrsBuilder::HowManyPrimitives (const Handle(MeshVS_HArray1OfSequ // Purpose : //================================================================ void MeshVS_MeshPrsBuilder::DrawArrays( const Handle(Prs3d_Presentation)& Prs, - const Handle(Graphic3d_ArrayOfPolygons)& thePolygons, - const Handle(Graphic3d_ArrayOfPolylines)& theLines, - const Handle(Graphic3d_ArrayOfPolylines)& theLinkLines, - const Handle(Graphic3d_ArrayOfPolygons)& theVolumesInShad, + 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, diff --git a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl index 00981f40e5..eaa77ad927 100644 --- a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl +++ b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl @@ -35,17 +35,21 @@ uses Boolean from Standard, Integer from Standard, - DisplayModeFlags from MeshVS, - Mesh from MeshVS, - MeshPtr from MeshVS, - DataSource from MeshVS, - DataMapOfIntegerColor from MeshVS, - BuilderPriority from MeshVS, - SequenceOfColor from Aspect, - Color from Quantity, - DataMapOfIntegerReal from TColStd, - Texture2D from Graphic3d, - PackedMapOfInteger from TColStd + DisplayModeFlags from MeshVS, + Mesh from MeshVS, + MeshPtr from MeshVS, + DataSource from MeshVS, + DataMapOfIntegerColor from MeshVS, + BuilderPriority from MeshVS, + HArray1OfSequenceOfInteger from MeshVS, + SequenceOfColor from Aspect, + Color from Quantity, + Texture2D from Graphic3d, + ArrayOfPrimitives from Graphic3d, + DataMapOfIntegerReal from TColStd, + PackedMapOfInteger from TColStd, + Array1OfInteger from TColStd, + Array1OfReal from TColStd is @@ -123,6 +127,16 @@ is ---Purpose: Create texture in accordance with myTextureColorMap is static private; + AddVolumePrs ( me; + theTopo : HArray1OfSequenceOfInteger from MeshVS; + theNodes : Array1OfInteger from TColStd; + theCoords : Array1OfReal from TColStd; + theArray : ArrayOfPrimitives from Graphic3d; + theIsShaded : Boolean; + theNbColors : Integer; + theNbTexColors : Integer; + theColorRatio : Real ); + ---Purpose: Add to array polygons or polylines representing volume fields myNodeColorMap : DataMapOfIntegerColor from MeshVS; diff --git a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx index 9609098744..4d9f6c4abe 100644 --- a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -45,6 +47,8 @@ #include #include #include +#include +#include #include #include @@ -56,6 +60,9 @@ #include #include +#include +#include + /* Class : MeshVS_ImageTexture2D Description : Texture for nodal presentation @@ -146,7 +153,7 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, (!myUseTexture && !myNodeColorMap.Extent()) ) return; - // subtract the hidden elements and ids to exclude (to minimise allocated memory) + // subtract the hidden elements and ids to exclude (to minimize allocated memory) TColStd_PackedMapOfInteger anIDs; anIDs.Assign( IDs ); Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems(); @@ -223,10 +230,54 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, ( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D, 0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture ); + Standard_Integer aNbFacePrimitives = 0; + Standard_Integer aNbVolmPrimitives = 0; + Standard_Integer aNbEdgePrimitives = 0; + Standard_Integer aNbLinkPrimitives = 0; + + for (it.Reset(); it.More(); it.Next()) + { + Standard_Integer aNbNodes = 0; + + if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)) + continue; + + if (aType == MeshVS_ET_Volume) + { + if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo)) + { + for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx); + + aNbEdgePrimitives += aFaceNodes.Length(); // add edge segments + aNbVolmPrimitives += aFaceNodes.Length() - 2; // add volumetric cell triangles + } + } + } + else if (aType == MeshVS_ET_Link) + { + aNbLinkPrimitives += aNbNodes - 1; // add link segments + } + else if (aType == MeshVS_ET_Face) + { + aNbEdgePrimitives += aNbNodes; // add edge segments + 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) + + // Create array of polygons for interior presentation of faces and volumes + Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles + ( (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, myUseTexture || IsReflect, !myUseTexture, myUseTexture ); + // Create array of polylines for presentation of edges - // (used for optimization insted of SetEdgeOn method call) - Handle(Graphic3d_ArrayOfPolylines) aPolyL = new Graphic3d_ArrayOfPolylines - ( ( aMaxFaceNodes + 1 ) * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D ); + Handle(Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments + (aNbEdgePrimitives * 2); gp_Pnt P, Start; Standard_Real aMin = gp::Resolution() * gp::Resolution(); @@ -235,204 +286,132 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, // Prepare for scaling the incoming colors Standard_Real anColorRatio = aMaterial[0].Ambient(); - for( it.Reset(); it.More(); it.Next() ) + for (it.Reset(); it.More(); it.Next()) { Standard_Integer aKey = it.Key(); - if ( aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) ) + + if (aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) { - MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer)); - TColStd_Array1OfInteger aNodes(aNodesBuf, 1, NbNodes); - if ( !aSource->GetNodesByElement ( aKey, aNodes, NbNodes ) ) + TColStd_Array1OfInteger aNodes (1, NbNodes); + + if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes)) continue; Quantity_Color aNColor; Standard_Boolean isValid = Standard_True; Standard_Integer i; - if ( myUseTexture ) + + if (myUseTexture) { - for ( i = 1; i <= NbNodes && isValid; i++ ) - isValid = myTextureCoords.IsBound( aNodes( i ) ); + for (i = 1; i <= NbNodes && isValid; ++i) + isValid = myTextureCoords.IsBound (aNodes (i)); } else { - for ( i = 1; i <= NbNodes && isValid; i++ ) - isValid = GetColor ( aNodes( i ), aNColor ); + for (i = 1; i <= NbNodes && isValid; ++i) + isValid = GetColor (aNodes (i), aNColor); } - if ( !isValid ) + if (!isValid) continue; // Preparing normal(s) to show reflections if requested Handle(TColStd_HArray1OfReal) aNormals; + Standard_Boolean hasNormals = - ( IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ) ); + (IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals)); - if ( aType == MeshVS_ET_Face ) + if (aType == MeshVS_ET_Face) { - aCPolyArr->AddBound ( NbNodes ); - aPolyL->AddBound ( NbNodes + 1 ); - - for ( i = 1; i <= NbNodes; i++) + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) // triangulate polygon { - P = gp_Pnt( aCoords( 3 * i - 2 ), aCoords( 3 * i - 1 ), aCoords( 3 * i ) ); - if ( myUseTexture ) + for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle { - int anId = aNodes( i ); - double aTexCoord = myTextureCoords( anId ); + gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), + aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), + aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); - // transform texture coordinate in accordance with number of colors specified - // by upper level and real size of Gl texture - // The Gl texture has border colors interpolated with the colors from the color map, - // thats why we need to shrink texture coordinates around the middle point to - // exclude areas where the map colors are interpolated with the borders color - double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors; + gp_Vec aNorm = aDefNorm; - if ( hasNormals ) + if (hasNormals) { - gp_Vec aNorm(aNormals->Value( 3 * i - 2 ), - aNormals->Value( 3 * i - 1 ), - aNormals->Value( 3 * i )); - // There are two "rows" of colors: user's invalid color at the top - // of texture and line of map colors at the bottom of the texture. - // Since the texture has borders, which are interpolated with the "rows" of colors - // we should specify the 0.25 offset to get the correct texture color - aNorm.SquareMagnitude() > aMin ? - aCPolyArr->AddVertex(P, gp_Dir( aNorm ), - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) : - aCPolyArr->AddVertex(P, aDefNorm, - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ); - } - else - aCPolyArr->AddVertex( P, aDefNorm, - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ); - } - else - { - GetColor ( aNodes( i ), aNColor ); + gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), + aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), + aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); - if ( IsReflect ) - { - // Simulating TelUpdateMaterial() from OpenGl_attri.c - // to get the same colors in elemental and nodal color prs builders - aNColor.SetValues(anColorRatio * aNColor.Red(), - anColorRatio * aNColor.Green(), - anColorRatio * aNColor.Blue(), - Quantity_TOC_RGB); - - if ( hasNormals ) + if (aTestNorm.SquareMagnitude() > aMin) { - gp_Vec aNorm(aNormals->Value( 3 * i - 2 ), - aNormals->Value( 3 * i - 1 ), - aNormals->Value( 3 * i )); - aNorm.SquareMagnitude() > aMin ? - aCPolyArr->AddVertex(P, gp_Dir( aNorm ), aNColor ) : - aCPolyArr->AddVertex(P, aDefNorm , aNColor ); + aNorm = gp_Dir (aTestNorm); } - else - aCPolyArr->AddVertex(P, aDefNorm, aNColor ); } - else - aCPolyArr->AddVertex( P, aNColor ); - } - aPolyL->AddVertex ( P ); - if ( i == 1 ) - Start = P; - } - aPolyL->AddVertex ( Start ); - // if IsExcludingOn then presentation must not be built by other builders - if ( IsExcludingOn() ) - IDsToExclude.Add( aKey ); - } - else if ( aType == MeshVS_ET_Volume ) - { - if ( !aSource->Get3DGeom( aKey, NbNodes, aTopo ) ) - continue; - - // iterate through faces of volume - for ( Standard_Integer k = aTopo->Lower(), last = aTopo->Upper(), normIndex = 1; k <= last; k++, normIndex++ ) - { - const TColStd_SequenceOfInteger& aSeq = aTopo->Value( k ); - Standard_Integer m = aSeq.Length(), ind; - - // build polygon & polylines for current face - aCPolyArr->AddBound( m ); - aPolyL->AddBound( m + 1 ); - for ( Standard_Integer j = 1; j <= m; j++ ) - { - ind = aSeq.Value( j ); - P = gp_Pnt( aCoords( 3 * ind + 1 ), - aCoords( 3 * ind + 2 ), - aCoords( 3 * ind + 3 ) ); - if ( myUseTexture ) + if (myUseTexture) { - Standard_Integer anId = aNodes( ind + 1 ); - Standard_Real aTexCoord = myTextureCoords( anId ); - - // transform texture coordinate in accordance with number of colors specified - // by upper level and real size of Gl texture - // The Gl texture has border colors interpolated with the colors from the color map, - // thats why we need to shrink texture coordinates around the middle point to - // exclude areas where the map colors are interpolated with the borders color - double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors; - - if ( hasNormals ) - { - gp_Vec aNorm(aNormals->Value( 3 * i - 2 ), - aNormals->Value( 3 * i - 1 ), - aNormals->Value( 3 * i )); - // There are two "rows" of colors: user's invalid color at the top - // of texture and line of map colors at the bottom of the texture. - // Since the texture has borders, which are interpolated with the "rows" of colors - // we should specify the 0.25 offset to get the correct texture color - aNorm.SquareMagnitude() > aMin ? - aCPolyArr->AddVertex(P, gp_Dir( aNorm ), - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) : - aCPolyArr->AddVertex(P, aDefNorm, - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ); - } - else - aCPolyArr->AddVertex( P, aDefNorm, - gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ); + const Standard_Real aTexCoord = myTextureCoords (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1))); + + // Transform texture coordinate in accordance with number of colors specified + // by upper level and real size of OpenGL texture. The OpenGL texture has border + // colors interpolated with the colors from the color map, thats why we need to + // shrink texture coordinates around the middle point to exclude areas where the + // map colors are interpolated with the borders color + aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d ( + (aTexCoord * (nbColors - 1.0) + 0.5) / nbTextureColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75)); } else { - GetColor( aNodes( ind + 1 ), aNColor ); - if ( IsReflect ) + GetColor (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)), aNColor); + + if (IsReflect) { - // Simulating TelUpdateMaterial() from OpenGl_attri.c - // to get the same colors in elemental and nodal color prs builders - aNColor.SetValues(anColorRatio * aNColor.Red(), - anColorRatio * aNColor.Green(), - anColorRatio * aNColor.Blue(), - Quantity_TOC_RGB); - - if ( hasNormals ) - { - gp_Vec aNorm(aNormals->Value( 3 * normIndex - 2 ), - aNormals->Value( 3 * normIndex - 1 ), - aNormals->Value( 3 * normIndex )); - aNorm.SquareMagnitude() > aMin ? - aCPolyArr->AddVertex( P, gp_Dir( aNorm ), aNColor ) : - aCPolyArr->AddVertex( P, aDefNorm , aNColor ); - } - else - aCPolyArr->AddVertex( P, aDefNorm, aNColor ); + aNColor.SetValues (anColorRatio * aNColor.Red(), + anColorRatio * aNColor.Green(), + anColorRatio * aNColor.Blue(), + Quantity_TOC_RGB); + + aFaceTriangles->AddVertex (aPnt, aNorm, aNColor); } else - aCPolyArr->AddVertex( P, aNColor ); + { + aFaceTriangles->AddVertex (aPnt, aNColor); + } } - aPolyL->AddVertex ( P ); - if ( j == 1 ) - Start = P; } - aPolyL->AddVertex ( Start ); + } + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) // border segmentation + { + const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes; + + anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1), + aCoords (3 * aNodeIdx + 2), + aCoords (3 * aNodeIdx + 3)); + + anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1), + aCoords (3 * aNextIdx + 2), + aCoords (3 * aNextIdx + 3)); } // if IsExcludingOn then presentation must not be built by other builders - if ( IsExcludingOn() ) - IDsToExclude.Add( aKey ); + if (IsExcludingOn()) + { + IDsToExclude.Add (aKey); + } + } + else if (aType == MeshVS_ET_Volume) + { + if (!aSource->Get3DGeom (aKey, NbNodes, aTopo)) + continue; + + AddVolumePrs (aTopo, aNodes, aCoords, aFaceTriangles, + IsReflect, nbColors, nbTextureColors, anColorRatio); + + AddVolumePrs (aTopo, aNodes, aCoords, anEdgeSegments, + IsReflect, nbColors, nbTextureColors, anColorRatio); + + // if IsExcludingOn then presentation must not be built by other builders + if (IsExcludingOn()) + IDsToExclude.Add (aKey); } } } // for ( ... @@ -500,7 +479,8 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::CurrentGroup ( Prs ); aGroup1->SetPrimitivesAspect( anAsp ); - aGroup1->AddPrimitiveArray( aCPolyArr ); + aGroup1->AddPrimitiveArray( aFaceTriangles /*aCPolyArr*/ ); + //aGroup1->AddPrimitiveArray( aCPolyArr ); if (aShowEdges) { @@ -511,11 +491,136 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, anAsp->SetTextureMapOff(); aGroup2->SetPrimitivesAspect( anAsp ); aGroup2->SetPrimitivesAspect( anLAsp ); - aGroup2->AddPrimitiveArray( aPolyL ); + aGroup2->AddPrimitiveArray( anEdgeSegments ); anAsp->SetEdgeOn(); } } +//================================================================ +// Function : AddVolumePrs +// Purpose : +//================================================================ +void MeshVS_NodalColorPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo, + const TColStd_Array1OfInteger& theNodes, + const TColStd_Array1OfReal& theCoords, + const Handle(Graphic3d_ArrayOfPrimitives)& theArray, + const Standard_Boolean theIsShaded, + const Standard_Integer theNbColors, + const Standard_Integer theNbTexColors, + const Standard_Real theColorRatio) const +{ + Standard_Integer aLow = theCoords.Lower(); + + if (theTopo.IsNull() || theArray.IsNull()) + return; + + Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles)); + + if (aIsPolygons) + { + for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); + + TColStd_Array1OfReal aPolyNodes (0, 3 * aFaceNodes.Length()); + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length(); ++aNodeIdx) + { + Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1); + + Standard_Real aX = theCoords.Value (aLow + 3 * anIdx + 0); + Standard_Real aY = theCoords.Value (aLow + 3 * anIdx + 1); + Standard_Real aZ = theCoords.Value (aLow + 3 * anIdx + 2); + + aPolyNodes.SetValue (3 * aNodeIdx + 1, aX); + aPolyNodes.SetValue (3 * aNodeIdx + 2, aY); + aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ); + } + + gp_Vec aNorm (0.0, 0.0, 1.0); + + if (theIsShaded) + { + aPolyNodes.SetValue (0, aFaceNodes.Length()); + + if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm)) + { + aNorm.SetCoord (0.0, 0.0, 1.0); + } + } + + for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length() - 2; ++aNodeIdx) // triangulate polygon + { + for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle + { + gp_Pnt aPnt (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), + aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); + + if (myUseTexture) + { + const Standard_Real aTexCoord = myTextureCoords (theNodes (aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)); + + theArray->AddVertex (aPnt, aNorm, gp_Pnt2d ( + (aTexCoord * (theNbColors - 1.0) + 0.5) / theNbTexColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75)); + } + else + { + Quantity_Color aNColor; + GetColor (theNodes ((aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)), aNColor); + + if (theIsShaded) + { + aNColor.SetValues (theColorRatio * aNColor.Red(), + theColorRatio * aNColor.Green(), + theColorRatio * aNColor.Blue(), + Quantity_TOC_RGB); + + theArray->AddVertex (aPnt, aNorm, aNColor); + } + else + { + theArray->AddVertex (aPnt, aNColor); + } + } + } + } + } + } + else + { + // Find all pairs of nodes (edges) to draw (will be drawn only once) + NCollection_Map aEdgeMap; + + for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) + { + const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); + + for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx) + { + const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes; + + aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1), + aFaceNodes.Value (aNextIdx + 1))); + } + } + + // Draw edges + for(NCollection_Map::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next()) + { + const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first; + const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second; + + Standard_Real aX[] = { theCoords.Value (anIdx1 + 0), theCoords.Value (anIdx2 + 0) }; + Standard_Real aY[] = { theCoords.Value (anIdx1 + 1), theCoords.Value (anIdx2 + 1) }; + Standard_Real aZ[] = { theCoords.Value (anIdx1 + 2), theCoords.Value (anIdx2 + 2) }; + + theArray->AddVertex (aX[0], aY[0], aZ[0]); + theArray->AddVertex (aX[1], aY[1], aZ[1]); + } + } +} + //================================================================ // Function : SetColors // Purpose : diff --git a/src/MeshVS/MeshVS_SymmetricPairHasher.hxx b/src/MeshVS/MeshVS_SymmetricPairHasher.hxx new file mode 100644 index 0000000000..8fd64227b1 --- /dev/null +++ b/src/MeshVS/MeshVS_SymmetricPairHasher.hxx @@ -0,0 +1,23 @@ +#ifndef _MeshVS_SymmetricPairHasher_HeaderFile +#define _MeshVS_SymmetricPairHasher_HeaderFile + +#include + +typedef std::pair MeshVS_NodePair; + +//! Provides symmetric hash methods pair of integers. +struct MeshVS_SymmetricPairHasher +{ + static Standard_Integer HashCode (const MeshVS_NodePair& thePair, const Standard_Integer theMaxCode) + { + return ((thePair.first + thePair.second) & 0x7FFFFFFF) % theMaxCode + 1; + } + + static Standard_Boolean IsEqual (const MeshVS_NodePair& thePair1, const MeshVS_NodePair& thePair2) + { + return (thePair1.first == thePair2.first && thePair1.second == thePair2.second) + || (thePair1.first == thePair2.second && thePair1.second == thePair2.first); + } +}; + +#endif // _MeshVS_SymmetricPairHasher_HeaderFile \ No newline at end of file diff --git a/src/MeshVS/MeshVS_VectorPrsBuilder.cxx b/src/MeshVS/MeshVS_VectorPrsBuilder.cxx index aa784f4bb2..df2407349c 100644 --- a/src/MeshVS/MeshVS_VectorPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_VectorPrsBuilder.cxx @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include #include @@ -225,20 +227,13 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, return; // polylines - Standard_Integer aNbVertices = aNbVectors * NB_VERTICES; - Standard_Integer aNbBounds = aNbVectors * NB_BOUNDS; + Standard_Integer aNbVertices = aNbVectors * NB_VERTICES; - // fans - Standard_Integer aNbTriangleVertices = aNbVectors * (NB_TRIANGLES + 2); - Standard_Integer aNbFans = aNbVectors * NB_TRIANGLES; + Handle(Graphic3d_ArrayOfPrimitives) aLineArray = new Graphic3d_ArrayOfSegments (aNbVertices); + Handle(Graphic3d_ArrayOfPrimitives) aArrowLineArray = new Graphic3d_ArrayOfSegments (aNbVertices); - Handle(Graphic3d_ArrayOfPrimitives) aLineArray = - new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds); - Handle(Graphic3d_ArrayOfPrimitives) aArrowLineArray = - new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds); - - Handle(Graphic3d_ArrayOfTriangleFans) aTriangleArray = - new Graphic3d_ArrayOfTriangleFans(aNbTriangleVertices, aNbFans); + Handle(Graphic3d_ArrayOfPrimitives) aTriangleArray = new Graphic3d_ArrayOfSegments ( + aNbVectors * 8 /* vertices per arrow */, aNbVectors * 12 /* segments per arrow */ * 2 /* indices per segment */); TColgp_Array1OfPnt anArrowPnt(1,8); Standard_Real k, b, aMaxValue, aMinValue, aValue, X, Y, Z; @@ -261,7 +256,7 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, TColStd_PackedMapOfInteger aCustomElements; - // subtract the hidden elements and ids to exclude (to minimise allocated memory) + // subtract the hidden elements and ids to exclude (to minimize allocated memory) TColStd_PackedMapOfInteger anIDs; anIDs.Assign( IDs ); if ( IsElement ) @@ -338,17 +333,10 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, if ( !myIsSimplePrs ) { - Graphic3d_MaterialAspect aMatAspect; - aMatAspect.SetAmbient( 1 ); - aMatAspect.SetDiffuse( 0 ); - aMatAspect.SetEmissive( 0 ); - aMatAspect.SetShininess( 1 ); - aMatAspect.SetSpecular( 0 ); - Handle(Graphic3d_AspectFillArea3d) aFillAspect = - new Graphic3d_AspectFillArea3d (Aspect_IS_HOLLOW, aColor, aColor, Aspect_TOL_SOLID, - 1., aMatAspect, aMatAspect ); - - aVGroup->SetPrimitivesAspect( aFillAspect ); + Handle(Graphic3d_AspectLine3d) anArrowLinAspect = + new Graphic3d_AspectLine3d (aColor, Aspect_TOL_SOLID, mySimpleWidthPrm); + + aVGroup->SetPrimitivesAspect( anArrowLinAspect ); aVGroup->AddPrimitiveArray( aTriangleArray ); } else @@ -369,58 +357,68 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, // Purpose : Fill arrays of primitives for drawing force //======================================================================= void MeshVS_VectorPrsBuilder::DrawVector ( const gp_Trsf& theTrsf, - const Standard_Real Length, - const Standard_Real MaxLength, - const TColgp_Array1OfPnt& ArrowPoints, - const Handle(Graphic3d_ArrayOfPrimitives)& Lines, - const Handle(Graphic3d_ArrayOfPrimitives)& ArrowLines, - const Handle(Graphic3d_ArrayOfPrimitives)& Triangles) const + const Standard_Real theLength, + const Standard_Real theMaxLength, + const TColgp_Array1OfPnt& theArrowPoints, + const Handle(Graphic3d_ArrayOfPrimitives)& theLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theArrowLines, + const Handle(Graphic3d_ArrayOfPrimitives)& theTriangles) const { const int PntNum = 8; - const Standard_Real aMinLength = MaxLength * ( 1 - mySimpleStartPrm ); - const Standard_Real aLocalLength = ( !myIsSimplePrs || Length > aMinLength ? Length : aMinLength ); + const Standard_Real aMinLength = theMaxLength * ( 1 - mySimpleStartPrm ); + const Standard_Real aLocalLength = ( !myIsSimplePrs || theLength > aMinLength ? theLength : aMinLength ); // draw line gp_Pnt aLinePnt[ 2 ] = { gp_Pnt( 0, 0, 0 ) , gp_Pnt( 0, 0, aLocalLength ) }; - theTrsf.Transforms( aLinePnt[ 0 ].ChangeCoord() ); - theTrsf.Transforms( aLinePnt[ 1 ].ChangeCoord() ); + theTrsf.Transforms (aLinePnt[0].ChangeCoord()); + theTrsf.Transforms (aLinePnt[1].ChangeCoord()); - Lines->AddBound( 2 ); - Lines->AddVertex( aLinePnt[ 0 ] ); - Lines->AddVertex( aLinePnt[ 1 ] ); + theLines->AddVertex (aLinePnt[0]); + theLines->AddVertex (aLinePnt[1]); // draw arrow - if ( !myIsSimplePrs ) + if (!myIsSimplePrs) { - Standard_Integer l = ArrowPoints.Lower(), - u = ArrowPoints.Upper(), - i; - if ( u-l < PntNum-1 ) + Standard_Integer aLower = theArrowPoints.Lower(), + aUpper = theArrowPoints.Upper(); + + if (aUpper - aLower < PntNum - 1) return; - TColgp_Array1OfPnt anArrowPnt( l, u ); - for ( i = l; i < l+PntNum; i++ ) + TColgp_Array1OfPnt anArrowPnt (aLower, aUpper); + for (Standard_Integer aPntIdx = aLower; aPntIdx < aLower + PntNum; ++aPntIdx) { - anArrowPnt( i ).ChangeCoord() = ArrowPoints ( i ).Coord() + gp_XYZ( 0, 0, aLocalLength ); - theTrsf.Transforms( anArrowPnt( i ).ChangeCoord() ); + anArrowPnt (aPntIdx).ChangeCoord() = theArrowPoints (aPntIdx).Coord() + gp_XYZ (0, 0, aLocalLength); + theTrsf.Transforms (anArrowPnt (aPntIdx).ChangeCoord()); } - Triangles->AddBound(8); - for ( i = 0; i < PntNum; i++ ) - Triangles->AddVertex( anArrowPnt( l+i ) ); + const Standard_Integer aVrtOffset = theTriangles->VertexNumber() + 1; + + for (Standard_Integer aPntIdx = 0; aPntIdx < PntNum; ++aPntIdx) + { + theTriangles->AddVertex (anArrowPnt (aLower + aPntIdx)); + } + + for (Standard_Integer aPntIdx = 1; aPntIdx <= PntNum - 2; ++aPntIdx) + { + theTriangles->AddEdge (aVrtOffset); + theTriangles->AddEdge (aVrtOffset + aPntIdx); + + theTriangles->AddEdge (aVrtOffset + aPntIdx); + theTriangles->AddEdge (aVrtOffset + aPntIdx + 1); + } } else { - const Standard_Real aEndPos = aLocalLength - MaxLength * ( 1 - mySimpleEndPrm ); - const Standard_Real aArrowLength = MaxLength * ( mySimpleEndPrm - mySimpleStartPrm ); + const Standard_Real aEndPos = aLocalLength - theMaxLength * ( 1 - mySimpleEndPrm ); + const Standard_Real aArrowLength = theMaxLength * ( mySimpleEndPrm - mySimpleStartPrm ); gp_Pnt aArrowPnt[ 2 ] = { gp_Pnt( 0, 0, aEndPos - aArrowLength ), gp_Pnt( 0, 0, aEndPos ) }; - theTrsf.Transforms( aArrowPnt[ 0 ].ChangeCoord() ); - theTrsf.Transforms( aArrowPnt[ 1 ].ChangeCoord() ); + theTrsf.Transforms (aArrowPnt[0].ChangeCoord()); + theTrsf.Transforms (aArrowPnt[1].ChangeCoord()); - ArrowLines->AddBound( 2 ); - ArrowLines->AddVertex( aArrowPnt[ 0 ] ); - ArrowLines->AddVertex( aArrowPnt[ 1 ] ); + theArrowLines->AddVertex (aArrowPnt[0]); + theArrowLines->AddVertex (aArrowPnt[1]); } } -- 2.20.1