From e1c659da58da75b177b665a8eef2e53e1c22698a Mon Sep 17 00:00:00 2001 From: aba Date: Wed, 25 Mar 2015 14:15:13 +0300 Subject: [PATCH] 0023484: Visualization, TKOpenGl - primitive arrays to become the only way to render geometry OpenGl_CappingAlgo - draw capping plane using OpenGl_PrimitiveArray. OpenGl_Trihedron - draw trihedron in wireframe mode using OpenGl_PrimitiveArray. ~OpenGl_Context() - release Delayed resources occured after deletion of Shared resources. Draw Harness, vzbufftrihedron command - redraw viewer after trihedron definition. --- src/OpenGl/OpenGl_CappingAlgo.cxx | 42 +- src/OpenGl/OpenGl_CappingPlaneResource.cxx | 48 +- src/OpenGl/OpenGl_CappingPlaneResource.hxx | 7 +- src/OpenGl/OpenGl_Context.cxx | 14 + src/OpenGl/OpenGl_PrimitiveArray.cxx | 17 +- src/OpenGl/OpenGl_PrimitiveArray.hxx | 41 +- src/OpenGl/OpenGl_Trihedron.cxx | 463 +++++++++---------- src/OpenGl/OpenGl_Trihedron.hxx | 53 ++- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 1 + tests/bugs/vis/bug23484_1 | 23 + tests/bugs/vis/bug23484_2 | 27 ++ 11 files changed, 415 insertions(+), 321 deletions(-) create mode 100644 tests/bugs/vis/bug23484_1 create mode 100644 tests/bugs/vis/bug23484_2 diff --git a/src/OpenGl/OpenGl_CappingAlgo.cxx b/src/OpenGl/OpenGl_CappingAlgo.cxx index 1436030bea..cb94604302 100755 --- a/src/OpenGl/OpenGl_CappingAlgo.cxx +++ b/src/OpenGl/OpenGl_CappingAlgo.cxx @@ -39,34 +39,6 @@ namespace static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES; static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN; #endif - - static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] = - { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f), - OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f), - OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) }; - - static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] = - { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - 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, 0.0f, 1.0f), - OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f), - OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f), - OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f), - 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, 0.0f, 1.0f), - OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f), - OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) }; } // ======================================================================= @@ -226,24 +198,12 @@ void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspa theWorkspace->SetAspectFace (aPlaneAspect); } - // apply aspect for rendering - theWorkspace->AspectFace (Standard_True); - // set identity model matrix aContext->ModelWorldState.Push(); aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*aPlaneRes->Orientation()->mat)); aContext->ApplyModelViewMatrix(); -#if !defined(GL_ES_VERSION_2_0) - glNormal3f (0.0f, 1.0f, 0.0f); - glEnableClientState (GL_VERTEX_ARRAY); - glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD); - glDrawArrays (GL_TRIANGLES, 0, 12); - glDisableClientState (GL_VERTEX_ARRAY); - glDisableClientState (GL_TEXTURE_COORD_ARRAY); -#endif + aPlaneRes->Primitives().Render (theWorkspace); aContext->ModelWorldState.Pop(); aContext->ApplyModelViewMatrix(); diff --git a/src/OpenGl/OpenGl_CappingPlaneResource.cxx b/src/OpenGl/OpenGl_CappingPlaneResource.cxx index 629462e60e..6da17358e4 100755 --- a/src/OpenGl/OpenGl_CappingPlaneResource.cxx +++ b/src/OpenGl/OpenGl_CappingPlaneResource.cxx @@ -13,11 +13,38 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include #include #include #include #include +namespace +{ + //! 12 plane vertices, interleaved: + //! - 4 floats, position + //! - 4 floats, normal + //! - 4 floats, UV texture coordinates + static const GLfloat THE_CAPPING_PLN_VERTS[12 * (4 + 4 + 4)] = + { + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, + + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; +} + IMPLEMENT_STANDARD_HANDLE (OpenGl_CappingPlaneResource, OpenGl_Resource) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingPlaneResource, OpenGl_Resource) @@ -26,12 +53,28 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingPlaneResource, OpenGl_Resource) // purpose : // ======================================================================= OpenGl_CappingPlaneResource::OpenGl_CappingPlaneResource (const Handle(Graphic3d_ClipPlane)& thePlane) -: myOrientation (OpenGl_IdentityMatrix), +: myPrimitives (NULL), + myOrientation (OpenGl_IdentityMatrix), myAspect (NULL), myPlaneRoot (thePlane), myEquationMod ((unsigned int )-1), myAspectMod ((unsigned int )-1) -{} +{ + // Fill primitive array + Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16); + Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (anAlloc); + Graphic3d_Attribute anAttribInfo[] = + { + { Graphic3d_TOA_POS, Graphic3d_TOD_VEC4 }, + { Graphic3d_TOA_NORM, Graphic3d_TOD_VEC4 }, + { Graphic3d_TOA_UV, Graphic3d_TOD_VEC4 } + }; + if (anAttribs->Init (12, anAttribInfo, 3)) + { + memcpy (anAttribs->ChangeData(), THE_CAPPING_PLN_VERTS, sizeof(THE_CAPPING_PLN_VERTS)); + myPrimitives.InitBuffers (NULL, Graphic3d_TOPA_TRIANGLES, NULL, anAttribs, NULL); + } +} // ======================================================================= // function : OpenGl_CappingPlaneResource @@ -59,6 +102,7 @@ void OpenGl_CappingPlaneResource::Update (const Handle(OpenGl_Context)& theConte void OpenGl_CappingPlaneResource::Release (OpenGl_Context* theContext) { OpenGl_Element::Destroy (theContext, myAspect); + myPrimitives.Release (theContext); myEquationMod = (unsigned int )-1; myAspectMod = (unsigned int )-1; } diff --git a/src/OpenGl/OpenGl_CappingPlaneResource.hxx b/src/OpenGl/OpenGl_CappingPlaneResource.hxx index 33dee4794b..27bcf7fde7 100755 --- a/src/OpenGl/OpenGl_CappingPlaneResource.hxx +++ b/src/OpenGl/OpenGl_CappingPlaneResource.hxx @@ -16,6 +16,7 @@ #ifndef _OpenGl_CappingPlaneResource_H__ #define _OpenGl_CappingPlaneResource_H__ +#include #include #include #include @@ -50,7 +51,7 @@ public: //! Release associated OpenGl resources. //! @param theContext [in] the resource context. - Standard_EXPORT void Release (OpenGl_Context* theContext); + Standard_EXPORT virtual void Release (OpenGl_Context* theContext) Standard_OVERRIDE; //! @return aspect face for rendering capping surface. inline const OpenGl_AspectFace* AspectFace() const { return myAspect; } @@ -58,6 +59,9 @@ public: //! @return evaluated orientation matrix to transform infinite plane. inline const OpenGl_Matrix* Orientation() const { return &myOrientation; } + //! @return primitive array of vertices to render infinite plane. + inline const OpenGl_PrimitiveArray& Primitives() const { return myPrimitives; } + private: //! Update precomputed plane orientation matrix. @@ -69,6 +73,7 @@ private: private: + OpenGl_PrimitiveArray myPrimitives; //!< vertices and texture coordinates for rendering OpenGl_Matrix myOrientation; //!< plane transformation matrix. OpenGl_AspectFace* myAspect; //!< capping face aspect. Handle(Graphic3d_ClipPlane) myPlaneRoot; //!< parent clipping plane structure. diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index d5a428b77c..a798c3a212 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -185,6 +185,13 @@ OpenGl_Context::~OpenGl_Context() { anIter.Value()->Release (this); } + + // release delayed resources added during deletion of shared resources + while (!myUnusedResources->IsEmpty()) + { + myUnusedResources->First()->Release (this); + myUnusedResources->RemoveFirst(); + } } else { @@ -231,6 +238,13 @@ void OpenGl_Context::forcedRelease() mySharedResources->Clear(); myShaderManager->clear(); myShaderManager->SetContext (NULL); + + // release delayed resources added during deletion of shared resources + while (!myUnusedResources->IsEmpty()) + { + myUnusedResources->First()->Release (this); + myUnusedResources->RemoveFirst(); + } } // ======================================================================= diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 6ecfc68926..4576d0c42c 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -596,6 +596,21 @@ void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWork #endif } +// ======================================================================= +// function : OpenGl_PrimitiveArray +// purpose : +// ======================================================================= +OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver) + +: myDrawMode (DRAW_MODE_NONE), + myIsVboInit (Standard_False) +{ + if (theDriver != NULL) + { + myUID = theDriver->GetNextPrimitiveArrayUID(); + } +} + // ======================================================================= // function : OpenGl_PrimitiveArray // purpose : @@ -874,5 +889,3 @@ void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& th setDrawMode (theType); } - - diff --git a/src/OpenGl/OpenGl_PrimitiveArray.hxx b/src/OpenGl/OpenGl_PrimitiveArray.hxx index 1ddb670c27..80a7fbdd56 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.hxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.hxx @@ -42,17 +42,29 @@ public: DRAW_MODE_NONE = -1 }; + //! Empty constructor + Standard_EXPORT OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver); + //! Default constructor - OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver, - const Graphic3d_TypeOfPrimitiveArray theType, - const Handle(Graphic3d_IndexBuffer)& theIndices, - const Handle(Graphic3d_Buffer)& theAttribs, - const Handle(Graphic3d_BoundBuffer)& theBounds); + Standard_EXPORT OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver, + const Graphic3d_TypeOfPrimitiveArray theType, + const Handle(Graphic3d_IndexBuffer)& theIndices, + const Handle(Graphic3d_Buffer)& theAttribs, + const Handle(Graphic3d_BoundBuffer)& theBounds); + + //! Destructor + Standard_EXPORT virtual ~OpenGl_PrimitiveArray(); //! Render primitives to the window - virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; + Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; + + //! Release OpenGL resources (VBOs) + Standard_EXPORT virtual void Release (OpenGl_Context* theContext); - virtual void Release (OpenGl_Context* theContext); + //! Return true if VBOs initialization has been performed. + //! VBO initialization is performed during first Render() call. + //! Notice that this flag does not indicate VBOs validity. + Standard_Boolean IsInitialized() const { return myIsVboInit; } //! @return primitive type (GL_LINES, GL_TRIANGLES and others) GLint DrawMode() const { return myDrawMode; } @@ -70,11 +82,11 @@ public: const Standard_Size GetUID() const { return myUID; } //! Initialize indices, attributes and bounds with new data. - void InitBuffers (const Handle(OpenGl_Context)& theContext, - const Graphic3d_TypeOfPrimitiveArray theType, - const Handle(Graphic3d_IndexBuffer)& theIndices, - const Handle(Graphic3d_Buffer)& theAttribs, - const Handle(Graphic3d_BoundBuffer)& theBounds); + Standard_EXPORT void InitBuffers (const Handle(OpenGl_Context)& theContext, + const Graphic3d_TypeOfPrimitiveArray theType, + const Handle(Graphic3d_IndexBuffer)& theIndices, + const Handle(Graphic3d_Buffer)& theAttribs, + const Handle(Graphic3d_BoundBuffer)& theBounds); protected: @@ -107,11 +119,6 @@ private: //! @param theType type of primitive array. void setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType); -protected: - - //! Destructor - virtual ~OpenGl_PrimitiveArray(); - protected: mutable Handle(OpenGl_VertexBuffer) myVboIndices; diff --git a/src/OpenGl/OpenGl_Trihedron.cxx b/src/OpenGl/OpenGl_Trihedron.cxx index b9597df29f..9773aed60c 100644 --- a/src/OpenGl/OpenGl_Trihedron.cxx +++ b/src/OpenGl/OpenGl_Trihedron.cxx @@ -17,6 +17,8 @@ #include +#include +#include #include #include @@ -58,225 +60,281 @@ static float theDiameter = 0.05f; static int theNbFacettes = 12; // ======================================================================= -// function : redraw +// function : resetTransformations // purpose : // ======================================================================= -void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) const +void OpenGl_Trihedron::resetTransformations (const Handle(OpenGl_Workspace)& theWorkspace) const { -#if !defined(GL_ES_VERSION_2_0) - const Standard_Real U = theWorkspace->ActiveView()->Height(); - const Standard_Real V = theWorkspace->ActiveView()->Width(); - - Handle(OpenGl_Context) aContext = theWorkspace->GetGlContext(); - - /* la taille des axes est 1 proportion (fixee a l'init du triedre) */ - /* de la dimension la plus petite de la window. */ - const GLdouble L = ( U < V ? U : V ) * myScale; - - /* - * On inhibe les translations; on conserve les autres transformations. - */ - - aContext->WorldViewState.Push(); - aContext->ProjectionState.Push(); + const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); + const Handle(OpenGl_View)& aView = theWorkspace->ActiveView(); + GLdouble anU = 1.0; + GLdouble aV = 1.0; + if (aView->Height() < aView->Width()) + { + aV = aView->Width() / aView->Height(); + } + else + { + anU = aView->Height() / aView->Width(); + } - /* on lit les matrices de transformation et de projection de la vue */ - /* pour annuler les translations (dernieres colonnes des matrices). */ + // Reading the transformation matrices and projection of sight + // to cancel translations (last columns of matrices). OpenGl_Mat4d aModelMatrix; - aModelMatrix.Convert (aContext->WorldViewState.Current()); - OpenGl_Mat4d aProjMatrix; + aModelMatrix.Convert (aContext->WorldViewState.Current()); - /* on annule la translation qui peut etre affectee a la vue */ + // Cancel the translation that can be assigned to the view aModelMatrix.ChangeValue (0, 3) = 0.0; aModelMatrix.ChangeValue (1, 3) = 0.0; aModelMatrix.ChangeValue (2, 3) = 0.0; - aProjMatrix.ChangeValue (0, 0) = 2.0 / U; + aProjMatrix.ChangeValue (0, 0) = 2.0 / anU; aProjMatrix.ChangeValue (1, 0) = 0.0; aProjMatrix.ChangeValue (2, 0) = 0.0; aProjMatrix.ChangeValue (3, 0) = 0.0; aProjMatrix.ChangeValue (0, 1) = 0.0; - aProjMatrix.ChangeValue (1, 1) = 2.0 / V; + aProjMatrix.ChangeValue (1, 1) = 2.0 / aV; aProjMatrix.ChangeValue (2, 1) = 0.0; aProjMatrix.ChangeValue (3, 1) = 0.0; aProjMatrix.ChangeValue (0, 2) = 0.0; aProjMatrix.ChangeValue (1, 2) = 0.0; - aProjMatrix.ChangeValue (2, 2) = -2.0 * 1e-7; - aProjMatrix.ChangeValue (3, 2) = 0.0; - + aProjMatrix.ChangeValue (2, 2) = -2.0 * 0.01; + aProjMatrix.ChangeValue (3, 2) = 0.0; + aProjMatrix.ChangeValue (0, 3) = 0.0; aProjMatrix.ChangeValue (1, 3) = 0.0; aProjMatrix.ChangeValue (2, 3) = 0.0; aProjMatrix.ChangeValue (3, 3) = 1.0; - /* - * Positionnement de l'origine du triedre selon le choix de l'init - */ - - /* on fait uniquement une translation de l'origine du Triedre */ - + // Define trihedron position in the view switch (myPos) { - case Aspect_TOTP_LEFT_LOWER : + case Aspect_TOTP_LEFT_LOWER: { OpenGl_Utils::Translate (aProjMatrix, - -0.5 * U + L, -0.5 * V + L, 0.0); + -0.5 * anU + myScale, -0.5 * aV + myScale, 0.0); + break; } - break; - - case Aspect_TOTP_LEFT_UPPER : + case Aspect_TOTP_LEFT_UPPER: { OpenGl_Utils::Translate (aProjMatrix, - -0.5 * U + L, 0.5 * V - L - L/3.0, 0.0); + -0.5 * anU + myScale, 0.5 * aV - myScale - myScale / 3.0, 0.0); + break; } - break; - - case Aspect_TOTP_RIGHT_LOWER : + case Aspect_TOTP_RIGHT_LOWER: { OpenGl_Utils::Translate (aProjMatrix, - 0.5 * U - L - L/3.0, -0.5 * V + L, 0.0); + 0.5 * anU - myScale - myScale / 3.0, -0.5 * aV + myScale, 0.0); + break; } - break; - - case Aspect_TOTP_RIGHT_UPPER : + case Aspect_TOTP_RIGHT_UPPER: { OpenGl_Utils::Translate (aProjMatrix, - 0.5 * U - L - L/3.0, 0.5 * V - L - L/3.0, 0.0); + 0.5 * anU - myScale - myScale / 3.0, 0.5 * aV - myScale - myScale / 3.0, 0.0); + break; } - break; - - //case Aspect_TOTP_CENTER : - default : + //case Aspect_TOTP_CENTER: + default: break; } aContext->ProjectionState.SetCurrent (aProjMatrix); - aContext->WorldViewState.SetCurrent (aModelMatrix); aContext->ApplyProjectionMatrix(); + + aContext->WorldViewState.SetCurrent (aModelMatrix); aContext->ApplyWorldViewMatrix(); +} - /* - * Creation du triedre - */ +// ======================================================================= +// function : redraw +// purpose : +// ======================================================================= +void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); + aContext->WorldViewState.Push(); + aContext->ProjectionState.Push(); - /* Fotis Sioutis 2007-11-14 15:06 - I have also seen in previous posts that the view trihedron in V3d_WIREFRAME mode - changes colors depending on the state of the view. This behaviour can be easily - corrected by altering call_triedron_redraw function in OpenGl_triedron.c of TKOpengl. - The only change needed is to erase glDisable(GL_LIGHTING) that is called before the - Axis name drawing and move this function call just before the initial axis drawing. - Below is the code portion with the modification.I don't know if this is considered to - be a bug but anyway i believe it might help some of you out there.*/ - glDisable(GL_LIGHTING); - - /* Position de l'origine */ - const GLdouble TriedronOrigin[3] = { 0.0, 0.0, 0.0 }; - - /* Position des Axes */ - GLdouble TriedronAxeX[3] = { 1.0, 0.0, 0.0 }; - GLdouble TriedronAxeY[3] = { 0.0, 1.0, 0.0 }; - GLdouble TriedronAxeZ[3] = { 0.0, 0.0, 1.0 }; - TriedronAxeX[0] = L ; - TriedronAxeY[1] = L ; - TriedronAxeZ[2] = L ; - - /* dessin des axes */ - glBegin(GL_LINES); - glVertex3dv( TriedronOrigin ); - glVertex3dv( TriedronAxeX ); - - glVertex3dv( TriedronOrigin ); - glVertex3dv( TriedronAxeY ); - - glVertex3dv( TriedronOrigin ); - glVertex3dv( TriedronAxeZ ); - glEnd(); - - /* fleches au bout des axes (= cones de la couleur demandee) */ - const GLdouble l = 0.75*L; /* distance a l'origine */ - const GLdouble rayon = L/30. ; /* rayon de la base du cone */ - const int NbFacettes = 12; /* le cone sera compose de 12 facettes triangulaires */ - const double Angle = 2. * M_PI/ NbFacettes; - - int ii; - GLdouble TriedronCoord[3] = { 1.0, 0.0, 0.0 }; - - /* solution FILAIRE des cones au bout des axes : une seule ligne */ - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - /* (la couleur est deja initialisee dans AspectLine) */ - /* FIN de la solution FILAIRE CHOISIE pour les cones des axes */ - - /* fleche en X */ - glBegin(GL_TRIANGLE_FAN); - glVertex3dv( TriedronAxeX ); - TriedronCoord[0] = l; - ii = NbFacettes; - while (ii >= 0 ) { - TriedronCoord[1] = rayon * sin(ii * Angle); - TriedronCoord[2] = rayon * cos(ii * Angle); - glVertex3dv( TriedronCoord ); - ii--; + resetTransformations (theWorkspace); + + // Set trihedron size parameters + GLdouble aScale = myScale; + aScale *= myRatio; + const Standard_Real aLineRatio = 0.75; + const GLdouble aLineLength = aScale * aLineRatio; + const GLdouble aConeDiametr = aScale * myDiameter; + const GLdouble aConeLength = aScale * (1.0 - aLineRatio); + const GLdouble aRayon = aScale / 30.0; + + // Create primitive line here for changing length + if (!myLine.IsInitialized()) + { + Handle(Graphic3d_ArrayOfSegments) aGraphicArray = new Graphic3d_ArrayOfSegments (2); + aGraphicArray->AddVertex (0.0, 0.0, 0.0); + aGraphicArray->AddVertex (0.0, 0.0, aLineLength); + myLine.InitBuffers (aContext, Graphic3d_TOPA_SEGMENTS, aGraphicArray->Indices(), + aGraphicArray->Attributes(), + aGraphicArray->Bounds()); } - glEnd(); - - /* fleche en Y */ - glBegin(GL_TRIANGLE_FAN); - glVertex3dv( TriedronAxeY ); - TriedronCoord[1] = l; - ii = NbFacettes; - while (ii >= 0 ) { - TriedronCoord[0] = rayon * cos(ii * Angle); - TriedronCoord[2] = rayon * sin(ii * Angle); - glVertex3dv( TriedronCoord ); - ii--; + + if (!myCircle.IsInitialized()) + { + const Standard_Integer THE_CIRCLE_SERMENTS_NB = 24; + Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2); + + const Standard_Real THE_CIRCLE_SEGMENT_ANGLE = 2.0 * M_PI / THE_CIRCLE_SERMENTS_NB; + for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt) + { + anCircleArray->AddVertex (aRayon * sin (anIt * THE_CIRCLE_SEGMENT_ANGLE), + aRayon * cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0); + } + anCircleArray->AddVertex (aRayon * sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), + aRayon * cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0); + + myCircle.InitBuffers (aContext, Graphic3d_TOPA_POLYLINES, anCircleArray->Indices(), + anCircleArray->Attributes(), anCircleArray->Bounds()); } - glEnd(); - - /* fleche en Z */ - glBegin(GL_TRIANGLE_FAN); - glVertex3dv( TriedronAxeZ ); - TriedronCoord[2] = l; - ii = NbFacettes; - while (ii >= 0 ) { - TriedronCoord[0] = rayon * sin(ii * Angle); - TriedronCoord[1] = rayon * cos(ii * Angle); - glVertex3dv( TriedronCoord ); - ii--; + + if (!myDisk.IsDefined()) + { + myDisk.Init (0.0, static_cast (aConeDiametr), myNbFacettes, 1); } - glEnd(); - - /* dessin de l'origine */ - TriedronCoord[2] = 0.0 ; - ii = 24 ; - const double Angle1 = 2. * M_PI/ ii; - glBegin(GL_LINE_LOOP); - while (ii >= 0 ) { - TriedronCoord[0] = rayon * sin(ii * Angle1); - TriedronCoord[1] = rayon * cos(ii * Angle1); - glVertex3dv( TriedronCoord ); - ii--; + + if (!myCone.IsDefined()) + { + myCone.Init (static_cast (aConeDiametr), 0.0f, static_cast (aConeLength), myNbFacettes, 1); } - glEnd(); - // draw axes labels - myLabelX.SetPosition (OpenGl_Vec3(float(L + rayon), 0.0f, float(-rayon))); - myLabelY.SetPosition (OpenGl_Vec3(float(rayon), float(L + 3.0 * rayon), float(2.0 * rayon))); - myLabelZ.SetPosition (OpenGl_Vec3(float(-2.0 * rayon), float(0.5 * rayon), float(L + 3.0 * rayon))); + OpenGl_AspectFace anAspectX; + OpenGl_AspectFace anAspectY; + OpenGl_AspectFace anAspectZ; + OpenGl_AspectLine anAspectLine; + memcpy (anAspectX.ChangeIntFront().matcol.rgb, myXColor.rgb, sizeof (TEL_COLOUR)); + memcpy (anAspectY.ChangeIntFront().matcol.rgb, myYColor.rgb, sizeof (TEL_COLOUR)); + memcpy (anAspectZ.ChangeIntFront().matcol.rgb, myZColor.rgb, sizeof (TEL_COLOUR)); + OpenGl_Mat4d aModelMatrix; + aModelMatrix.Convert (aContext->WorldViewState.Current()); + OpenGl_Mat4d aModelViewX (aModelMatrix); + OpenGl_Mat4d aModelViewY (aModelMatrix); + OpenGl_Mat4d aModelViewZ (aModelMatrix); + + // Set line aspect + const OpenGl_AspectLine* aCurrentAspectLine = theWorkspace->AspectLine (Standard_True); + CALL_DEF_CONTEXTLINE aLineAspect = {1, 1, { 1.F, 1.F, 1.F }, aCurrentAspectLine->Type(), aCurrentAspectLine->Width()}; + aLineAspect.Color.r = myZColor.rgb[0]; + aLineAspect.Color.g = myZColor.rgb[1]; + aLineAspect.Color.b = myZColor.rgb[2]; + anAspectLine.SetAspect (aLineAspect); + + // Disable depth test and face culling + GLboolean wasDepthMaskEnabled = GL_FALSE; + GLint aDepthFuncBack = 0, aCullFaceModeBack = GL_BACK; + const GLboolean wasDepthEnabled = aContext->core11fwd->glIsEnabled (GL_DEPTH_TEST); + const GLboolean wasCullFaceEnabled = aContext->core11fwd->glIsEnabled (GL_CULL_FACE); + aContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncBack); + aContext->core11fwd->glGetIntegerv (GL_CULL_FACE_MODE, &aCullFaceModeBack); + aContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &wasDepthMaskEnabled); + if (!wasDepthEnabled) + { + aContext->core11fwd->glEnable (GL_DEPTH_TEST); + aContext->core11fwd->glClear (GL_DEPTH_BUFFER_BIT); + } + if (!wasDepthMaskEnabled) + { + aContext->core11fwd->glDepthMask (GL_TRUE); + } + aContext->core11fwd->glCullFace (GL_BACK); + if (!wasCullFaceEnabled) + { + aContext->core11fwd->glEnable (GL_CULL_FACE); + } + + // Origin + myCircle.Render (theWorkspace); + + // Z axis + const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace(&anAspectZ); + theWorkspace->SetAspectLine (&anAspectLine); + myLine.Render (theWorkspace); + OpenGl_Utils::Translate (aModelViewZ, 0.0, 0.0, aLineLength); + aContext->WorldViewState.SetCurrent(aModelViewZ); + aContext->ApplyWorldViewMatrix(); + myDisk.Render (theWorkspace); + myCone.Render (theWorkspace); + + // X axis + theWorkspace->SetAspectFace (&anAspectX); + OpenGl_Utils::Rotate (aModelViewX, 90.0, 0.0, aScale, 0.0); + aContext->WorldViewState.SetCurrent (aModelViewX); + aContext->ApplyWorldViewMatrix(); + + aLineAspect.Color.r = myXColor.rgb[0]; + aLineAspect.Color.g = myXColor.rgb[1]; + aLineAspect.Color.b = myXColor.rgb[2]; + anAspectLine.SetAspect (aLineAspect); + theWorkspace->SetAspectLine (&anAspectLine); + myLine.Render (theWorkspace); + OpenGl_Utils::Translate (aModelViewX, 0.0, 0.0, aLineLength); + aContext->WorldViewState.SetCurrent (aModelViewX); + aContext->ApplyWorldViewMatrix(); + myDisk.Render (theWorkspace); + myCone.Render (theWorkspace); + + // Y axis + theWorkspace->SetAspectFace (&anAspectY); + OpenGl_Utils::Rotate (aModelViewY, -90.0, aScale, 0.0, 0.0); + aContext->WorldViewState.SetCurrent (aModelViewY); + aContext->ApplyWorldViewMatrix(); + + aLineAspect.Color.r = myYColor.rgb[0]; + aLineAspect.Color.g = myYColor.rgb[1]; + aLineAspect.Color.b = myYColor.rgb[2]; + anAspectLine.SetAspect (aLineAspect); + theWorkspace->SetAspectLine (&anAspectLine); + myLine.Render (theWorkspace); + OpenGl_Utils::Translate (aModelViewY, 0.0, 0.0, aLineLength); + aContext->WorldViewState.SetCurrent (aModelViewY); + aContext->ApplyWorldViewMatrix(); + myDisk.Render (theWorkspace); + myCone.Render (theWorkspace); + + // Restore aspects + theWorkspace->SetAspectFace (anOldAspectFace); + + if (!wasDepthEnabled) + { + aContext->core11fwd->glDisable (GL_DEPTH_TEST); + } + if (!wasDepthMaskEnabled) + { + aContext->core11fwd->glDepthMask (GL_FALSE); + } + if (!wasCullFaceEnabled) + { + aContext->core11fwd->glDisable (GL_CULL_FACE); + } + aContext->core11fwd->glCullFace (aCullFaceModeBack); + + // Always write the text + aContext->core11fwd->glDepthFunc (GL_ALWAYS); + + // Render labels + myLabelX.SetPosition (OpenGl_Vec3 (float (aScale + 2.0 * aRayon), 0.0f, float (-aRayon))); + myLabelY.SetPosition (OpenGl_Vec3 (float (aRayon), float (aScale + 3.0 * aRayon), float (2.0 * aRayon))); + myLabelZ.SetPosition (OpenGl_Vec3 (float (-2.0 * aRayon), float (0.5 * aRayon), float (aScale + 3.0 * aRayon))); + aContext->WorldViewState.SetCurrent (aModelMatrix); + aContext->ApplyWorldViewMatrix(); myLabelX.Render (theWorkspace); myLabelY.Render (theWorkspace); myLabelZ.Render (theWorkspace); - /* - * restauration du contexte des matrices - */ - + aContext->core11fwd->glDepthFunc (aDepthFuncBack); aContext->WorldViewState.Pop(); aContext->ProjectionState.Pop(); aContext->ApplyProjectionMatrix(); -#endif } // ======================================================================= @@ -286,87 +344,14 @@ void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) con void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspace) const { Handle(OpenGl_Context) aContext = theWorkspace->GetGlContext(); - const Handle(OpenGl_View)& aView = theWorkspace->ActiveView(); - - OpenGl_Mat4d aModelMatrix, aProjMatrix; aContext->WorldViewState.Push(); aContext->ProjectionState.Push(); - aModelMatrix.Convert (aContext->WorldViewState.Current()); - GLdouble U = 1.0; - GLdouble V = 1.0; - if (aView->Height() < aView->Width()) - { - V = aView->Width() / aView->Height(); - } - else - { - U = aView->Height() / aView->Width(); - } + resetTransformations (theWorkspace); GLdouble aScale = myScale; - - // Annulate translation matrix - aModelMatrix.ChangeValue (0, 3) = 0.0; - aModelMatrix.ChangeValue (1, 3) = 0.0; - aModelMatrix.ChangeValue (2, 3) = 0.0; - - aProjMatrix.ChangeValue (0, 0) = 2.0 / U; - aProjMatrix.ChangeValue (1, 0) = 0.0; - aProjMatrix.ChangeValue (2, 0) = 0.0; - aProjMatrix.ChangeValue (3, 0) = 0.0; - - aProjMatrix.ChangeValue (0, 1) = 0.0; - aProjMatrix.ChangeValue (1, 1) = 2.0 / V; - aProjMatrix.ChangeValue (2, 1) = 0.0; - aProjMatrix.ChangeValue (3, 1) = 0.0; - - aProjMatrix.ChangeValue (0, 2) = 0.0; - aProjMatrix.ChangeValue (1, 2) = 0.0; - aProjMatrix.ChangeValue (2, 2) = -2.0 * 1e-2; - aProjMatrix.ChangeValue (3, 2) = 0.0; - - aProjMatrix.ChangeValue (0, 3) = 0.0; - aProjMatrix.ChangeValue (1, 3) = 0.0; - aProjMatrix.ChangeValue (2, 3) = 0.0; - aProjMatrix.ChangeValue (3, 3) = 1.0; - - // Define position in the view - switch (myPos) - { - case Aspect_TOTP_LEFT_LOWER: - { - OpenGl_Utils::Translate (aProjMatrix, - -0.5 * U + aScale, -0.5 * V + aScale, 0.0); - break; - } - case Aspect_TOTP_LEFT_UPPER: - { - OpenGl_Utils::Translate (aProjMatrix, - -0.5 * U + aScale, 0.5 * V - aScale - aScale / 3.0, 0.0); - break; - } - case Aspect_TOTP_RIGHT_LOWER: - { - OpenGl_Utils::Translate (aProjMatrix, - 0.5 * U - aScale - aScale / 3.0, -0.5 * V + aScale, 0.0); - break; - } - case Aspect_TOTP_RIGHT_UPPER: - { - OpenGl_Utils::Translate (aProjMatrix, - 0.5 * U - aScale - aScale / 3.0, 0.5 * V - aScale - aScale / 3.0, 0.0); - break; - } - //case Aspect_TOTP_CENTER: - default: - break; - } aScale *= myRatio; - aContext->ProjectionState.SetCurrent (aProjMatrix); - aContext->ApplyProjectionMatrix(); - const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True); const TEL_COLOUR& aLineColor = anAspectLine->Color(); @@ -435,6 +420,9 @@ void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspa memcpy (anAspectY.ChangeIntFront().matcol.rgb, myYColor.rgb, sizeof (TEL_COLOUR)); memcpy (anAspectZ.ChangeIntFront().matcol.rgb, myZColor.rgb, sizeof (TEL_COLOUR)); memcpy (anAspectC.ChangeIntFront().matcol.rgb, aLineColor.rgb, sizeof (TEL_COLOUR)); + + OpenGl_Mat4d aModelMatrix; + aModelMatrix.Convert (aContext->WorldViewState.Current()); for (Standard_Integer aPass = 0; aPass < 2; ++aPass) { OpenGl_Mat4d aModelViewX (aModelMatrix); @@ -533,7 +521,9 @@ OpenGl_Trihedron::OpenGl_Trihedron (const Aspect_TypeOfTriedronPosition thePosit myIsWireframe (theAsWireframe), myLabelX ("X", OpenGl_Vec3(1.0f, 0.0f, 0.0f), THE_LABEL_PARAMS), myLabelY ("Y", OpenGl_Vec3(0.0f, 1.0f, 0.0f), THE_LABEL_PARAMS), - myLabelZ ("Z", OpenGl_Vec3(0.0f, 0.0f, 1.0f), THE_LABEL_PARAMS) + myLabelZ ("Z", OpenGl_Vec3(0.0f, 0.0f, 1.0f), THE_LABEL_PARAMS), + myLine (NULL), // do not register arrays UID - trihedron is not intended to be drawn by Ray Tracing engine + myCircle (NULL) { Standard_Real R,G,B; Quantity_Color aColor (theColor); @@ -566,6 +556,7 @@ OpenGl_Trihedron::OpenGl_Trihedron (const Aspect_TypeOfTriedronPosition thePosit // ======================================================================= OpenGl_Trihedron::~OpenGl_Trihedron() { + // } // ======================================================================= @@ -583,6 +574,8 @@ void OpenGl_Trihedron::Release (OpenGl_Context* theCtx) myDisk .Release (theCtx); mySphere .Release (theCtx); myCylinder.Release (theCtx); + myLine.Release (theCtx); + myCircle.Release (theCtx); } // ======================================================================= @@ -631,7 +624,7 @@ void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) con /*----------------------------------------------------------------------*/ //call_ztriedron_setup void OpenGl_Trihedron::Setup (const Quantity_NameOfColor XColor, const Quantity_NameOfColor YColor, const Quantity_NameOfColor ZColor, - const Standard_Real SizeRatio, const Standard_Real AxisDiametr, const Standard_Integer NbFacettes) + const Standard_Real SizeRatio, const Standard_Real AxisDiametr, const Standard_Integer NbFacettes) { Standard_Real R,G,B; diff --git a/src/OpenGl/OpenGl_Trihedron.hxx b/src/OpenGl/OpenGl_Trihedron.hxx index 520a92b44c..adc7ad1c22 100755 --- a/src/OpenGl/OpenGl_Trihedron.hxx +++ b/src/OpenGl/OpenGl_Trihedron.hxx @@ -32,29 +32,34 @@ class OpenGl_Trihedron : public OpenGl_Element { public: - static void Setup (const Quantity_NameOfColor theXColor, - const Quantity_NameOfColor theYColor, - const Quantity_NameOfColor theZColor, - const Standard_Real theSizeRatio, - const Standard_Real theAxisDiametr, - const Standard_Integer theNbFacettes); + static void Setup(const Quantity_NameOfColor theXColor, + const Quantity_NameOfColor theYColor, + const Quantity_NameOfColor theZColor, + const Standard_Real theSizeRatio, + const Standard_Real theAxisDiametr, + const Standard_Integer theNbFacettes); public: - OpenGl_Trihedron (const Aspect_TypeOfTriedronPosition thePosition, - const Quantity_NameOfColor theColor, - const Standard_Real theScale, - const Standard_Boolean theAsWireframe); + OpenGl_Trihedron(const Aspect_TypeOfTriedronPosition thePosition, + const Quantity_NameOfColor theColor, + const Standard_Real theScale, + const Standard_Boolean theAsWireframe); - virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; - virtual void Release (OpenGl_Context* theCtx); + virtual void Render(const Handle(OpenGl_Workspace)& theWorkspace) const; + virtual void Release(OpenGl_Context* theCtx); protected: virtual ~OpenGl_Trihedron(); - void redraw (const Handle(OpenGl_Workspace)& theWorkspace) const; - void redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspace) const; + void redraw(const Handle(OpenGl_Workspace)& theWorkspace) const; + void redrawZBuffer(const Handle(OpenGl_Workspace)& theWorkspace) const; + + //! Resets current model-view and projection transfprmations and sets + //! translation for trihedron position + //! @sa Aspect_TypeOfTriedronPosition + void resetTransformations (const Handle(OpenGl_Workspace)& theWorkspace) const; protected: @@ -69,15 +74,17 @@ protected: float myDiameter; int myNbFacettes; - OpenGl_AspectLine myAspectLine; - OpenGl_AspectText myAspectText; - mutable OpenGl_Text myLabelX; - mutable OpenGl_Text myLabelY; - mutable OpenGl_Text myLabelZ; - mutable OpenGl_Cylinder myCylinder; - mutable OpenGl_Sphere mySphere; - mutable OpenGl_Cylinder myCone; - mutable OpenGl_Disk myDisk; + OpenGl_AspectLine myAspectLine; + OpenGl_AspectText myAspectText; + mutable OpenGl_Text myLabelX; + mutable OpenGl_Text myLabelY; + mutable OpenGl_Text myLabelZ; + mutable OpenGl_Cylinder myCylinder; + mutable OpenGl_Sphere mySphere; + mutable OpenGl_Cylinder myCone; + mutable OpenGl_Disk myDisk; + mutable OpenGl_PrimitiveArray myLine; + mutable OpenGl_PrimitiveArray myCircle; public: diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 8f7c676b5c..d32f2f5078 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -2943,6 +2943,7 @@ static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, cons } V3dView->View()->ZFitAll(); + V3dView->Redraw(); return 0; } diff --git a/tests/bugs/vis/bug23484_1 b/tests/bugs/vis/bug23484_1 new file mode 100644 index 0000000000..25fd4282dd --- /dev/null +++ b/tests/bugs/vis/bug23484_1 @@ -0,0 +1,23 @@ +puts "============" +puts "OCC23484" +puts "============" +puts "" +############################################################################################ +puts "Visualization, TKOpenGl - primitive arrays to become the only way to render geometry" +puts "Tests wireframe trihedron rendering with primitive arrays" +############################################################################################ + +set anImage1 $imagedir/${casename}_1.png +set anImage2 $imagedir/${casename}_2.png + +vinit View1 +vfit +vaxo + +vzbufftrihedron left_lower 255 255 255 0.1 wireframe +vdump $anImage1 + +vzbufftrihedron center 255 255 255 0.1 wireframe +vdump $anImage2 + +vclear diff --git a/tests/bugs/vis/bug23484_2 b/tests/bugs/vis/bug23484_2 new file mode 100644 index 0000000000..56409a20a9 --- /dev/null +++ b/tests/bugs/vis/bug23484_2 @@ -0,0 +1,27 @@ +puts "============" +puts "OCC23484" +puts "============" +puts "" +############################################################################################ +puts "Visualization, TKOpenGl - primitive arrays to become the only way to render geometry" +puts "Tests clipping plane rendering with primitive arrays" +############################################################################################ + +set anImage $imagedir/${casename}_1.png + +vinit View1 +vclear +vaxo +vsetdispmode 1 +box b 1 1 1 +vdisplay b +vfit + +vclipplane create pln +vclipplane set pln view Driver1/Viewer1/View1 +vclipplane change pln equation 0 1 0 -0.5 +vclipplane change pln capping on + +vdump $anImage + +vclear -- 2.20.1