1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-05 18:16:23 +03:00

0030854: Visualization, AIS_ViewCube - pack triangulations into common array(s)

Presentation computation has been modified to merge triangulations per box part type.
Prs3d_Drawer::FaceBoundaryDraw() flag is now handled for drawing box sides edges.

Graphic3d_ArrayOfPrimitives has been extended by auxiliary methods:
- ::AddSegmentEdges(), ::AddTriangleEdges(), ::AddQuadEdges() raising exception on wrong primitive type.
- ::AddQuadTriangleEdges() splitting quad into indexed triangulation;
- ::AddTriangleStripEdges() splitting triangle strip into indexed triangulation;
- ::AddTriangleFanEdges() splitting triangle fan into indexed triangulation;
- ::AddPolylineEdges() splitting polyline into indexed segments.
This commit is contained in:
kgv 2019-08-05 20:26:11 +03:00 committed by bugmaster
parent 6f5db50804
commit caa309aaf4
5 changed files with 513 additions and 161 deletions

View File

@ -346,98 +346,107 @@ void AIS_ViewCube::SetRoundRadius (const Standard_Real theValue)
//function : createRoundRectangleTriangles
//purpose :
//=======================================================================
Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createRoundRectangleTriangles (const gp_XY& theSize,
Standard_Real theRadius,
const gp_Trsf& theTrsf)
void AIS_ViewCube::createRoundRectangleTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
const gp_XY& theSize,
Standard_Real theRadius,
const gp_Trsf& theTrsf)
{
const Standard_Real aRadius = Min (theRadius, Min (theSize.X(), theSize.Y()) * 0.5);
const gp_XY aHSize (theSize.X() * 0.5 - aRadius, theSize.Y() * 0.5 - aRadius);
const gp_Dir aNorm = gp::DZ().Transformed (theTrsf);
Handle(Graphic3d_ArrayOfTriangles) aTris;
const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0;
if (aRadius > 0.0)
{
const Standard_Integer aNbNodes = (THE_NB_ROUND_SPLITS + 1) * 4 + 1;
aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbNodes * 3, Graphic3d_ArrayFlags_VertexNormal);
theNbNodes += aNbNodes;
theNbTris += aNbNodes;
if (theTris.IsNull())
{
return;
}
aTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (theTrsf));
for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
{
const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (M_PI * 0.5, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
aTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
}
for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
{
const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (0.0, -M_PI * 0.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
aTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
}
for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
{
const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI * 0.5, -M_PI, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
aTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
}
for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
{
const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI, -M_PI * 1.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
aTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
}
// split triangle fan
for (Standard_Integer aNodeIter = 2; aNodeIter <= aTris->VertexNumber(); ++aNodeIter)
{
aTris->AddEdge (1);
aTris->AddEdge (aNodeIter - 1);
aTris->AddEdge (aNodeIter);
}
aTris->AddEdge (1);
aTris->AddEdge (aTris->VertexNumber());
aTris->AddEdge (2);
theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true);
}
else
{
aTris = new Graphic3d_ArrayOfTriangles (4, 6, Graphic3d_ArrayFlags_VertexNormal);
aTris->AddVertex (gp_Pnt (-aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
aTris->AddVertex (gp_Pnt (-aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
aTris->AddVertex (gp_Pnt ( aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
aTris->AddVertex (gp_Pnt ( aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
aTris->AddEdges (3, 1, 2);
aTris->AddEdges (1, 3, 4);
theNbNodes += 4;
theNbTris += 2;
if (theTris.IsNull())
{
return;
}
theTris->AddVertex (gp_Pnt (-aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt (-aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt ( aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
theTris->AddVertex (gp_Pnt ( aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
theTris->AddQuadTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3, aVertFirst + 4);
}
for (Standard_Integer aVertIter = 1; aVertIter <= aTris->VertexNumber(); ++aVertIter)
for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter)
{
aTris->SetVertexNormal (aVertIter, -aNorm);
theTris->SetVertexNormal (aVertIter, -aNorm);
}
return aTris;
}
//=======================================================================
//function : createBoxPartTriangles
//purpose :
//=======================================================================
Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxPartTriangles (V3d_TypeOfOrientation theDir) const
void AIS_ViewCube::createBoxPartTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const
{
if (IsBoxSide (theDir))
{
return createBoxSideTriangles (theDir);
createBoxSideTriangles (theTris, theNbNodes, theNbTris, theDir);
}
else if (IsBoxEdge (theDir)
&& myToDisplayEdges)
{
return createBoxEdgeTriangles (theDir);
createBoxEdgeTriangles (theTris, theNbNodes, theNbTris, theDir);
}
else if (IsBoxCorner (theDir)
&& myToDisplayVertices)
{
return createBoxCornerTriangles (theDir);
createBoxCornerTriangles (theTris, theNbNodes, theNbTris, theDir);
}
return Handle(Graphic3d_ArrayOfTriangles)();
}
//=======================================================================
//function : createBoxSideTriangles
//purpose :
//=======================================================================
Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxSideTriangles (V3d_TypeOfOrientation theDirection) const
void AIS_ViewCube::createBoxSideTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDirection) const
{
const gp_Dir aDir = V3d::GetProjAxis (theDirection);
const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension);
@ -447,14 +456,18 @@ Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxSideTriangles (V3d_Typ
gp_Trsf aTrsf;
aTrsf.SetTransformation (aSystem, gp_Ax3());
return createRoundRectangleTriangles (gp_XY (mySize, mySize), myRoundRadius * mySize, aTrsf);
createRoundRectangleTriangles (theTris, theNbNodes, theNbTris,
gp_XY (mySize, mySize), myRoundRadius * mySize, aTrsf);
}
//=======================================================================
//function : createBoxEdgeTriangles
//purpose :
//=======================================================================
Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxEdgeTriangles (V3d_TypeOfOrientation theDirection) const
void AIS_ViewCube::createBoxEdgeTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDirection) const
{
const Standard_Real aThickness = Max (myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() - myBoxEdgeGap, myBoxEdgeMinSize);
@ -466,20 +479,32 @@ Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxEdgeTriangles (V3d_Typ
gp_Trsf aTrsf;
aTrsf.SetTransformation (aSystem, gp_Ax3());
return createRoundRectangleTriangles (gp_XY (aThickness, mySize), myRoundRadius * mySize, aTrsf);
createRoundRectangleTriangles (theTris, theNbNodes, theNbTris,
gp_XY (aThickness, mySize), myRoundRadius * mySize, aTrsf);
}
//=======================================================================
//function : createBoxCornerTriangles
//purpose :
//=======================================================================
Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxCornerTriangles (V3d_TypeOfOrientation theDir) const
void AIS_ViewCube::createBoxCornerTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const
{
const Standard_Real aHSize = mySize * 0.5;
const gp_Dir aDir = V3d::GetProjAxis (theDir);
const gp_XYZ aHSizeDir = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude());
const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0;
if (myRoundRadius > 0.0)
{
theNbNodes += THE_NB_DISK_SLICES + 1;
theNbTris += THE_NB_DISK_SLICES + 1;
if (theTris.IsNull())
{
return;
}
const Standard_Real anEdgeHWidth = myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() * 0.5;
const Standard_Real aHeight = anEdgeHWidth * Sqrt (2.0 / 3.0); // tetrahedron height
const gp_Pnt aPos = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude() + aHeight);
@ -488,33 +513,46 @@ Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxCornerTriangles (V3d_T
gp_Trsf aTrsf;
aTrsf.SetTransformation (aSystem, gp_Ax3());
const Standard_Real aRadius = Max (myBoxFacetExtension * 0.5 / Cos (M_PI_4), myCornerMinSize);
return Prs3d_ToolDisk::Create (0.0, aRadius, THE_NB_DISK_SLICES, 1, aTrsf);
}
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (3, 3, Graphic3d_ArrayFlags_VertexNormal);
aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (aDir.X(), 0.0, 0.0).XYZ());
aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, aDir.Y(), 0.0).XYZ());
aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, 0.0, aDir.Z()).XYZ());
const gp_XYZ aNode1 = aTris->Vertice (1).XYZ();
const gp_XYZ aNode2 = aTris->Vertice (2).XYZ();
const gp_XYZ aNode3 = aTris->Vertice (3).XYZ();
const gp_XYZ aNormTri = ((aNode2 - aNode1).Crossed (aNode3 - aNode1));
if (aNormTri.Dot (aDir.XYZ()) < 0.0)
{
aTris->AddEdges (1, 3, 2);
theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (aTrsf));
for (Standard_Integer aNodeIter = 0; aNodeIter < THE_NB_DISK_SLICES; ++aNodeIter)
{
const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (2.0 * M_PI, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_DISK_SLICES));
theTris->AddVertex (gp_Pnt (aRadius * Cos (anAngle), aRadius * Sin (anAngle), 0.0).Transformed (aTrsf));
}
theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true);
}
else
{
aTris->AddEdges (1, 2, 3);
theNbNodes += 3;
theNbTris += 1;
if (theTris.IsNull())
{
return;
}
theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (aDir.X(), 0.0, 0.0).XYZ());
theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, aDir.Y(), 0.0).XYZ());
theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, 0.0, aDir.Z()).XYZ());
const gp_XYZ aNode1 = theTris->Vertice (aVertFirst + 1).XYZ();
const gp_XYZ aNode2 = theTris->Vertice (aVertFirst + 2).XYZ();
const gp_XYZ aNode3 = theTris->Vertice (aVertFirst + 3).XYZ();
const gp_XYZ aNormTri = ((aNode2 - aNode1).Crossed (aNode3 - aNode1));
if (aNormTri.Dot (aDir.XYZ()) < 0.0)
{
theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 3, aVertFirst + 2);
}
else
{
theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3);
}
}
for (Standard_Integer aVertIter = 1; aVertIter <= aTris->VertexNumber(); ++aVertIter)
for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter)
{
aTris->SetVertexNormal (aVertIter, aDir);
theTris->SetVertexNormal (aVertIter, aDir);
}
return aTris;
}
//=======================================================================
@ -590,73 +628,144 @@ void AIS_ViewCube::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
}
}
// Display box
// Display box sides
{
Handle(Graphic3d_Group) aGroupSides = thePrs->NewGroup(), aGroupEdges = thePrs->NewGroup(), aGroupCorners = thePrs->NewGroup();
aGroupSides->SetClosed (true); // should be replaced by forced back-face culling aspect
aGroupSides->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
Standard_Integer aNbNodes = 0, aNbTris = 0;
for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
{
createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
}
if (aNbNodes > 0)
{
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
Handle(Graphic3d_ArrayOfSegments) aSegs;
if (myDrawer->FaceBoundaryDraw())
{
aSegs = new Graphic3d_ArrayOfSegments (aNbNodes, aNbNodes * 2, Graphic3d_ArrayFlags_None);
}
aNbNodes = aNbTris = 0;
for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
{
Standard_Integer aTriNodesFrom = aTris->VertexNumber();
const Standard_Integer aTriFrom = aNbTris;
createBoxPartTriangles (aTris, aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
if (aSegs.IsNull())
{
continue;
}
aGroupEdges->SetClosed (true);
aGroupEdges->SetGroupPrimitivesAspect (myBoxEdgeAspect->Aspect());
const Standard_Integer aFirstNode = aSegs->VertexNumber();
for (Standard_Integer aVertIter = (aNbTris - aTriFrom) > 2 ? aTriNodesFrom + 2 : aTriNodesFrom + 1; // skip triangle fan center
aVertIter <= aTris->VertexNumber(); ++aVertIter)
{
aSegs->AddVertex (aTris->Vertice (aVertIter));
}
aSegs->AddPolylineEdges (aFirstNode + 1, aSegs->VertexNumber(), true);
}
aGroupCorners->SetClosed (true);
aGroupCorners->SetGroupPrimitivesAspect (myBoxCornerAspect->Aspect());
{
Handle(Graphic3d_Group) aGroupSides = thePrs->NewGroup();
aGroupSides->SetClosed (true); // should be replaced by forced back-face culling aspect
aGroupSides->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
aGroupSides->AddPrimitiveArray (aTris);
}
if (!aSegs.IsNull())
{
Handle(Graphic3d_Group) aGroupSegs = thePrs->NewGroup();
aGroupSegs->SetGroupPrimitivesAspect (myDrawer->FaceBoundaryAspect()->Aspect());
aGroupSegs->AddPrimitiveArray (aSegs);
}
}
// Display box sides labels
Handle(Graphic3d_Group) aTextGroup = thePrs->NewGroup();
//aTextGroup->SetClosed (true);
aTextGroup->SetGroupPrimitivesAspect (myDrawer->TextAspect()->Aspect());
for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
{
const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (anOrient))
TCollection_AsciiString aLabel;
if (!myBoxSideLabels.Find (anOrient, aLabel)
|| aLabel.IsEmpty())
{
if (IsBoxSide (anOrient))
{
aGroupSides->AddPrimitiveArray (aTris);
continue;
}
TCollection_AsciiString aLabel;
if (!myBoxSideLabels.Find (anOrient, aLabel)
|| aLabel.IsEmpty())
{
continue;
}
const gp_Dir aDir = V3d::GetProjAxis (anOrient);
gp_Dir anUp = myIsYup ? gp::DY() : gp::DZ();
if (myIsYup)
{
if (anOrient == V3d_Ypos
|| anOrient == V3d_Yneg)
{
anUp = -gp::DZ();
}
}
else
{
if (anOrient == V3d_Zpos)
{
anUp = gp::DY();
}
else if (anOrient == V3d_Zneg)
{
anUp = -gp::DY();
}
}
const Standard_Real anOffset = 2.0; // extra offset to avoid overlapping with triangulation
const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension + anOffset);
const gp_Ax2 aPosition (aPos, aDir, anUp.Crossed (aDir));
Prs3d_Text::Draw (aTextGroup, myDrawer->TextAspect(), aLabel, aPosition);
}
else if (IsBoxEdge (anOrient))
const gp_Dir aDir = V3d::GetProjAxis (anOrient);
gp_Dir anUp = myIsYup ? gp::DY() : gp::DZ();
if (myIsYup)
{
if (anOrient == V3d_Ypos
|| anOrient == V3d_Yneg)
{
aGroupEdges->AddPrimitiveArray (aTris);
}
else if (IsBoxCorner (anOrient))
{
aGroupCorners->AddPrimitiveArray (aTris);
anUp = -gp::DZ();
}
}
else
{
if (anOrient == V3d_Zpos)
{
anUp = gp::DY();
}
else if (anOrient == V3d_Zneg)
{
anUp = -gp::DY();
}
}
const Standard_Real anOffset = 2.0; // extra offset to avoid overlapping with triangulation
const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension + anOffset);
const gp_Ax2 aPosition (aPos, aDir, anUp.Crossed (aDir));
Prs3d_Text::Draw (aTextGroup, myDrawer->TextAspect(), aLabel, aPosition);
}
}
// Display box edges
{
Standard_Integer aNbNodes = 0, aNbTris = 0;
for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter)
{
createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
}
if (aNbNodes > 0)
{
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
aNbNodes = aNbTris = 0;
for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter)
{
const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient);
}
Handle(Graphic3d_Group) aGroupEdges = thePrs->NewGroup();
aGroupEdges->SetClosed (true);
aGroupEdges->SetGroupPrimitivesAspect (myBoxEdgeAspect->Aspect());
aGroupEdges->AddPrimitiveArray (aTris);
}
}
// Display box corners
{
Standard_Integer aNbNodes = 0, aNbTris = 0;
for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
{
createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
}
if (aNbNodes > 0)
{
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
aNbNodes = aNbTris = 0;
for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
{
const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient);
}
Handle(Graphic3d_Group) aGroupCorners = thePrs->NewGroup();
aGroupCorners->SetClosed (true);
aGroupCorners->SetGroupPrimitivesAspect (myBoxCornerAspect->Aspect());
aGroupCorners->AddPrimitiveArray (aTris);
}
}
}
@ -676,22 +785,30 @@ void AIS_ViewCube::ComputeSelection (const Handle(SelectMgr_Selection)& theSelec
for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
{
const V3d_TypeOfOrientation anOri = (V3d_TypeOfOrientation )aPartIter;
if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (anOri))
Standard_Integer aNbNodes = 0, aNbTris = 0;
createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, anOri);
if (aNbNodes <= 0)
{
Standard_Integer aSensitivity = 2;
if (IsBoxCorner (anOri))
{
aSensitivity = 8;
}
else if (IsBoxEdge (anOri))
{
aSensitivity = 4;
}
Handle(AIS_ViewCubeOwner) anOwner = new AIS_ViewCubeOwner (this, anOri);
Handle(AIS_ViewCubeSensitive) aTriSens = new AIS_ViewCubeSensitive (anOwner, aTris);
aTriSens->SetSensitivityFactor (aSensitivity);
theSelection->Add (aTriSens);
continue;
}
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None);
aNbNodes = aNbTris = 0;
createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOri);
Standard_Integer aSensitivity = 2;
if (IsBoxCorner (anOri))
{
aSensitivity = 8;
}
else if (IsBoxEdge (anOri))
{
aSensitivity = 4;
}
Handle(AIS_ViewCubeOwner) anOwner = new AIS_ViewCubeOwner (this, anOri);
Handle(AIS_ViewCubeSensitive) aTriSens = new AIS_ViewCubeSensitive (anOwner, aTris);
aTriSens->SetSensitivityFactor (aSensitivity);
theSelection->Add (aTriSens);
}
}
@ -704,6 +821,25 @@ Standard_Boolean AIS_ViewCube::HasAnimation() const
return !myViewAnimation->IsStopped();
}
//=======================================================================
//function : viewFitAll
//purpose :
//=======================================================================
void AIS_ViewCube::viewFitAll (const Handle(V3d_View)& theView,
const Handle(Graphic3d_Camera)& theCamera)
{
Bnd_Box aBndBox = myToFitSelected ? GetContext()->BoundingBoxOfSelection() : theView->View()->MinMaxValues();
if (aBndBox.IsVoid()
&& myToFitSelected)
{
aBndBox = theView->View()->MinMaxValues();
}
if (!aBndBox.IsVoid())
{
theView->FitMinMax (theCamera, aBndBox, 0.01, 10.0 * Precision::Confusion());
}
}
//=======================================================================
//function : StartAnimation
//purpose :
@ -721,25 +857,28 @@ void AIS_ViewCube::StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner)
myEndState ->Copy (aView->Camera());
{
Handle(Graphic3d_Camera) aBackupCamera = new Graphic3d_Camera (aView->Camera());
{
Handle(Graphic3d_Camera) aBackupCamera = aView->Camera();
const bool wasImmediateUpdate = aView->SetImmediateUpdate (false);
aView->SetCamera (myEndState);
aView->SetProj (theOwner->MainOrientation(), myIsYup);
aView->SetCamera (aBackupCamera);
aView->SetImmediateUpdate (wasImmediateUpdate);
}
const bool wasImmediateUpdate = aView->SetImmediateUpdate (false);
aView->SetCamera (myEndState);
aView->SetProj (theOwner->MainOrientation(), myIsYup);
const gp_Dir aNewDir = aView->Camera()->Direction();
const gp_Dir aNewDir = myEndState->Direction();
if (!myToResetCameraUp
&& !aNewDir.IsEqual (aBackupCamera->Direction(), Precision::Angular()))
&& !aNewDir.IsEqual (myStartState->Direction(), Precision::Angular()))
{
// find the Up direction closest to current instead of default one
const gp_Ax1 aNewDirAx1 (gp::Origin(), aNewDir);
const gp_Dir anOldUp = aBackupCamera->Up();
const gp_Dir anOldUp = myStartState->Up();
const gp_Dir anUpList[4] =
{
aView->Camera()->Up(),
aView->Camera()->Up().Rotated (aNewDirAx1, M_PI_2),
aView->Camera()->Up().Rotated (aNewDirAx1, M_PI),
aView->Camera()->Up().Rotated (aNewDirAx1, M_PI * 1.5),
myEndState->Up(),
myEndState->Up().Rotated (aNewDirAx1, M_PI_2),
myEndState->Up().Rotated (aNewDirAx1, M_PI),
myEndState->Up().Rotated (aNewDirAx1, M_PI * 1.5),
};
Standard_Real aBestAngle = Precision::Infinite();
@ -753,20 +892,10 @@ void AIS_ViewCube::StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner)
anUpBest = anUpList[anUpIter];
}
}
aView->Camera()->SetUp (anUpBest);
myEndState->SetUp (anUpBest);
}
const Bnd_Box aBndSelected = myToFitSelected ? GetContext()->BoundingBoxOfSelection() : Bnd_Box();
if (!aBndSelected.IsVoid())
{
aView->FitAll (aBndSelected, 0.01, false);
}
else
{
aView->FitAll (0.01, false);
}
aView->SetCamera (aBackupCamera);
aView->SetImmediateUpdate (wasImmediateUpdate);
viewFitAll (aView, myEndState);
}
myViewAnimation->SetView (aView);
@ -864,8 +993,13 @@ void AIS_ViewCube::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManage
{
Handle(Graphic3d_Group) aGroup = aHiPrs->NewGroup();
aGroup->SetGroupPrimitivesAspect (theStyle->ShadingAspect()->Aspect());
if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (aCubeOwner->MainOrientation()))
Standard_Integer aNbNodes = 0, aNbTris = 0;
createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, aCubeOwner->MainOrientation());
if (aNbNodes > 0)
{
Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None);
aNbNodes = aNbTris = 0;
createBoxPartTriangles (aTris, aNbNodes, aNbTris, aCubeOwner->MainOrientation());
aGroup->AddPrimitiveArray (aTris);
}
}

