diff --git a/src/Mod/Part/Gui/DlgSettings3DViewPart.ui b/src/Mod/Part/Gui/DlgSettings3DViewPart.ui index d4389d290..8b8a4c652 100644 --- a/src/Mod/Part/Gui/DlgSettings3DViewPart.ui +++ b/src/Mod/Part/Gui/DlgSettings3DViewPart.ui @@ -6,7 +6,7 @@ 0 0 - 610 + 525 339 @@ -53,26 +53,7 @@ 6 - - - - Defines the appearance of surfaces - - - <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Flat shading/Phong shading</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">With flat shading the surface normals are not defined per vertex that leads to a unreal appearance for curved surfaces while using Phong shading leads to a smoother appearance. </p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this option is unset Phong shading is used, if it is set flat shading is used.</p></body></html> - - - Do not define normal per vertex - - - NoPerVertexNormals - - - Mod/Part - - - - + Defines the deviation of tessellation to the actual surface @@ -85,21 +66,7 @@ - - - - <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Hint</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;">Defining the normals per vertex is also called <span style=" font-style:italic;">Phong shading</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-style:italic;"><span style=" font-style:normal;">while defining the normals per face is called </span>Flat shading<span style=" font-style:normal;">.</span></p></body></html> - - - - - - - View smoothing - - - - + % @@ -127,70 +94,6 @@ - - - - This will slow down render speed but will lead to nicer results - - - <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">High-quality normals</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This will slow down render speed but will lead to nicer results.</p></body></html> - - - Using high-quality normals - - - QualityNormals - - - Mod/Part - - - - - - - - 0 - 0 - - - - QFrame::HLine - - - QFrame::Sunken - - - Qt::Horizontal - - - - - - - View accuracy / Performance - - - - - - - - 0 - 0 - - - - QFrame::HLine - - - QFrame::Sunken - - - Qt::Horizontal - - - @@ -200,11 +103,6 @@ - - Gui::PrefCheckBox - QCheckBox -
Gui/PrefWidgets.h
-
Gui::PrefDoubleSpinBox QDoubleSpinBox diff --git a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp index 98b84f1db..846775ce3 100644 --- a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp +++ b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp @@ -70,8 +70,6 @@ void DlgSettings3DViewPart::on_maxDeviation_valueChanged(double v) void DlgSettings3DViewPart::saveSettings() { ui->maxDeviation->onSave(); - ui->prefCheckBox8->onSave(); - ui->prefCheckBox3->onSave(); // search for Part view providers and apply the new settings std::vector docs = App::GetApplication().getDocuments(); @@ -87,8 +85,6 @@ void DlgSettings3DViewPart::saveSettings() void DlgSettings3DViewPart::loadSettings() { ui->maxDeviation->onRestore(); - ui->prefCheckBox8->onRestore(); - ui->prefCheckBox3->onRestore(); } /** diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index ead6e02ca..02ad4c645 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -35,6 +35,7 @@ # include # include # include +# include # include # include # include @@ -47,6 +48,7 @@ # include # include # include +# include # include # include # include @@ -61,7 +63,13 @@ # include # include # include +# include +# include # include +# include +# include +# include + # include # include # include @@ -119,6 +127,94 @@ using namespace PartGui; PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject) +void GetNormals(const TopoDS_Face& theFace, + const Handle(Poly_Triangulation)& aPolyTri, + TColgp_Array1OfDir& theNormals) +{ + Poly_Connect thePolyConnect(aPolyTri); + const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); + + if(aPolyTri->HasNormals()) + { + // normals pre-computed in triangulation structure + const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); + const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower())); + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); + const gp_Dir aNorm(aNormArr[anId + 0], + aNormArr[anId + 1], + aNormArr[anId + 2]); + theNormals(aNodeIter) = aNorm; + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + + return; + } + + // take in face the surface location + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3); + const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); + const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() + ? &aPolyTri->UVNodes() + : NULL; + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if(aNodesUV == NULL + || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord()); + const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; + aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X()); + aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y()); + aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z()); + } + + aPolyTri->SetNormals(aNormals); + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } +} + //************************************************************************** // Construction/Destruction @@ -765,6 +861,9 @@ void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape) // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); + TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); + GetNormals(actFace, mesh, Normals); + for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; @@ -780,22 +879,23 @@ void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape) // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); - // transform the vertices to the place of the face - if (!identity) { + // get the 3 normals of this triangle + gp_Dir NV1(Normals(N1)), NV2(Normals(N2)), NV3(Normals(N3)); + + // transform the vertices and normals to the place of the face + if(!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); + NV1.Transform(myTransf); + NV2.Transform(myTransf); + NV3.Transform(myTransf); } - - // calculating per vertex normals - // Calculate triangle normal - gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); - gp_Vec Normal = (v2-v1)^(v3-v1); - // add the triangle normal to the vertex normal for all points of this triangle - norms[faceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[faceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); - norms[faceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); + // add the normals for all points of this triangle + norms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z()); + norms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z()); + norms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z()); // set the vertices verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));