+ Improve mesh selection (precompute projection matrix and use polygon bounding box)

This commit is contained in:
wmayer
2018-07-25 18:00:42 +02:00
parent 1fcfbcf1ab
commit 65879dfe63
2 changed files with 59 additions and 32 deletions

View File

@@ -51,6 +51,7 @@ Base::Vector3f ViewVolumeProjection::operator()(const Base::Vector3f &pt) const
pt3d.setValue(ptt.x, ptt.y, ptt.z);
}
// Calling this function is expensive as the complete projection matrix is recomputed on each step
viewVolume.projectToScreen(pt3d,pt3d);
return Base::Vector3f(pt3d[0],pt3d[1],pt3d[2]);
}
@@ -101,12 +102,26 @@ Base::Matrix4D ViewVolumeProjection::getProjectionMatrix () const
// Inventor stores the transposed matrix
Base::Matrix4D mat;
SbMatrix affine, proj;
// The Inventor projection matrix is obtained by multiplying both matrices together (cf source)
viewVolume.getMatrices(affine, proj);
SbMatrix pmatrix = affine.multRight(proj);
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++)
mat[i][j] = proj[j][i];
mat[i][j] = pmatrix[j][i];
}
// Compose the object transform, if defined
if (hasTransform) {
mat = mat * transform;
}
// Scale from [-1,1] to [0,1]
// As done in OpenInventor sources (see SbDPViewVolume::projectToScreen)
mat.scale(0.5, 0.5, 0.5);
mat.move(0.5, 0.5, 0.5);
return mat;
}

View File

@@ -1083,23 +1083,24 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, const Base::ViewPr
Base::Vector3f clPt2d;
Base::Vector3f clGravityOfFacet;
bool bNoPointInside;
// Cache current view projection matrix since calls to COIN's projection are expensive
Base::ViewProjMatrix fixedProj(pclProj->getProjectionMatrix());
// Precompute the polygon's bounding box
Base::BoundBox2d clPolyBBox = rclPoly.CalcBoundBox();
// Falls true, verwende Grid auf Mesh, um Suche zu beschleunigen
if (bInner)
{
BoundBox3f clBBox3d;
BoundBox2d clViewBBox, clPolyBBox;
BoundBox2d clViewBBox;
std::vector<unsigned long> aulAllElements;
//B-Box des Polygons
clPolyBBox = rclPoly.CalcBoundBox();
// Iterator fuer die zu durchsuchenden B-Boxen des Grids
MeshGridIterator clGridIter(rclGrid);
// alle B-Boxen durchlaufen und die Facets speichern
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next())
{
clBBox3d = clGridIter.GetBoundBox();
clViewBBox = clBBox3d.ProjectBox(pclProj);
clViewBBox = clBBox3d.ProjectBox(&fixedProj);
if (clViewBBox.Intersect(clPolyBBox))
{
// alle Elemente in AllElements sammeln
@@ -1119,9 +1120,10 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, const Base::ViewPr
MeshGeomFacet rclFacet = _rclMesh.GetFacet(*it);
for (int j=0; j<3; j++)
{
clPt2d = pclProj->operator()(rclFacet._aclPoints[j]);
clPt2d = fixedProj(rclFacet._aclPoints[j]);
clGravityOfFacet += clPt2d;
if (rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) == bInner)
if ((clPolyBBox.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) &&
rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y))) ^ !bInner)
{
raulFacets.push_back(*it);
bNoPointInside = false;
@@ -1134,8 +1136,9 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, const Base::ViewPr
{
clGravityOfFacet *= 1.0f/3.0f;
if (rclPoly.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y)) == bInner)
raulFacets.push_back(*it);
if ((clPolyBBox.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y)) &&
rclPoly.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y))) ^ !bInner)
raulFacets.push_back(*it);
}
seq.next();
@@ -1144,20 +1147,21 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, const Base::ViewPr
// Dreiecke ausserhalb schneiden, dann alles durchsuchen
else
{
Base::SequencerLauncher seq("Check facets", _rclMesh.CountFacets());
for (clIter.Init(); clIter.More(); clIter.Next())
{
for (int j=0; j<3; j++)
{
clPt2d = pclProj->operator()(clIter->_aclPoints[j]);
if (rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) == bInner)
{
raulFacets.push_back(clIter.Position());
break;
}
}
seq.next();
}
Base::SequencerLauncher seq("Check facets", _rclMesh.CountFacets());
for (clIter.Init(); clIter.More(); clIter.Next())
{
for (int j=0; j<3; j++)
{
clPt2d = fixedProj(clIter->_aclPoints[j]);
if ((clPolyBBox.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) &&
rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y))) ^ !bInner)
{
raulFacets.push_back(clIter.Position());
break;
}
}
seq.next();
}
}
}
@@ -1167,11 +1171,19 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base:
const MeshPointArray& p = _rclMesh.GetPoints();
const MeshFacetArray& f = _rclMesh.GetFacets();
Base::Vector3f pt2d;
// Use a bounding box to reduce number of call to Polygon::Contains
Base::BoundBox2d bb = rclPoly.CalcBoundBox();
// Precompute the screen projection matrix as COIN's projection function is expensive
Base::Matrix4D pmat = pclProj->getProjectionMatrix();
unsigned long index=0;
for (MeshFacetArray::_TConstIterator it = f.begin(); it != f.end(); ++it,++index) {
for (int i = 0; i < 3; i++) {
pt2d = (*pclProj)(p[it->_aulPoints[i]]);
if (rclPoly.Contains(Base::Vector2d(pt2d.x, pt2d.y)) == bInner) {
pt2d = pmat * p[it->_aulPoints[i]];
// First check whether the point is in the bounding box of the polygon
if ((bb.Contains(Base::Vector2d(pt2d.x, pt2d.y)) &&
rclPoly.Contains(Base::Vector2d(pt2d.x, pt2d.y))) ^ !bInner) {
raulFacets.push_back(index);
break;
}
@@ -1181,13 +1193,13 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base:
float MeshAlgorithm::Surface (void) const
{
float fTotal = 0.0f;
MeshFacetIterator clFIter(_rclMesh);
float fTotal = 0.0f;
MeshFacetIterator clFIter(_rclMesh);
for (clFIter.Init(); clFIter.More(); clFIter.Next())
fTotal += clFIter->Area();
return fTotal;
for (clFIter.Init(); clFIter.More(); clFIter.Next())
fTotal += clFIter->Area();
return fTotal;
}
void MeshAlgorithm::SubSampleByDist (float fDist, std::vector<Base::Vector3f> &rclPoints) const