View File

@ -28,6 +28,7 @@
class AIS_AnimationCamera;
class AIS_ViewCubeOwner;
class Graphic3d_ArrayOfTriangles;
class V3d_View;
//! Interactive object for displaying the view manipulation cube.
//!
@ -466,6 +467,12 @@ protected:
//! @return FALSE if animation has been finished
Standard_EXPORT Standard_Boolean updateAnimation();
//! Fit selected/all into view.
//! @param theView [in] view definition to retrieve scene bounding box
//! @param theCamera [in,out] camera definition
Standard_EXPORT virtual void viewFitAll (const Handle(V3d_View)& theView,
const Handle(Graphic3d_Camera)& theCamera);
protected: //! @name protected virtual API
//! Method that is called after one step of transformation.
@ -536,26 +543,60 @@ public: //! @name Presentation computation
protected: //! @name Auxiliary classes to fill presentation with proper primitives
//! Create triangulation for a box part - for presentation and selection purposes.
Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxPartTriangles (V3d_TypeOfOrientation theDir) const;
//! @param theTris [in,out] triangulation to fill, or NULL to return size
//! @param theNbNodes [in,out] should be incremented by a number of nodes defining this triangulation
//! @param theNbTris [in,out] should be incremented by a number of triangles defining this triangulation
//! @param theDir [in] part to define
Standard_EXPORT virtual void createBoxPartTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const;
//! Create triangulation for a box side.
Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxSideTriangles (V3d_TypeOfOrientation theDir) const;
//! @param theTris [in,out] triangulation to fill, or NULL to return size
//! @param theNbNodes [in,out] should be incremented by a number of nodes defining this triangulation
//! @param theNbTris [in,out] should be incremented by a number of triangles defining this triangulation
//! @param theDir [in] part to define
Standard_EXPORT virtual void createBoxSideTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const;
//! Create triangulation for a box edge.
Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxEdgeTriangles (V3d_TypeOfOrientation theDir) const;
//! @param theTris [in,out] triangulation to fill, or NULL to return size
//! @param theNbNodes [in,out] should be incremented by a number of nodes defining this triangulation
//! @param theNbTris [in,out] should be incremented by a number of triangles defining this triangulation
//! @param theDir [in] part to define
Standard_EXPORT virtual void createBoxEdgeTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const;
//! Create triangulation for a box corner (vertex).
Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxCornerTriangles (V3d_TypeOfOrientation theDir) const;
//! @param theTris [in,out] triangulation to fill, or NULL to return size
//! @param theNbNodes [in,out] should be incremented by a number of nodes defining this triangulation
//! @param theNbTris [in,out] should be incremented by a number of triangles defining this triangulation
//! @param theDir [in] part to define
Standard_EXPORT virtual void createBoxCornerTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
V3d_TypeOfOrientation theDir) const;
protected:
//! Create triangulation for a rectangle with round corners.
//! @param theSize rectangle dimensions
//! @param theRadius radius at corners
//! @param theTrsf transformation
Standard_EXPORT static Handle(Graphic3d_ArrayOfTriangles) createRoundRectangleTriangles (const gp_XY& theSize,
Standard_Real theRadius,
const gp_Trsf& theTrsf);
//! @param theTris [in,out] triangulation to fill, or NULL to return size
//! @param theNbNodes [in,out] should be incremented by a number of nodes defining this triangulation
//! @param theNbTris [in,out] should be incremented by a number of triangles defining this triangulation
//! @param theSize [in] rectangle dimensions
//! @param theRadius [in] radius at corners
//! @param theTrsf [in] transformation
Standard_EXPORT static void createRoundRectangleTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
Standard_Integer& theNbNodes,
Standard_Integer& theNbTris,
const gp_XY& theSize,
Standard_Real theRadius,
const gp_Trsf& theTrsf);
protected:

