1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-07-10 12:25:50 +03:00

0028945: Visualization - StdPrs_ToolTriangulatedShape::ComputeNormals() is extremely slow for triangulation-only surface

StdPrs_ToolTriangulatedShape::ComputeNormals() now calls Poly::ComputeNormals() for triangulation-only surfaces.
Poly::ComputeNormals() now averages normal considering triangle size.
This commit is contained in:
kgv 2017-07-25 15:49:53 +03:00 committed by bugmaster
parent 1f9eb89082
commit dc2cc1350e
2 changed files with 69 additions and 61 deletions

View File

@ -445,69 +445,72 @@ Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
//function : ComputeNormals //function : ComputeNormals
//purpose : //purpose :
//======================================================================= //=======================================================================
void Poly::ComputeNormals (const Handle(Poly_Triangulation)& theTri)
void Poly::ComputeNormals(const Handle(Poly_Triangulation)& Tri)
{ {
const TColgp_Array1OfPnt& arrNodes = Tri->Nodes(); const TColgp_Array1OfPnt& aNodes = theTri->Nodes();
const Poly_Array1OfTriangle & arrTri = Tri->Triangles(); const Standard_Integer aNbNodes = aNodes.Size();
Standard_Integer nbNormVal = Tri->NbNodes() * 3;
const Handle(TShort_HArray1OfShortReal) Normals =
new TShort_HArray1OfShortReal(1, nbNormVal);
Normals->Init(0.F);
Standard_ShortReal * arrNormal = &(Normals->ChangeValue(1)); const Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aNbNodes * 3);
aNormals->Init (0.0f);
Standard_ShortReal* aNormArr = &aNormals->ChangeFirst();
Standard_Real aCoord[3]; Standard_Integer anElem[3] = {0, 0, 0};
Standard_Integer iNode[3] = {0, 0, 0}; const Standard_Real anEps2 = gp::Resolution();
Standard_Integer iN, iTri; for (Poly_Array1OfTriangle::Iterator aTriIter (theTri->Triangles()); aTriIter.More(); aTriIter.Next())
const Standard_Real eps2 = gp::Resolution(); {
aTriIter.Value().Get (anElem[0], anElem[1], anElem[2]);
const gp_Pnt& aNode0 = aNodes.Value (anElem[0]);
const gp_Pnt& aNode1 = aNodes.Value (anElem[1]);
const gp_Pnt& aNode2 = aNodes.Value (anElem[2]);
for (iTri = 1; iTri <= arrTri.Length(); iTri++) { const gp_XYZ aVec01 = aNode1.XYZ() - aNode0.XYZ();
// Get the nodes of the current triangle const gp_XYZ aVec02 = aNode2.XYZ() - aNode0.XYZ();
arrTri(iTri).Get (iNode[0], iNode[1], iNode[2]); gp_XYZ aTriNorm = aVec01 ^ aVec02;
const gp_XYZ aVec[2] = { /*if (theToIgnoreTriangleSize)
arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ(), {
arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ() const Standard_Real aMod = aTriNorm.SquareModulus();
}; if (aMod > anEps2)
{
aTriNorm /= Sqrt (aMod);
}
else
{
continue;
}
}*/
// Find the normal vector of the current triangle for (Standard_Integer aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
gp_XYZ aNorm = aVec[0] ^ aVec[1]; {
const Standard_Real aMod = aNorm.SquareModulus(); const Standard_Size anIndex = (anElem[aNodeIter] - 1) * 3;
if (aMod > eps2) { aNormArr[anIndex + 0] += Standard_ShortReal(aTriNorm.X());
aNorm /= sqrt(aMod); aNormArr[anIndex + 1] += Standard_ShortReal(aTriNorm.Y());
aNorm.Coord (aCoord[0], aCoord[1], aCoord[2]); aNormArr[anIndex + 2] += Standard_ShortReal(aTriNorm.Z());
iNode[0] = (iNode[0]-1)*3;
iNode[1] = (iNode[1]-1)*3;
iNode[2] = (iNode[2]-1)*3;
arrNormal[iNode[0]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[0]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[0]+2] += (Standard_ShortReal)aCoord[2];
arrNormal[iNode[1]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[1]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[1]+2] += (Standard_ShortReal)aCoord[2];
arrNormal[iNode[2]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[2]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[2]+2] += (Standard_ShortReal)aCoord[2];
} }
} }
// Normalize all vectors // Normalize all vectors
for (iN = 0; iN < nbNormVal; iN+=3) { gp_XYZ aNormXYZ;
Standard_Real aMod (arrNormal[iN+0]*arrNormal[iN+0] + for (Standard_Integer aNodeIter = 0; aNodeIter < aNbNodes; ++aNodeIter)
arrNormal[iN+1]*arrNormal[iN+1] + {
arrNormal[iN+2]*arrNormal[iN+2]); const Standard_Size anIndex = aNodeIter * 3;
if (aMod < eps2) { aNormXYZ.SetCoord (aNormArr[anIndex + 0], aNormArr[anIndex + 1], aNormArr[anIndex + 2]);
arrNormal[iN+0] = 0.f; const Standard_Real aMod2 = aNormXYZ.SquareModulus();
arrNormal[iN+1] = 0.f; if (aMod2 < anEps2)
arrNormal[iN+2] = 1.f; {
} else { aNormArr[anIndex + 0] = 0.0f;
aMod = sqrt(aMod); aNormArr[anIndex + 1] = 0.0f;
arrNormal[iN+0] = Standard_ShortReal(arrNormal[iN+0]/aMod); aNormArr[anIndex + 2] = 1.0f;
arrNormal[iN+1] = Standard_ShortReal(arrNormal[iN+1]/aMod); }
arrNormal[iN+2] = Standard_ShortReal(arrNormal[iN+2]/aMod); else
{
aNormXYZ /= Sqrt (aMod2);
aNormArr[anIndex + 0] = Standard_ShortReal(aNormXYZ.X());
aNormArr[anIndex + 1] = Standard_ShortReal(aNormXYZ.Y());
aNormArr[anIndex + 2] = Standard_ShortReal(aNormXYZ.Z());
} }
} }
Tri->SetNormals(Normals); theTri->SetNormals (aNormals);
} }
//======================================================================= //=======================================================================

