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

0029823: Visualization, TKOpenGl - highlighting by Bounding Box mistreats Local Transformation

The problem when object transformation was applied to the bounding box twice has been fixed in OpenGl_Structure.
OpenGl_ShaderManager has been extended with GLSL program drawing bounding box.
OpenGl_Structure does not create extra Groups for drawing bounding box.
This commit is contained in:
mnv 2018-07-02 11:21:35 +03:00 committed by bugmaster
parent 1b661a81d5
commit 98b15dbfce
7 changed files with 208 additions and 164 deletions

View File

@ -118,8 +118,7 @@ public:
virtual void Disconnect (Graphic3d_CStructure& theStructure) = 0;
//! Highlights structure with the given style
virtual void GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
const Handle(Graphic3d_Structure)& theStruct) = 0;
virtual void GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle) = 0;
//! Unhighlights the structure and invalidates pointer to structure's highlight
//! style

View File

@ -260,7 +260,7 @@ void Graphic3d_Structure::Highlight (const Handle(Graphic3d_PresentationAttribut
SetDisplayPriority (Structure_MAX_PRIORITY - 1);
myCStructure->GraphicHighlight (theStyle, this);
myCStructure->GraphicHighlight (theStyle);
if (!theToUpdateMgr)
{

View File

@ -24,6 +24,7 @@
#include <OpenGl_Context.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <OpenGl_ShaderProgram.hxx>
#include <OpenGl_VertexBufferCompat.hxx>
#include <OpenGl_Workspace.hxx>
#include <TCollection_ExtendedString.hxx>
@ -406,6 +407,8 @@ void OpenGl_ShaderManager::clear()
myMapOfLightPrograms.Clear();
myFontProgram.Nullify();
myBlitProgram.Nullify();
myBoundBoxProgram.Nullify();
myBoundBoxVertBuffer.Nullify();
for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
{
myStereoPrograms[aModeIter].Nullify();
@ -2469,6 +2472,95 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
return Standard_True;
}
// =======================================================================
// function : prepareStdProgramBoundBox
// purpose :
// =======================================================================
Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
{
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert =
EOL"uniform vec3 occBBoxCenter;"
EOL"uniform vec3 occBBoxSize;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
EOL"}";
TCollection_AsciiString aSrcFrag =
EOL"void main()"
EOL"{"
EOL" occSetFragColor (occColor);"
EOL"}";
#if !defined(GL_ES_VERSION_2_0)
if (myContext->core32 != NULL)
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 1))
{
// prefer "100 es" on OpenGL ES 3.0 devices
// and "300 es" on newer devices (3.1+)
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
TCollection_AsciiString aKey;
if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
{
myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
return Standard_False;
}
const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
const OpenGl_Vec4 anAxisShifts[3] =
{
OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
};
const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
OpenGl_Vec4 aLinesVertices[24];
for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
{
for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
{
aLinesVertices[aVertex++] = aMin
+ anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
+ anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
aLinesVertices[aVertex++] = aMin
+ anAxisShifts[anAxis]
+ anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
+ anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
}
}
if (myContext->ToUseVbo())
{
myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
{
myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
return Standard_True;
}
}
myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
return Standard_True;
}
// =======================================================================
// function : bindProgramWithState
// purpose :

View File

@ -32,6 +32,7 @@
#include <OpenGl_Texture.hxx>
class OpenGl_View;
class OpenGl_VertexBuffer;
//! List of shader programs.
typedef NCollection_Sequence<Handle(OpenGl_ShaderProgram)> OpenGl_ShaderProgramList;
@ -204,6 +205,19 @@ public:
&& myContext->BindProgram (aProgram);
}
//! Bind program for rendering bounding box.
Standard_Boolean BindBoundBoxProgram()
{
if (myBoundBoxProgram.IsNull())
{
prepareStdProgramBoundBox();
}
return bindProgramWithState (myBoundBoxProgram);
}
//! Returns bounding box vertex buffer.
const Handle(OpenGl_VertexBuffer)& BoundBoxVertBuffer() const { return myBoundBoxVertBuffer; }
public:
//! Returns current state of OCCT light sources.
@ -538,6 +552,9 @@ protected:
Standard_EXPORT Standard_Boolean prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
const Graphic3d_StereoMode theStereoMode);
//! Prepare standard GLSL program for bounding box.
Standard_EXPORT Standard_Boolean prepareStdProgramBoundBox();
protected:
//! Packed properties of light source
@ -606,11 +623,14 @@ protected:
Handle(OpenGl_SetOfShaderPrograms) myUnlitPrograms; //!< programs matrix without lighting
Handle(OpenGl_ShaderProgram) myFontProgram; //!< standard program for textured text
Handle(OpenGl_ShaderProgram) myBlitProgram; //!< standard program for FBO blit emulation
Handle(OpenGl_ShaderProgram) myBoundBoxProgram; //!< standard program for bounding box
Handle(OpenGl_ShaderProgram) myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
OpenGl_MapOfShaderPrograms myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
Handle(OpenGl_ShaderProgram) myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
Handle(OpenGl_VertexBuffer) myBoundBoxVertBuffer; //!< bounding box vertex buffer
OpenGl_Context* myContext; //!< OpenGL context
protected:

View File

@ -27,96 +27,76 @@
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
//! Auxiliary class for bounding box presentation
class OpenGl_BndBoxPrs : public OpenGl_Element
// =======================================================================
// function : renderBoundingBox
// purpose :
// =======================================================================
void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWorkspace) const
{
public:
//! Main constructor
OpenGl_BndBoxPrs (const Graphic3d_BndBox3d& theBndBox)
{
const float Xm = (float )theBndBox.CornerMin().x();
const float Ym = (float)theBndBox.CornerMin().y();
const float Zm = (float)theBndBox.CornerMin().z();
const float XM = (float)theBndBox.CornerMax().x();
const float YM = (float)theBndBox.CornerMax().y();
const float ZM = (float)theBndBox.CornerMax().z();
myVerts[0] = OpenGl_Vec3 (Xm, Ym, Zm);
myVerts[1] = OpenGl_Vec3 (Xm, Ym, ZM);
myVerts[2] = OpenGl_Vec3 (Xm, YM, ZM);
myVerts[3] = OpenGl_Vec3 (Xm, YM, Zm);
myVerts[4] = OpenGl_Vec3 (Xm, Ym, Zm);
myVerts[5] = OpenGl_Vec3 (XM, Ym, Zm);
myVerts[6] = OpenGl_Vec3 (XM, Ym, ZM);
myVerts[7] = OpenGl_Vec3 (XM, YM, ZM);
myVerts[8] = OpenGl_Vec3 (XM, YM, Zm);
myVerts[9] = OpenGl_Vec3 (XM, Ym, Zm);
myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
}
//! Render presentation
virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
{
#if !defined(GL_ES_VERSION_2_0)
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
if (aCtx->core11 == NULL)
if (!myBndBox.IsValid())
{
return;
}
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
glDisable (GL_LIGHTING);
// Use highlight colors
aCtx->core11->glColor3fv (theWorkspace->LineColor().GetData());
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
glDrawArrays (GL_LINE_STRIP, 0, 16);
glDisableClientState (GL_VERTEX_ARRAY);
// restore aspects
if (!aPrevTexture.IsNull())
const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
const Graphic3d_Vec3d aMoveVec = myTrsfPers.IsNull()
&& !aLayer.OriginTransformation().IsNull()
? -Graphic3d_Vec3d (aLayer.Origin().X(), aLayer.Origin().Y(), aLayer.Origin().Z())
: Graphic3d_Vec3d (0.0, 0.0, 0.0);
if (aCtx->core20fwd != NULL
&& aCtx->ShaderManager()->BindBoundBoxProgram())
{
const Graphic3d_Vec3d aCenter = myBndBox.Center() + aMoveVec;
const Graphic3d_Vec3d aSize = myBndBox.Size();
aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxCenter", Graphic3d_Vec3 ((float )aCenter.x(), (float )aCenter.y(), (float )aCenter.z()));
aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxSize", Graphic3d_Vec3 ((float )aSize.x(), (float )aSize.y(), (float )aSize.z()));
aCtx->SetColor4fv (theWorkspace->LineColor());
const Handle(OpenGl_VertexBuffer)& aBoundBoxVertBuffer = aCtx->ShaderManager()->BoundBoxVertBuffer();
aBoundBoxVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS);
aCtx->core20fwd->glDrawArrays (GL_LINES, 0, aBoundBoxVertBuffer->GetElemsNb());
aBoundBoxVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
}
#if !defined(GL_ES_VERSION_2_0)
else if (aCtx->core11 != NULL)
{
const Graphic3d_Vec3d aMind = myBndBox.CornerMin() + aMoveVec;
const Graphic3d_Vec3d aMaxd = myBndBox.CornerMax() + aMoveVec;
const Graphic3d_Vec3 aMin ((float )aMind.x(), (float )aMind.y(), (float )aMind.z());
const Graphic3d_Vec3 aMax ((float )aMaxd.x(), (float )aMaxd.y(), (float )aMaxd.z());
const OpenGl_Vec3 aVerts[16] =
{
OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z()),
OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z())
};
aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false, Handle(OpenGl_ShaderProgram)());
aCtx->SetColor4fv (theWorkspace->LineColor());
aCtx->core11fwd->glDisable (GL_LIGHTING);
aCtx->core11->glEnableClientState (GL_VERTEX_ARRAY);
aCtx->core11->glVertexPointer (3, GL_FLOAT, 0, aVerts[0].GetData());
aCtx->core11fwd->glDrawArrays (GL_LINE_STRIP, 0, 16);
aCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);
}
#endif
aCtx->BindTextures (aPrevTexture);
}
#else
(void )theWorkspace;
#endif
}
//! Release graphical resources
virtual void Release (OpenGl_Context*)
{
//
}
protected:
//! Protected destructor
virtual ~OpenGl_BndBoxPrs() {}
private:
OpenGl_Vec3 myVerts[16]; //!< vertices array
public:
DEFINE_STANDARD_ALLOC
};
/*----------------------------------------------------------------------*/
}
// =======================================================================
// function : OpenGl_Structure
@ -207,64 +187,14 @@ void OpenGl_Structure::updateLayerTransformation()
aRenderTrsf.GetMat4 (myRenderTrsf);
}
// =======================================================================
// function : clearHighlightBox
// purpose :
// =======================================================================
void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
{
if (!myHighlightBox.IsNull())
{
myHighlightBox->Release (theGlCtx);
myHighlightBox.Nullify();
}
}
// =======================================================================
// function : HighlightWithBndBox
// purpose :
// =======================================================================
void OpenGl_Structure::highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct)
{
const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
if (!myHighlightBox.IsNull())
{
myHighlightBox->Release (aContext);
}
else
{
myHighlightBox = new OpenGl_Group (theStruct);
}
myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myHighlightStyle->Color(), Aspect_TOL_SOLID, 1.0));
OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
myHighlightBox->AddElement (aBndBoxPrs);
}
// =======================================================================
// function : GraphicHighlight
// purpose :
// =======================================================================
void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
const Handle(Graphic3d_Structure)& theStruct)
void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle)
{
if (!myHighlightStyle.IsNull()
&& myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX
&& theStyle->Method() != Aspect_TOHM_BOUNDBOX)
{
const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
clearHighlightBox (aContext);
}
myHighlightStyle = theStyle;
highlight = 1;
if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
{
highlightWithBndBox (theStruct);
}
}
// =======================================================================
@ -274,13 +204,6 @@ void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttr
void OpenGl_Structure::GraphicUnhighlight()
{
highlight = 0;
if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
{
const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
clearHighlightBox (aContext);
}
myHighlightStyle.Nullify();
}
@ -488,7 +411,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
// Render named status
if (highlight && myHighlightBox.IsNull())
if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX)
{
theWorkspace->SetHighlightStyle (myHighlightStyle);
}
@ -666,10 +589,6 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
// Restore local transformation
aCtx->ModelWorldState.Pop();
aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
if (!myTrsfPers.IsNull())
{
aCtx->WorldViewState.Pop();
}
// Restore aspects
theWorkspace->SetAspectLine (aPrevAspectLine);
@ -678,10 +597,18 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
theWorkspace->SetAspectText (aPrevAspectText);
// Apply highlight box
if (!myHighlightBox.IsNull())
if (!isClipped
&& !myHighlightStyle.IsNull()
&& myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
{
aCtx->ApplyModelViewMatrix();
theWorkspace->SetHighlightStyle (myHighlightStyle);
myHighlightBox->Render (theWorkspace);
renderBoundingBox (theWorkspace);
}
if (!myTrsfPers.IsNull())
{
aCtx->WorldViewState.Pop();
}
// Restore named status
@ -696,7 +623,6 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
{
// Release groups
Clear (theGlCtx);
clearHighlightBox (theGlCtx);
myHighlightStyle.Nullify();
}
@ -710,10 +636,6 @@ void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCt
{
aGroupIter.ChangeValue()->Release (theGlCtx);
}
if (!myHighlightBox.IsNull())
{
myHighlightBox->Release (theGlCtx.operator->());
}
}
//=======================================================================