View File

@ -259,6 +259,79 @@ Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer th
return ++myIndices->NbElements;
}
// =======================================================================
// function : AddTriangleStripEdges
// purpose :
// =======================================================================
void Graphic3d_ArrayOfPrimitives::AddTriangleStripEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper)
{
if (myType != Graphic3d_TOPA_TRIANGLES)
{
throw Standard_TypeMismatch ("Not array of triangles");
}
Standard_Boolean isOdd = Standard_True;
for (Standard_Integer aNodeIter = theVertexLower + 2; aNodeIter <= theVertexUpper; ++aNodeIter)
{
if (isOdd)
{
AddTriangleEdges (aNodeIter - 2, aNodeIter - 1, aNodeIter);
}
else
{
AddTriangleEdges (aNodeIter - 1, aNodeIter - 2, aNodeIter);
}
isOdd = !isOdd;
}
}
// =======================================================================
// function : AddTriangleFanEdges
// purpose :
// =======================================================================
void Graphic3d_ArrayOfPrimitives::AddTriangleFanEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper,
Standard_Boolean theToClose)
{
if (myType != Graphic3d_TOPA_TRIANGLES)
{
throw Standard_TypeMismatch ("Not array of triangles");
}
for (Standard_Integer aNodeIter = theVertexLower + 1; aNodeIter <= theVertexUpper; ++aNodeIter)
{
AddTriangleEdges (theVertexLower, aNodeIter - 1, aNodeIter);
}
if (theToClose)
{
AddTriangleEdges (theVertexLower, theVertexUpper, theVertexLower + 1);
}
}
// =======================================================================
// function : AddPolylineEdges
// purpose :
// =======================================================================
void Graphic3d_ArrayOfPrimitives::AddPolylineEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper,
Standard_Boolean theToClose)
{
if (myType != Graphic3d_TOPA_SEGMENTS)
{
throw Standard_TypeMismatch ("Not array of segments");
}
for (Standard_Integer aNodeIter = theVertexLower; aNodeIter < theVertexUpper; ++aNodeIter)
{
AddSegmentEdges (aNodeIter, aNodeIter + 1);
}
if (theToClose)
{
AddSegmentEdges (theVertexUpper, theVertexLower);
}
}
// =======================================================================
// function : StringType
// purpose :