View File

@ -23,6 +23,7 @@
#include <GeomAbs_SurfaceType.hxx> #include <GeomAbs_SurfaceType.hxx>
#include <GeomLib.hxx> #include <GeomLib.hxx>
#include <gp_XYZ.hxx> #include <gp_XYZ.hxx>
#include <Poly.hxx>
#include <Poly_Connect.hxx> #include <Poly_Connect.hxx>
#include <Poly_Triangulation.hxx> #include <Poly_Triangulation.hxx>
#include <Precision.hxx> #include <Precision.hxx>
@ -145,22 +146,26 @@ void StdPrs_ToolTriangulatedShape::ComputeNormals (const TopoDS_Face& theFace,
} }
// take in face the surface location // take in face the surface location
const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location())); const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace); Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
const Standard_Real aTol = Precision::Confusion();
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, theTris->NbNodes() * 3);
const Poly_Array1OfTriangle& aTriangles = theTris->Triangles(); const Poly_Array1OfTriangle& aTriangles = theTris->Triangles();
const TColgp_Array1OfPnt2d* aNodesUV = theTris->HasUVNodes() && !aSurf.IsNull() if (!theTris->HasUVNodes() || aSurf.IsNull())
? &theTris->UVNodes() {
: NULL; // compute normals by averaging triangulation normals sharing the same vertex
Poly::ComputeNormals (theTris);
return;
}
const Standard_Real aTol = Precision::Confusion();
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, theTris->NbNodes() * 3);
const TColgp_Array1OfPnt2d& aNodesUV = theTris->UVNodes();
Standard_Integer aTri[3]; Standard_Integer aTri[3];
const TColgp_Array1OfPnt& aNodes = theTris->Nodes(); const TColgp_Array1OfPnt& aNodes = theTris->Nodes();
gp_Dir aNorm; gp_Dir aNorm;
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
{ {
// try to retrieve normal from real surface first, when UV coordinates are available // try to retrieve normal from real surface first, when UV coordinates are available
if (aNodesUV == NULL if (GeomLib::NormEstim (aSurf, aNodesUV.Value (aNodeIter), aTol, aNorm) > 1)
|| GeomLib::NormEstim (aSurf, aNodesUV->Value (aNodeIter), aTol, aNorm) > 1)
{ {
if (thePolyConnect.Triangulation() != theTris) if (thePolyConnect.Triangulation() != theTris)
{ {