implement correct vertex normals
- use mesh vertices uv value to get correct normals from face - remove unused normal and shading options for parts
This commit is contained in:
parent
d29d62b4ab
commit
d5ee7a6efe
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>610</width>
|
||||
<width>525</width>
|
||||
<height>339</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -53,26 +53,7 @@
|
|||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="Gui::PrefCheckBox" name="prefCheckBox8">
|
||||
<property name="toolTip">
|
||||
<string>Defines the appearance of surfaces</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Do not define normal per vertex</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>NoPerVertexNormals</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Part</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="2" colspan="2">
|
||||
<item row="0" column="0" rowspan="2" colspan="2">
|
||||
<widget class="QLabel" name="textLabel1">
|
||||
<property name="toolTip">
|
||||
<string>Defines the deviation of tessellation to the actual surface</string>
|
||||
|
@ -85,21 +66,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="textLabel1_3_3_2">
|
||||
<property name="text">
|
||||
<string>View smoothing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="1" column="2">
|
||||
<widget class="Gui::PrefDoubleSpinBox" name="maxDeviation">
|
||||
<property name="suffix">
|
||||
<string> %</string>
|
||||
|
@ -127,70 +94,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<widget class="Gui::PrefCheckBox" name="prefCheckBox3">
|
||||
<property name="toolTip">
|
||||
<string>This will slow down render speed but will lead to nicer results</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Using high-quality normals</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>QualityNormals</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Part</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2" colspan="2">
|
||||
<widget class="Line" name="line2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::HLine</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="textLabel1_3">
|
||||
<property name="text">
|
||||
<string>View accuracy / Performance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="Line" name="line2_2_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::HLine</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -200,11 +103,6 @@
|
|||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
|
|
|
@ -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<App::Document*> docs = App::GetApplication().getDocuments();
|
||||
|
@ -87,8 +85,6 @@ void DlgSettings3DViewPart::saveSettings()
|
|||
void DlgSettings3DViewPart::loadSettings()
|
||||
{
|
||||
ui->maxDeviation->onRestore();
|
||||
ui->prefCheckBox8->onRestore();
|
||||
ui->prefCheckBox3->onRestore();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
# include <BRepTools.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <GeomLib.hxx>
|
||||
# include <GeomAbs_CurveType.hxx>
|
||||
# include <GeomAbs_SurfaceType.hxx>
|
||||
# include <Geom_BezierCurve.hxx>
|
||||
|
@ -47,6 +48,7 @@
|
|||
# include <Handle_Poly_Triangulation.hxx>
|
||||
# include <Poly_Array1OfTriangle.hxx>
|
||||
# include <Poly_Triangulation.hxx>
|
||||
# include <Poly_Connect.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# include <TColgp_Array1OfPnt.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
|
@ -61,7 +63,13 @@
|
|||
# include <TopTools_IndexedMapOfShape.hxx>
|
||||
# include <Poly_PolygonOnTriangulation.hxx>
|
||||
# include <TColStd_Array1OfInteger.hxx>
|
||||
# include <TColgp_Array1OfDir.hxx>
|
||||
# include <TColgp_Array1OfPnt2d.hxx>
|
||||
# include <TopTools_ListOfShape.hxx>
|
||||
# include <TShort_Array1OfShortReal.hxx>
|
||||
# include <TShort_HArray1OfShortReal.hxx>
|
||||
# include <Precision.hxx>
|
||||
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/details/SoFaceDetail.h>
|
||||
# include <Inventor/details/SoLineDetail.h>
|
||||
|
@ -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()));
|
||||
|
|
Loading…
Reference in New Issue
Block a user