View File

@ -23,6 +23,7 @@
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <Standard_OutOfRange.hxx>
#include <Standard_TypeMismatch.hxx>
#include <Quantity_Color.hxx>
class Graphic3d_ArrayOfPrimitives;
@ -537,6 +538,16 @@ public: //! @name optional array of Indices/Edges for using shared Vertex data
return AddEdge (theVertexIndex2);
}
//! Convenience method, adds two vertex indices (a segment) in the range [1,VertexNumber()] in the array of segments (Graphic3d_TOPA_SEGMENTS).
//! Raises exception if array is not of type Graphic3d_TOPA_SEGMENTS.
//! @return the actual edges number
Standard_Integer AddSegmentEdges (Standard_Integer theVertexIndex1,
Standard_Integer theVertexIndex2)
{
Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_SEGMENTS, "Not array of segments");
return AddEdges (theVertexIndex1, theVertexIndex2);
}
//! Convenience method, adds three vertex indices (a triangle) in the range [1,VertexNumber()] in the array.
//! @return the actual edges number
Standard_Integer AddEdges (Standard_Integer theVertexIndex1,
@ -548,6 +559,35 @@ public: //! @name optional array of Indices/Edges for using shared Vertex data
return AddEdge (theVertexIndex3);
}
//! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in the array of triangles.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @return the actual edges number
Standard_Integer AddTriangleEdges (Standard_Integer theVertexIndex1,
Standard_Integer theVertexIndex2,
Standard_Integer theVertexIndex3)
{
Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
return AddEdges (theVertexIndex1, theVertexIndex2, theVertexIndex3);
}
//! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in the array of triangles.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @return the actual edges number
Standard_Integer AddTriangleEdges (const Graphic3d_Vec3i& theIndexes)
{
Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
return AddEdges (theIndexes[0], theIndexes[1], theIndexes[2]);
}
//! Convenience method, adds three vertex indices (4th component is ignored) of triangle in the range [1,VertexNumber()] in the array of triangles.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @return the actual edges number
Standard_Integer AddTriangleEdges (const Graphic3d_Vec4i& theIndexes)
{
Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
return AddEdges (theIndexes[0], theIndexes[1], theIndexes[2]);
}
//! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the array.
//! @return the actual edges number
Standard_Integer AddEdges (Standard_Integer theVertexIndex1,
@ -561,6 +601,66 @@ public: //! @name optional array of Indices/Edges for using shared Vertex data
return AddEdge (theVertexIndex4);
}
//! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the array of quads.
//! Raises exception if array is not of type Graphic3d_TOPA_QUADRANGLES.
//! @return the actual edges number
Standard_Integer AddQuadEdges (Standard_Integer theVertexIndex1,
Standard_Integer theVertexIndex2,
Standard_Integer theVertexIndex3,
Standard_Integer theVertexIndex4)
{
Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_QUADRANGLES, "Not array of quads");
return AddEdges (theVertexIndex1, theVertexIndex2, theVertexIndex3, theVertexIndex4);
}
//! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles as two triangles.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @return the actual edges number
Standard_Integer AddQuadTriangleEdges (Standard_Integer theVertexIndex1,
Standard_Integer theVertexIndex2,
Standard_Integer theVertexIndex3,
Standard_Integer theVertexIndex4)
{
AddTriangleEdges (theVertexIndex3, theVertexIndex1, theVertexIndex2);
return AddTriangleEdges (theVertexIndex1, theVertexIndex3, theVertexIndex4);
}
//! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles as two triangles.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @return the actual edges number
Standard_Integer AddQuadTriangleEdges (const Graphic3d_Vec4i& theIndexes)
{
return AddQuadTriangleEdges (theIndexes[0], theIndexes[1], theIndexes[2], theIndexes[3]);
}
//! Add triangle strip into indexed triangulation array.
//! N-2 triangles are added from N input nodes.
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @param theVertexLower [in] index of first node defining triangle strip
//! @param theVertexUpper [in] index of last node defining triangle strip
Standard_EXPORT void AddTriangleStripEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper);
//! Add triangle fan into indexed triangulation array.
//! N-2 triangles are added from N input nodes (or N-1 with closed flag).
//! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
//! @param theVertexLower [in] index of first node defining triangle fun (center)
//! @param theVertexUpper [in] index of last node defining triangle fun
//! @param theToClose [in] close triangle fan (connect first and last points)
Standard_EXPORT void AddTriangleFanEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper,
Standard_Boolean theToClose);
//! Add line strip (polyline) into indexed segments array.
//! N-1 segments are added from N input nodes (or N with closed flag).
//! Raises exception if array is not of type Graphic3d_TOPA_SEGMENTS.
//! @param theVertexLower [in] index of first node defining line strip fun (center)
//! @param theVertexUpper [in] index of last node defining triangle fun
//! @param theToClose [in] close triangle fan (connect first and last points)
Standard_EXPORT void AddPolylineEdges (Standard_Integer theVertexLower,
Standard_Integer theVertexUpper,
Standard_Boolean theToClose);
public: //! @name optional array of Bounds/Subgroups within primitive array (e.g. restarting primitives / assigning colors)
//! Returns optional bounds buffer.