View File

@ -88,8 +88,7 @@ public:
//! Highlights structure according to the given style and updates corresponding class fields
//! (highlight status and style)
Standard_EXPORT virtual void GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
const Handle(Graphic3d_Structure)& theStruct) Standard_OVERRIDE;
Standard_EXPORT virtual void GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle) Standard_OVERRIDE;
//! Unighlights structure and updates corresponding class fields (highlight status and style)
Standard_EXPORT virtual void GraphicUnhighlight() Standard_OVERRIDE;
@ -177,16 +176,11 @@ protected:
Standard_EXPORT void renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
bool& theHasClosed) const;
//! Highlight structure using boundary box
Standard_EXPORT void highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct);
//! Invalidates highlight box and releases graphic resources it uses
Standard_EXPORT void clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx);
//! Render the bounding box.
Standard_EXPORT void renderBoundingBox(const Handle(OpenGl_Workspace)& theWorkspace) const;
protected:
Handle(OpenGl_Group) myHighlightBox;
OpenGl_Structure* myInstancedStructure;
Graphic3d_Mat4 myRenderTrsf; //!< transformation, actually used for rendering (includes Local Origin shift)

17
tests/v3d/glsl/bndbox1 Normal file
View File

@ -0,0 +1,17 @@
puts "============"
puts "0029823: Visualization, TKOpenGl - highlighting by Bounding Box mistreats Local Transformation"
puts "============"
puts ""
pload MODELING VISUALIZATION
vclear
vinit View1
vaxo
psphere s0 1
psphere s1 1
vdisplay -dispMode 1 s0 s1
vlocation s1 -reset -translate 2 1 0 -rotate 0 0 0 1 0 0 20
vfit
vbounding
vdump $imagedir/${casename}.png