View File

@ -5,6 +5,7 @@ puts "=================================="
vclear
vinit View1
vrenderparams -rendScale 1
vviewcube vc -edges 0
if {[vreadpixel 70 295 name rgb] != "BLACK"} { puts "Error: Invalid display of View Cube without edges." }
@ -23,6 +24,7 @@ vdump $imagedir/${casename}_noedgeandvert.png
vclear
# Color
vrenderparams -rendScale 2
vviewcube vc1 -boxColor 0.69 0.88 1 -textColor 0 0.4 0.54
vdisplay vc1 -trihedron bottomLeft 100 100
@ -33,10 +35,12 @@ vdisplay vc2 -trihedron topLeft 100 100
# Font
vviewcube vc3 -reset -boxSideColor WHITE -font "monospace" -fontHeight 16
vdisplay vc3 -trihedron bottomRight 100 100
vaspects vc3 -setFaceBoundaryDraw 1 -setFaceBoundaryWidth 2
# Corner radius
vviewcube vc4 -reset -boxSideColor WHITE -roundRadius 0.2 -boxEdgeGap 2
vdisplay vc4 -trihedron topRight 100 100
vaspects vc4 -setFaceBoundaryDraw 1
# Padding
vviewcube vc5 -reset -boxFacetExtension 0 -axesPadding 0