diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 13c448d4c2..3b2fe4241e 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -37,6 +37,7 @@ Graphic3d_Buffer.hxx Graphic3d_BufferType.hxx Graphic3d_Camera.cxx Graphic3d_Camera.hxx +Graphic3d_CameraTile.hxx Graphic3d_CappingFlags.hxx Graphic3d_CLight.hxx Graphic3d_ClipPlane.cxx @@ -132,6 +133,7 @@ Graphic3d_TypeOfBackground.hxx Graphic3d_TypeOfComposition.hxx Graphic3d_TypeOfConnection.hxx Graphic3d_TypeOfLightSource.hxx +Graphic3d_TypeOfLimit.hxx Graphic3d_TypeOfMaterial.hxx Graphic3d_TypeOfPrimitiveArray.hxx Graphic3d_TypeOfReflection.hxx diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index 2288278062..754af59094 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -112,6 +112,7 @@ void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOther SetZFocus (theOtherCamera->ZFocusType(), theOtherCamera->ZFocus()); SetIOD (theOtherCamera->GetIODType(), theOtherCamera->IOD()); SetProjectionType (theOtherCamera->ProjectionType()); + SetTile (theOtherCamera->myTile); } // ======================================================================= @@ -425,6 +426,21 @@ void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD InvalidateProjection(); } +// ======================================================================= +// function : SetTile +// purpose : +// ======================================================================= +void Graphic3d_Camera::SetTile (const Graphic3d_CameraTile& theTile) +{ + if (myTile == theTile) + { + return; + } + + myTile = theTile; + InvalidateProjection(); +} + // ======================================================================= // function : OrthogonalizeUp // purpose : @@ -824,6 +840,17 @@ Graphic3d_Camera::TransformMatrices& ? static_cast (myZFocus * Distance()) : static_cast (myZFocus); + if (myTile.IsValid()) + { + const Elem_t aDXFull = Elem_t(2) * aDXHalf; + const Elem_t aDYFull = Elem_t(2) * aDYHalf; + const Graphic3d_Vec2i anOffset = myTile.OffsetLowerLeft(); + aLeft = -aDXHalf + aDXFull * static_cast (anOffset.x()) / static_cast (myTile.TotalSize.x()); + aRight = -aDXHalf + aDXFull * static_cast (anOffset.x() + myTile.TileSize.x()) / static_cast (myTile.TotalSize.x()); + aBot = -aDYHalf + aDYFull * static_cast (anOffset.y()) / static_cast (myTile.TotalSize.y()); + aTop = -aDYHalf + aDYFull * static_cast (anOffset.y() + myTile.TileSize.y()) / static_cast (myTile.TotalSize.y()); + } + switch (myProjType) { case Projection_Orthographic : diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index dfb90bbce4..fe9e44b658 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -16,6 +16,7 @@ #ifndef _Graphic3d_Camera_HeaderFile #define _Graphic3d_Camera_HeaderFile +#include #include #include #include @@ -375,6 +376,14 @@ public: return myIODType; } + //! Get current tile. + const Graphic3d_CameraTile& Tile() const { return myTile; } + + //! Sets the Tile defining the drawing sub-area within View. + //! Note that tile defining a region outside the view boundaries is also valid - use method Graphic3d_CameraTile::Cropped() to assign a cropped copy. + //! @param theTile tile definition + Standard_EXPORT void SetTile (const Graphic3d_CameraTile& theTile); + //! @name Basic camera operations public: @@ -639,6 +648,8 @@ private: Standard_Real myIOD; //!< Intraocular distance value. IODType myIODType; //!< Intraocular distance definition type. + Graphic3d_CameraTile myTile;//!< Tile defining sub-area for drawing + mutable TransformMatrices myMatricesD; mutable TransformMatrices myMatricesF; diff --git a/src/Graphic3d/Graphic3d_CameraTile.hxx b/src/Graphic3d/Graphic3d_CameraTile.hxx new file mode 100644 index 0000000000..9ad8051185 --- /dev/null +++ b/src/Graphic3d/Graphic3d_CameraTile.hxx @@ -0,0 +1,88 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_CameraTile_HeaderFile +#define _Graphic3d_CameraTile_HeaderFile + +#include +#include +#include + +//! Class defines the area (Tile) inside a view. +class Graphic3d_CameraTile +{ +public: + + Graphic3d_Vec2i TotalSize; //!< total size of the View area, in pixels + Graphic3d_Vec2i TileSize; //!< size of the Tile, in pixels + Graphic3d_Vec2i Offset; //!< the lower-left corner of the Tile relative to the View area (or upper-left if IsTopDown is true), in pixels + bool IsTopDown; //!< indicate the offset coordinate system - lower-left (default) or top-down + +public: + + //! Default constructor. + //! Initializes the empty Tile of zero size and lower-left offset orientation. + //! Such Tile is considered uninitialized (invalid). + Graphic3d_CameraTile() : IsTopDown (false) {} + + //! Return true if Tile has been defined. + bool IsValid() const + { + return TotalSize.x() > 0 && TotalSize.y() > 0 + && TileSize.x() > 0 && TileSize.y() > 0; + } + + //! Return offset position from lower-left corner. + Graphic3d_Vec2i OffsetLowerLeft() const + { + return Graphic3d_Vec2i (Offset.x(), + !IsTopDown + ? Offset.y() + : TotalSize.y() - Offset.y() - 1); + } + + //! Return the copy cropped by total size + Graphic3d_CameraTile Cropped() const + { + Graphic3d_CameraTile aTile = *this; + if (!IsValid()) + { + return aTile; + } + + aTile.Offset.x() = Max (Offset.x(), 0); + aTile.Offset.y() = Max (Offset.y(), 0); + + const Standard_Integer anX = Min (Offset.x() + TileSize.x(), TotalSize.x()); + const Standard_Integer anY = Min (Offset.y() + TileSize.y(), TotalSize.y()); + aTile.TileSize.x() = anX - Offset.x(); + aTile.TileSize.y() = anY - Offset.y(); + return aTile; + } + + //! Equality check. + bool operator== (const Graphic3d_CameraTile& theOther) const + { + const Graphic3d_Vec2i anOffset1 = OffsetLowerLeft(); + const Graphic3d_Vec2i anOffset2 = theOther.OffsetLowerLeft(); + return TotalSize.x() == theOther.TotalSize.x() + && TotalSize.y() == theOther.TotalSize.y() + && TileSize.x() == theOther.TileSize.x() + && TileSize.y() == theOther.TileSize.y() + && anOffset1.x() == anOffset2.x() + && anOffset1.y() == anOffset2.y(); + } + +}; + +#endif // _Graphic3d_CameraTile_HeaderFile diff --git a/src/Graphic3d/Graphic3d_GraphicDriver.hxx b/src/Graphic3d/Graphic3d_GraphicDriver.hxx index 2f7dede872..01fddf393b 100644 --- a/src/Graphic3d/Graphic3d_GraphicDriver.hxx +++ b/src/Graphic3d/Graphic3d_GraphicDriver.hxx @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -68,16 +69,20 @@ class Graphic3d_GraphicDriver : public MMgt_TShared public: - - //! call_togl_inquirelight - virtual Standard_Integer InquireLightLimit() = 0; - - //! call_togl_inquireplane - virtual Standard_Integer InquirePlaneLimit() = 0; - - //! call_togl_inquireview - virtual Standard_Integer InquireViewLimit() = 0; - + //! Request limit of graphic resource of specific type. + virtual Standard_Integer InquireLimit (const Graphic3d_TypeOfLimit theType) const = 0; + + //! Request maximum number of active light sources supported by driver and hardware. + Standard_Integer InquireLightLimit() const { return InquireLimit (Graphic3d_TypeOfLimit_MaxNbLights); } + + //! Request maximum number of active clipping planes supported by driver and hardware. + Standard_Integer InquirePlaneLimit() const { return InquireLimit (Graphic3d_TypeOfLimit_MaxNbClipPlanes); } + + //! Request maximum number of views supported by driver. + Standard_Integer InquireViewLimit() const { return InquireLimit (Graphic3d_TypeOfLimit_MaxNbViews); } + +public: + //! Creates new empty graphic structure virtual Handle(Graphic3d_CStructure) CreateStructure (const Handle(Graphic3d_StructureManager)& theManager) = 0; diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx index fb3058a483..6ce52b0e13 100644 --- a/src/Graphic3d/Graphic3d_TransformPers.hxx +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -115,6 +115,7 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, return; } + const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight; if (Flags == Graphic3d_TMF_TriedronPers) { // reset Z focus for trihedron persistence @@ -126,7 +127,7 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, // scale factor to pixels const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); - const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(theViewportHeight); + const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); // offset from the corner const Standard_Real anOffset = Point.z() * aScale; @@ -171,7 +172,7 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, // scale factor to pixels const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); - const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(theViewportHeight); + const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); gp_XYZ aCenter (0.0, 0.0, -aFocus); if (Point.x() != 0.0) { diff --git a/src/Graphic3d/Graphic3d_TransformUtils.hxx b/src/Graphic3d/Graphic3d_TransformUtils.hxx index a2ba5cd526..85fc7d3283 100644 --- a/src/Graphic3d/Graphic3d_TransformUtils.hxx +++ b/src/Graphic3d/Graphic3d_TransformUtils.hxx @@ -15,6 +15,7 @@ #ifndef _Graphic3d_TransformUtils_HeaderFile #define _Graphic3d_TransformUtils_HeaderFile +#include #include #include // M_PI diff --git a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx new file mode 100644 index 0000000000..8cc1cbde68 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx @@ -0,0 +1,28 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_TypeOfLimit_HeaderFile +#define _Graphic3d_TypeOfLimit_HeaderFile + +//! Type of graphic resource limit. +enum Graphic3d_TypeOfLimit +{ + Graphic3d_TypeOfLimit_MaxNbLights, //!< maximum number of active light sources + Graphic3d_TypeOfLimit_MaxNbClipPlanes, //!< maximum number of active clipping planes + Graphic3d_TypeOfLimit_MaxNbViews, //!< maximum number of views + Graphic3d_TypeOfLimit_MaxTextureSize, //!< maximum size of texture + Graphic3d_TypeOfLimit_MaxMsaa, //!< maximum number of MSAA samples + Graphic3d_TypeOfLimit_NB //!< number of elements in this enumeration +}; + +#endif // _Graphic3d_TypeOfLimit_HeaderFile diff --git a/src/OpenGl/OpenGl_BackgroundArray.cxx b/src/OpenGl/OpenGl_BackgroundArray.cxx index 63f36bfc38..0dce18bb4d 100644 --- a/src/OpenGl/OpenGl_BackgroundArray.cxx +++ b/src/OpenGl/OpenGl_BackgroundArray.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include // ======================================================================= @@ -26,11 +27,11 @@ // ======================================================================= OpenGl_BackgroundArray::OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground theType) : OpenGl_PrimitiveArray (NULL, Graphic3d_TOPA_TRIANGLESTRIPS, NULL, NULL, NULL), - myToUpdate (Standard_False), myType (theType), + myFillMethod (Aspect_FM_NONE), myViewWidth (0), myViewHeight (0), - myFillMethod (Aspect_FM_NONE) + myToUpdate (Standard_False) { Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16); myAttribs = new Graphic3d_Buffer (anAlloc); @@ -40,6 +41,18 @@ OpenGl_BackgroundArray::OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground myGradientParams.color1 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); myGradientParams.color2 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); myGradientParams.type = Aspect_GFM_NONE; + + myTrsfPers.Flags = Graphic3d_TMF_2d; + if (myType == Graphic3d_TOB_TEXTURE) + { + myTrsfPers.Point.x() = 0.0; + myTrsfPers.Point.y() = 0.0; + } + else + { + myTrsfPers.Point.x() = -1.0; + myTrsfPers.Point.y() = -1.0; + } } // ======================================================================= @@ -131,10 +144,10 @@ void OpenGl_BackgroundArray::invalidateData() } // ======================================================================= -// method : Init +// method : init // purpose : // ======================================================================= -Standard_Boolean OpenGl_BackgroundArray::Init (const Handle(OpenGl_Workspace)& theWorkspace) +Standard_Boolean OpenGl_BackgroundArray::init (const Handle(OpenGl_Workspace)& theWorkspace) const { switch (myType) { @@ -148,8 +161,6 @@ Standard_Boolean OpenGl_BackgroundArray::Init (const Handle(OpenGl_Workspace)& t } case Graphic3d_TOB_TEXTURE: { - myViewWidth = theWorkspace->Width(); - myViewHeight = theWorkspace->Height(); if (!createTextureArray (theWorkspace)) { return Standard_False; @@ -181,7 +192,7 @@ Standard_Boolean OpenGl_BackgroundArray::Init (const Handle(OpenGl_Workspace)& t // method : createGradientArray // purpose : // ======================================================================= -Standard_Boolean OpenGl_BackgroundArray::createGradientArray() +Standard_Boolean OpenGl_BackgroundArray::createGradientArray() const { // Initialize data for primitive array Graphic3d_Attribute aGragientAttribInfo[] = @@ -197,10 +208,10 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray() OpenGl_Vec2 aVertices[4] = { - OpenGl_Vec2( 1.0f, -1.0f), - OpenGl_Vec2( 1.0f, 1.0f), - OpenGl_Vec2(-1.0f, -1.0f), - OpenGl_Vec2(-1.0f, 1.0f) + OpenGl_Vec2(float(myViewWidth), 0.0f), + OpenGl_Vec2(float(myViewWidth), float(myViewHeight)), + OpenGl_Vec2(0.0f, 0.0f), + OpenGl_Vec2(0.0f, float(myViewHeight)) }; float* aCorners[4] = {}; @@ -249,10 +260,10 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray() } case Aspect_GFM_CORNER1: { - aVertices[0] = OpenGl_Vec2( 1.0f, 1.0f); - aVertices[1] = OpenGl_Vec2(-1.0f, 1.0f); - aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f); - aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f); + aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight)); + aVertices[1] = OpenGl_Vec2(0.0f, float(myViewHeight)); + aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f); + aVertices[3] = OpenGl_Vec2(0.0f, 0.0f); aCorners[0] = myGradientParams.color2.xyz().ChangeData(); aCorners[1] = myGradientParams.color1.xyz().ChangeData(); @@ -270,10 +281,10 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray() } case Aspect_GFM_CORNER3: { - aVertices[0] = OpenGl_Vec2( 1.0f, 1.0f); - aVertices[1] = OpenGl_Vec2(-1.0f, 1.0f); - aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f); - aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f); + aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight)); + aVertices[1] = OpenGl_Vec2(0.0f, float(myViewHeight)); + aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f); + aVertices[3] = OpenGl_Vec2(0.0f, 0.0f); aCorners[0] = myGradientParams.color2.xyz().ChangeData(); aCorners[1] = myGradientParams.color2.xyz().ChangeData(); @@ -311,7 +322,7 @@ Standard_Boolean OpenGl_BackgroundArray::createGradientArray() // method : createTextureArray // purpose : // ======================================================================= -Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) +Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) const { Graphic3d_Attribute aTextureAttribInfo[] = { @@ -328,8 +339,8 @@ Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl GLfloat aTexRangeY = 1.0f; // texture coordinate // Set up for stretching or tiling - GLfloat anOffsetX = 1.0f; - GLfloat anOffsetY = 1.0f; + GLfloat anOffsetX = 0.5f * (float )myViewWidth; + GLfloat anOffsetY = 0.5f * (float )myViewHeight; // Setting this coefficient to -1.0f allows to tile textures relatively to the top-left corner of the view // (value 1.0f corresponds to the initial behavior - tiling from the bottom-left corner) @@ -343,8 +354,8 @@ Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl if (myFillMethod == Aspect_FM_CENTERED) { - anOffsetX = aTextureWidth / (GLfloat )myViewWidth; - anOffsetY = aTextureHeight / (GLfloat )myViewHeight; + anOffsetX = 0.5f * aTextureWidth; + anOffsetY = 0.5f * aTextureHeight; } else if (myFillMethod == Aspect_FM_TILED) { @@ -375,3 +386,45 @@ Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl return Standard_True; } + +// ======================================================================= +// method : createTextureArray +// purpose : +// ======================================================================= +void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + Standard_Integer aViewSizeX = aCtx->Viewport()[2]; + Standard_Integer aViewSizeY = aCtx->Viewport()[3]; + if (theWorkspace->View()->Camera()->Tile().IsValid()) + { + aViewSizeX = theWorkspace->View()->Camera()->Tile().TotalSize.x(); + aViewSizeY = theWorkspace->View()->Camera()->Tile().TotalSize.y(); + } + if (myToUpdate + || myViewWidth != aViewSizeX + || myViewHeight != aViewSizeY) + { + myViewWidth = aViewSizeX; + myViewHeight = aViewSizeY; + init (theWorkspace); + } + + OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current(); + OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current(); + myTrsfPers.Apply (theWorkspace->View()->Camera(), aProjection, aWorldView, + aCtx->Viewport()[2], aCtx->Viewport()[3]); + + aCtx->ProjectionState.Push(); + aCtx->WorldViewState.Push(); + aCtx->ProjectionState.SetCurrent (aProjection); + aCtx->WorldViewState.SetCurrent (aWorldView); + aCtx->ApplyProjectionMatrix(); + aCtx->ApplyModelViewMatrix(); + + OpenGl_PrimitiveArray::Render (theWorkspace); + + aCtx->ProjectionState.Pop(); + aCtx->WorldViewState.Pop(); + aCtx->ApplyProjectionMatrix(); +} diff --git a/src/OpenGl/OpenGl_BackgroundArray.hxx b/src/OpenGl/OpenGl_BackgroundArray.hxx index efdb1b6094..8458736415 100644 --- a/src/OpenGl/OpenGl_BackgroundArray.hxx +++ b/src/OpenGl/OpenGl_BackgroundArray.hxx @@ -33,14 +33,12 @@ public: //! Main constructor. Standard_EXPORT OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground theType); + //! Render primitives to the window + Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const Standard_OVERRIDE; + //! Check if background parameters are set properly Standard_EXPORT bool IsDefined() const; - //! Fill attributes arrays for background array according to its type: - //! - for gradient background its attributes consist of colors and gradient coordinates - //! - for texture one its attributes consist of position and texure coordinates. - Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Workspace)& theWorkspace); - //! Sets background texture parameters Standard_EXPORT void SetTextureParameters (const Aspect_FillMethod theFillMethod); @@ -64,18 +62,6 @@ public: const Quantity_Color& theColor2, const Aspect_GradientFillMethod theType); - //! Shows if array parameters were changed - Standard_Boolean IsDataChanged() const { return myToUpdate; } - - //! Shows if view sizes were changed - //! (texture coordinates is no be changed) - Standard_Boolean IsViewSizeChanged (const Handle(OpenGl_Workspace)& theWorkspace) const - { - return myType == Graphic3d_TOB_TEXTURE - && (myViewWidth != theWorkspace->Width() - || myViewHeight != theWorkspace->Height()); - } - protected: //! @name Internal structure for storing gradient parameters struct OpenGl_GradientParameters @@ -87,12 +73,17 @@ protected: //! @name Internal structure for storing gradient parameters protected: + //! Fill attributes arrays for background array according to its type: + //! - for gradient background its attributes consist of colors and gradient coordinates + //! - for texture one its attributes consist of position and texture coordinates. + Standard_EXPORT Standard_Boolean init (const Handle(OpenGl_Workspace)& theWorkspace) const; + //! Initializes gradient arrays. - Standard_EXPORT Standard_Boolean createGradientArray(); + Standard_EXPORT Standard_Boolean createGradientArray() const; //! Initializes texture arrays. //! @param theWorkspace OpenGl workspace that stores texture in the current enabled face aspect. - Standard_EXPORT Standard_Boolean createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace); + Standard_EXPORT Standard_Boolean createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) const; //! Marks array parameters as changed, //! on next rendering stage array data is to be updated. @@ -100,12 +91,13 @@ protected: protected: - Standard_Boolean myToUpdate; //!< Shows if array parameters were changed and data (myAttribs storage) is to be updated - Graphic3d_TypeOfBackground myType; //!< Type of background: texture or gradient. - Standard_Integer myViewWidth; //!< view width used for array initialization - Standard_Integer myViewHeight; //!< view height used for array initialization - Aspect_FillMethod myFillMethod; //!< Texture parameters - OpenGl_GradientParameters myGradientParams; //!< Gradient parameters + Graphic3d_TransformPers myTrsfPers; //!< transformation persistence + Graphic3d_TypeOfBackground myType; //!< Type of background: texture or gradient. + Aspect_FillMethod myFillMethod; //!< Texture parameters + mutable OpenGl_GradientParameters myGradientParams; //!< Gradient parameters + mutable Standard_Integer myViewWidth; //!< view width used for array initialization + mutable Standard_Integer myViewHeight; //!< view height used for array initialization + mutable Standard_Boolean myToUpdate; //!< Shows if array parameters were changed and data (myAttribs storage) is to be updated }; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index ccadcf60b7..42d5e6204b 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -154,6 +154,11 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myIsGlDebugCtx (Standard_False), myResolutionRatio (1.0f) { + myViewport[0] = 0; + myViewport[1] = 0; + myViewport[2] = 0; + myViewport[3] = 0; + // system-dependent fields #if defined(HAVE_EGL) myDisplay = (Aspect_Display )EGL_NO_DISPLAY; @@ -288,6 +293,19 @@ void OpenGl_Context::forcedRelease() } } +// ======================================================================= +// function : ResizeViewport +// purpose : +// ======================================================================= +void OpenGl_Context::ResizeViewport (const Standard_Integer* theRect) +{ + core11fwd->glViewport (theRect[0], theRect[1], theRect[2], theRect[3]); + myViewport[0] = theRect[0]; + myViewport[1] = theRect[1]; + myViewport[2] = theRect[2]; + myViewport[3] = theRect[3]; +} + #if !defined(GL_ES_VERSION_2_0) inline Standard_Integer stereoToMonoBuffer (const Standard_Integer theBuffer) { diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index e89b4d1bf5..6a53922816 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -542,6 +542,13 @@ public: public: //! @name methods to alter or retrieve current state + //! Return cached viewport definition (x, y, width, height). + const Standard_Integer* Viewport() const { return myViewport; } + + //! Resize the viewport (alias for glViewport). + //! @param theRect viewport definition (x, y, width, height) + Standard_EXPORT void ResizeViewport (const Standard_Integer theRect[4]); + //! Return active read buffer. Standard_Integer ReadBuffer() { return myReadBuffer; } @@ -763,6 +770,7 @@ private: //! @name fields tracking current state Handle(OpenGl_Sampler) myTexSampler; //!< currently active sampler object Handle(OpenGl_FrameBuffer) myDefaultFbo; //!< default Frame Buffer Object Handle(OpenGl_LineAttributes) myHatchStyles; //!< resource holding predefined hatch styles patterns + Standard_Integer myViewport[4]; //!< current viewport Standard_Integer myPointSpriteOrig; //!< GL_POINT_SPRITE_COORD_ORIGIN state (GL_UPPER_LEFT by default) Standard_Integer myRenderMode; //!< value for active rendering mode Standard_Integer myPolygonMode; //!< currently used polygon rasterization mode (glPolygonMode) diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index 8b813531ab..6f686a48d4 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -433,9 +433,10 @@ void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx) // function : SetupViewport // purpose : // ======================================================================= -void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& /*theGlCtx*/) +void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx) { - glViewport (0, 0, myVPSizeX, myVPSizeY); + const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY }; + theGlCtx->ResizeViewport (aViewport); } // ======================================================================= diff --git a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx index cd12dfb418..655043aecc 100755 --- a/src/OpenGl/OpenGl_GraduatedTrihedron.cxx +++ b/src/OpenGl/OpenGl_GraduatedTrihedron.cxx @@ -128,8 +128,7 @@ void OpenGl_GraduatedTrihedron::initGlResources (const Handle(OpenGl_Context)& t Standard_ShortReal OpenGl_GraduatedTrihedron::getNormal (const Handle(OpenGl_Context)& theContext, OpenGl_Vec3& theNormal) const { - GLint aViewport[4] = {}; - glGetIntegerv(GL_VIEWPORT, aViewport); + const Standard_Integer* aViewport = theContext->Viewport(); OpenGl_Mat4 aModelMatrix; OpenGl_Mat4 aProjMatrix; @@ -432,8 +431,6 @@ void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theW // Get current Model-View and Projection states OpenGl_Mat4 aModelMat; OpenGl_Mat4 aProjMat; - GLint aViewport[4]; - aContext->core11fwd->glGetIntegerv (GL_VIEWPORT, aViewport); aModelMat.Convert (aContext->WorldViewState.Current() * aContext->ModelWorldState.Current()); aProjMat .Convert (aContext->ProjectionState.Current()); @@ -441,7 +438,7 @@ void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theW OpenGl_Vec3 aEndPoint = -anAxis.Direction * myData.ArrowsLength(); OpenGl_Vec3 aWinPoint; Graphic3d_TransformUtils::Project (aEndPoint.x(), aEndPoint.y(), aEndPoint.z(), - aModelMat, aProjMat, aViewport, + aModelMat, aProjMat, aContext->Viewport(), aWinPoint.x(), aWinPoint.y(), aWinPoint.z()); aContext->ModelWorldState.SetIdentity(); @@ -451,7 +448,7 @@ void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theW // Get start point of zoom persistent arrow OpenGl_Vec3 anArrowStart; Graphic3d_TransformUtils::UnProject (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(), - aModelMat, aProjMat, aViewport, + aModelMat, aProjMat, aContext->Viewport(), anArrowStart.x(), anArrowStart.y(), anArrowStart.z()); // Render axis line aModelMat = theMat; diff --git a/src/OpenGl/OpenGl_GraphicDriver.cxx b/src/OpenGl/OpenGl_GraphicDriver.cxx index 1c1081bea3..83cf40da17 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver.cxx @@ -363,31 +363,28 @@ Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display t #endif // ======================================================================= -// function : InquireLightLimit +// function : InquireLimit // purpose : // ======================================================================= -Standard_Integer OpenGl_GraphicDriver::InquireLightLimit() -{ - return OpenGLMaxLights; -} - -// ======================================================================= -// function : InquireViewLimit -// purpose : -// ======================================================================= -Standard_Integer OpenGl_GraphicDriver::InquireViewLimit() -{ - return 10000; -} - -// ======================================================================= -// function : InquirePlaneLimit -// purpose : -// ======================================================================= -Standard_Integer OpenGl_GraphicDriver::InquirePlaneLimit() +Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit theType) const { const Handle(OpenGl_Context)& aCtx = GetSharedContext(); - return aCtx.IsNull() ? aCtx->MaxClipPlanes() : 0; + switch (theType) + { + case Graphic3d_TypeOfLimit_MaxNbLights: + return OpenGLMaxLights; + case Graphic3d_TypeOfLimit_MaxNbClipPlanes: + return !aCtx.IsNull() ? aCtx->MaxClipPlanes() : 0; + case Graphic3d_TypeOfLimit_MaxNbViews: + return 10000; + case Graphic3d_TypeOfLimit_MaxTextureSize: + return !aCtx.IsNull() ? aCtx->MaxTextureSize() : 1024; + case Graphic3d_TypeOfLimit_MaxMsaa: + return !aCtx.IsNull() ? aCtx->MaxMsaaSamples() : 0; + case Graphic3d_TypeOfLimit_NB: + return 0; + } + return 0; } // ======================================================================= diff --git a/src/OpenGl/OpenGl_GraphicDriver.hxx b/src/OpenGl/OpenGl_GraphicDriver.hxx index b0e5a00c63..29a40b9c3a 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.hxx +++ b/src/OpenGl/OpenGl_GraphicDriver.hxx @@ -110,8 +110,8 @@ public: void* theEglConfig); #endif - Standard_EXPORT Standard_Integer InquireLightLimit () Standard_OVERRIDE; - Standard_EXPORT Standard_Integer InquireViewLimit () Standard_OVERRIDE; + //! Request limit of graphic resource of specific type. + Standard_EXPORT virtual Standard_Integer InquireLimit (const Graphic3d_TypeOfLimit theType) const Standard_OVERRIDE; public: @@ -134,8 +134,6 @@ public: Standard_ShortReal& theAscent, Standard_ShortReal& theDescent) const Standard_OVERRIDE; - Standard_EXPORT Standard_Integer InquirePlaneLimit() Standard_OVERRIDE; - Standard_EXPORT Standard_ShortReal DefaultTextHeight() const Standard_OVERRIDE; Standard_EXPORT Standard_Boolean ViewExists (const Handle(Aspect_Window)& theWindow, Handle(Graphic3d_CView)& theView) Standard_OVERRIDE; diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 1355473699..cd7139c905 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -475,7 +475,8 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con { OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current(); OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current(); - TransformPersistence.Apply (theWorkspace->View()->Camera(), aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height()); + TransformPersistence.Apply (theWorkspace->View()->Camera(), aProjection, aWorldView, + aCtx->Viewport()[2], aCtx->Viewport()[3]); aCtx->ProjectionState.Push(); aCtx->WorldViewState.Push(); diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 039e56070b..157be5092e 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -503,7 +503,7 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx, myWinZ + theDVec.z(), OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), OpenGl_Mat4d::Map (aProjectMat), - myViewport, + theCtx->Viewport(), anObjX, anObjY, anObjZ); @@ -776,14 +776,12 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, if (!myIs2d) { - glGetIntegerv (GL_VIEWPORT, myViewport); - Graphic3d_TransformUtils::Project (myPoint.x(), myPoint.y(), myPoint.z(), myModelMatrix, myProjMatrix, - myViewport, + theCtx->Viewport(), myWinX, myWinY, myWinZ); @@ -795,7 +793,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, myWinZ, OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), myProjMatrix, - myViewport, + theCtx->Viewport(), x1, y1, z1); @@ -807,7 +805,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, myWinZ, OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), myProjMatrix, - myViewport, + theCtx->Viewport(), x2, y2, z2); diff --git a/src/OpenGl/OpenGl_Text.hxx b/src/OpenGl/OpenGl_Text.hxx index 0b1653a15d..36b6c037d1 100755 --- a/src/OpenGl/OpenGl_Text.hxx +++ b/src/OpenGl/OpenGl_Text.hxx @@ -148,7 +148,6 @@ protected: mutable OpenGl_Mat4d myProjMatrix; mutable OpenGl_Mat4d myModelMatrix; mutable OpenGl_Mat4d myOrientationMatrix; - mutable GLint myViewport[4]; mutable GLdouble myWinX; mutable GLdouble myWinY; mutable GLdouble myWinZ; diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index 4d854ae93f..55d11d6dbb 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -167,15 +167,6 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) aCtx->core11fwd->glDisable (GL_DEPTH_TEST); } - aCtx->ProjectionState.Push(); - aCtx->WorldViewState.Push(); - aCtx->ModelWorldState.Push(); - aCtx->ProjectionState.SetIdentity(); - aCtx->WorldViewState.SetIdentity(); - aCtx->ModelWorldState.SetIdentity(); - aCtx->ApplyProjectionMatrix(); - aCtx->ApplyModelViewMatrix(); - // Drawing background gradient if: // - gradient fill type is not Aspect_GFM_NONE and // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode @@ -194,11 +185,6 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) } #endif - if (myBgGradientArray->IsDataChanged()) - { - myBgGradientArray->Init (theWorkspace); - } - myBgGradientArray->Render (theWorkspace); #if !defined(GL_ES_VERSION_2_0) @@ -217,25 +203,10 @@ void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) aCtx->core11fwd->glDisable (GL_BLEND); const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams); - - if (myBgTextureArray->IsDataChanged() - || myBgTextureArray->IsViewSizeChanged (theWorkspace)) - { - myBgTextureArray->Init (theWorkspace); - } - myBgTextureArray->Render (theWorkspace); - - // restore aspects theWorkspace->SetAspectFace (anOldAspectFace); } - aCtx->ModelWorldState.Pop(); - aCtx->WorldViewState.Pop(); - aCtx->ProjectionState.Pop(); - aCtx->ApplyProjectionMatrix(); - aCtx->ApplyModelViewMatrix(); - if (wasUsedZBuffer) { theWorkspace->SetUseZBuffer (Standard_True); @@ -437,7 +408,7 @@ void OpenGl_View::Redraw() } else { - OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; + OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer; OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) { @@ -449,13 +420,12 @@ void OpenGl_View::Redraw() } #if !defined(GL_ES_VERSION_2_0) - if (aMainFbo == NULL - && aFrameBuffer == NULL) + if (aMainFbo == NULL) { aCtx->SetReadDrawBuffer (GL_BACK); } #endif - redraw (aProjectType, aMainFbo != NULL ? aMainFbo : aFrameBuffer); + redraw (aProjectType, aMainFbo); myBackBufferRestored = Standard_True; myIsImmediateDrawn = Standard_False; if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo)) @@ -676,7 +646,8 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, Open } else { - aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height()); + const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; + aCtx->ResizeViewport (aViewport); } // request reset of material @@ -1257,7 +1228,8 @@ void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } #endif - aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height()); + const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; + aCtx->ResizeViewport (aViewport); } } diff --git a/src/OpenGl/OpenGl_Window.cxx b/src/OpenGl/OpenGl_Window.cxx index 495b5f1654..1c442e49b6 100644 --- a/src/OpenGl/OpenGl_Window.cxx +++ b/src/OpenGl/OpenGl_Window.cxx @@ -731,9 +731,10 @@ void OpenGl_Window::Init() glDisable (GL_DITHER); glDisable (GL_SCISSOR_TEST); - glViewport (0, 0, myWidth, myHeight); + const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight }; + myGlContext->ResizeViewport (aViewport); #if !defined(GL_ES_VERSION_2_0) - glDrawBuffer (GL_BACK); + myGlContext->SetDrawBuffer (GL_BACK); if (myGlContext->core11 != NULL) { glMatrixMode (GL_MODELVIEW); diff --git a/src/V3d/FILES b/src/V3d/FILES index 8354090b66..29439f7f4a 100755 --- a/src/V3d/FILES +++ b/src/V3d/FILES @@ -8,6 +8,7 @@ V3d_CircularGrid.hxx V3d_Coordinate.hxx V3d_DirectionalLight.cxx V3d_DirectionalLight.hxx +V3d_ImageDumpOptions.hxx V3d_Light.cxx V3d_Light.hxx V3d_ListOfTransient.hxx diff --git a/src/V3d/V3d_ImageDumpOptions.hxx b/src/V3d/V3d_ImageDumpOptions.hxx new file mode 100644 index 0000000000..368f7c881d --- /dev/null +++ b/src/V3d/V3d_ImageDumpOptions.hxx @@ -0,0 +1,44 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _V3d_ImageDumpOptions_HeaderFile +#define _V3d_ImageDumpOptions_HeaderFile + +#include +#include + +//! The structure defines options for image dump functionality. +struct V3d_ImageDumpOptions +{ + + Standard_Integer Width; //!< width of image dump to allocate an image, 0 by default (meaning that image should be already allocated) + Standard_Integer Height; //!< height of image dump to allocate an image, 0 by default (meaning that image should be already allocated) + Graphic3d_BufferType BufferType; //!< which buffer to dump (color / depth), Graphic3d_BT_RGB by default + V3d_StereoDumpOptions StereoOptions; //!< dumping stereoscopic camera, V3d_SDO_MONO by default (middle-point monographic projection) + Standard_Integer TileSize; //!< the view dimension limited for tiled dump, 0 by default (automatic tiling depending on hardware capabilities) + Standard_Boolean ToAdjustAspect; //!< flag to override active view aspect ratio by (Width / Height) defined for image dump (TRUE by default) + +public: + + //! Default constructor. + V3d_ImageDumpOptions() + : Width (0), + Height (0), + BufferType (Graphic3d_BT_RGB), + StereoOptions (V3d_SDO_MONO), + TileSize (0), + ToAdjustAspect(Standard_True) {} + +}; + +#endif // _V3d_ImageDumpOptions_HeaderFile diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index dd5263df7c..b44dd5af38 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -11,60 +11,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -/*********************************************************************** -FONCTION : ----------- -Classe V3d_View : -HISTORIQUE DES MODIFICATIONS : --------------------------------- -00-09-92 : GG ; Creation. -02-10-96 : FMN ; Suppression appel Redraw sans MustBeResized() -05-06-97 : FMN ; Correction FitAll() -30-06-97 : GG ; Correction + Optimisation de Panning(...) -On fait la translation + le zoom en une seule -operation au lieu de 2 precedemment qui etait buggee. -09-07-97 : FMN ; Correction FitAll() sur le Ratio -16-07-97 : FMN ; Correction FitAll() sur le calcul de la Box -22-07-97 : FMN ; Ajout mode RetainMode pour le Transient -15-12-97 : FMN ; Ajout texture mapping -17-12-97 : FMN ; CTS19129 Correction FitAll() multiple -18-12-97 : FMN ; Ajout mode Ajout -24-12-97 : FMN ; Remplacement de math par MathGra -24-12-97 : CQO ; BUC50037 Xw_Window -> Aspect_Window -31-12-97 : CAL ; Remplacement de MathGra par Array2OfReal -07-01-98 : CAL ; Ajout de la methode DoMapping. -07-01-98 : CAL ; Retrait de tous les "this->" inutiles -21-01-98 : CAL ; Remplacement des Window->Position () par Window->Size () -27-01-98 : FMN ; PERF: OPTIMISATION LOADER (LOPTIM) -12-02-98 : GG ; Reactivation du Redraw dans MustBeResized() -23-02-98 : FMN ; Remplacement PI par Standard_PI -25-02-98 : FMN ; PERF.27: Optimisation of view creation from existing view -11-03-98 : STT ; S3558 -19-03-98 : FMN ; Probleme dans FitAll car la methode WNT_Window::Size(Real,Real) -ne marche pas. -08-04-98 : STT ; suppr. S3558 -10-04-98 : CAL ; Ajout des methodes RefToPix et PixToRef -13-06-98 : FMN ; Probleme dans FitAll car la methode WNT_Window::Size(Real,Real) -ne marche pas. Contournement en appelant WNT_Window::Size(Int,Int). -16-08-98 : CAL ; S3892. Ajout grilles 3d. -09-09-98 : CAL ; S3892. Generalisation de TrsPoint. -06-10-98 : CAL ; Ajout d'un TIMER si CSF_GraphicTimer est definie. -16-10-98 : CAL ; Retrait d'un TIMER si CSF_GraphicTimer est definie. -06-11-98 : CAL ; PRO ?????. Probleme dans ZFitAll si un point dans la vue. -29-OCT-98 : DCB : Adding ScreenCopy () method. -REMARQUES : ------------ -About FitAll() multiple. This probleme is caused by missing -precision of transformation matrices. If it is supposed that -projection is made in the plane (U,V), there is a difference -after several Zoom - compared to the exact value (cf ZoomX). -Don't forget that the matrices work in float and not in double. -To solve the problem (for lack of a better solution) I make 2 passes. -************************************************************************/ -/*----------------------------------------------------------------------*/ -/* -* Includes -*/ +#include #include #include @@ -82,6 +29,8 @@ To solve the problem (for lack of a better solution) I make 2 passes. #include #include #include +#include +#include #include #include #include @@ -100,21 +49,10 @@ To solve the problem (for lack of a better solution) I make 2 passes. #include #include #include -#include #include IMPLEMENT_STANDARD_RTTIEXT(V3d_View,MMgt_TShared) -#define V3d_FLAG_COMPUTATION 0x00000004 - -// Perspective -#include - -/*----------------------------------------------------------------------*/ -/* -* Constant -*/ - #define DEUXPI (2. * M_PI) namespace @@ -2900,71 +2838,117 @@ Standard_Boolean V3d_View::Dump (const Standard_CString theFile, //purpose : //============================================================================= Standard_Boolean V3d_View::ToPixMap (Image_PixMap& theImage, - const Standard_Integer theWidth, - const Standard_Integer theHeight, - const Graphic3d_BufferType& theBufferType, - const Standard_Boolean theToKeepAspect, - const V3d_StereoDumpOptions theStereoOptions) + const V3d_ImageDumpOptions& theParams) { - // always prefer hardware accelerated offscreen buffer + Graphic3d_Vec2i aTargetSize (theParams.Width, theParams.Height); + if (aTargetSize.x() != 0 + && aTargetSize.y() != 0) + { + // allocate image buffer for dumping + if (theImage.IsEmpty() + || theImage.SizeX() != Standard_Size(aTargetSize.x()) + || theImage.SizeY() != Standard_Size(aTargetSize.y())) + { + const bool isBigEndian = Image_PixMap::IsBigEndianHost(); + Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN; + switch (theParams.BufferType) + { + case Graphic3d_BT_RGB: aFormat = isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR; break; + case Graphic3d_BT_RGBA: aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break; + case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break; + } + + if (!theImage.InitZero (aFormat, Standard_Size(aTargetSize.x()), Standard_Size(aTargetSize.y()))) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Fail to allocate an image ") + aTargetSize.x() + "x" + aTargetSize.y() + + " for view dump", Message_Fail); + return Standard_False; + } + } + } + if (theImage.IsEmpty()) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("V3d_View::ToPixMap() has been called without image dimensions"), Message_Fail); + return Standard_False; + } + aTargetSize.x() = (Standard_Integer )theImage.SizeX(); + aTargetSize.y() = (Standard_Integer )theImage.SizeY(); + Handle(Standard_Transient) aFBOPtr; Handle(Standard_Transient) aPrevFBOPtr = myView->FBO(); - Standard_Integer aFBOVPSizeX (theWidth), aFBOVPSizeY (theHeight), aFBOSizeXMax (0), aFBOSizeYMax (0); - Standard_Integer aPrevFBOVPSizeX (0), aPrevFBOVPSizeY (0), aPrevFBOSizeXMax (0), aPrevFBOSizeYMax (0); + Graphic3d_Vec2i aFBOVPSize = aTargetSize; + + bool isTiling = false; + if (theParams.TileSize > 0) + { + if (aFBOVPSize.x() > theParams.TileSize + || aFBOVPSize.y() > theParams.TileSize) + { + aFBOVPSize.x() = Min (aFBOVPSize.x(), theParams.TileSize); + aFBOVPSize.y() = Min (aFBOVPSize.y(), theParams.TileSize); + isTiling = true; + } + } + + Graphic3d_Vec2i aPrevFBOVPSize; if (!aPrevFBOPtr.IsNull()) { + Graphic3d_Vec2i aPrevFBOSizeMax; myView->FBOGetDimensions (aPrevFBOPtr, - aPrevFBOVPSizeX, aPrevFBOVPSizeY, - aPrevFBOSizeXMax, aPrevFBOSizeYMax); - if (aFBOVPSizeX <= aPrevFBOSizeXMax && aFBOVPSizeY <= aPrevFBOSizeYMax) + aPrevFBOVPSize.x(), aPrevFBOVPSize.y(), + aPrevFBOSizeMax.x(), aPrevFBOSizeMax.y()); + if (aFBOVPSize.x() <= aPrevFBOSizeMax.x() + && aFBOVPSize.y() <= aPrevFBOSizeMax.y()) { - myView->FBOChangeViewport (aPrevFBOPtr, aFBOVPSizeX, aFBOVPSizeY); aFBOPtr = aPrevFBOPtr; } } if (aFBOPtr.IsNull()) { - // Try to create hardware accelerated buffer - aFBOPtr = myView->FBOCreate (aFBOVPSizeX, aFBOVPSizeY); - if (!aFBOPtr.IsNull()) + Standard_Integer aMaxTexSize = MyViewer->Driver()->InquireLimit (Graphic3d_TypeOfLimit_MaxTextureSize); + if (theParams.TileSize > aMaxTexSize) { - myView->FBOGetDimensions (aFBOPtr, - aFBOVPSizeX, aFBOVPSizeY, - aFBOSizeXMax, aFBOSizeYMax); - // reduce viewport in case of hardware limits - if (aFBOVPSizeX > aFBOSizeXMax) aFBOVPSizeX = aFBOSizeXMax; - if (aFBOVPSizeY > aFBOSizeYMax) aFBOVPSizeY = aFBOSizeYMax; - myView->FBOChangeViewport (aFBOPtr, aFBOVPSizeX, aFBOVPSizeY); + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Image dump can not be performed - specified tile size (") + + theParams.TileSize + ") exceeds hardware limits (" + aMaxTexSize + ")", Message_Fail); + return Standard_False; } + + if (aFBOVPSize.x() > aMaxTexSize + || aFBOVPSize.y() > aMaxTexSize) + { + aFBOVPSize.x() = Min (aFBOVPSize.x(), aMaxTexSize); + aFBOVPSize.y() = Min (aFBOVPSize.y(), aMaxTexSize); + isTiling = true; + } + + // Try to create hardware accelerated buffer + aFBOPtr = myView->FBOCreate (aFBOVPSize.x(), aFBOVPSize.y()); } myView->SetFBO (aFBOPtr); - // If hardware accelerated buffer - try to use onscreen buffer - // Results may be bad! if (aFBOPtr.IsNull()) { - // retrieve window sizes - Standard_Integer aWinWidth, aWinHeight; - MyWindow->Size (aWinWidth, aWinHeight); - - // technically we can reduce existing viewport... - // but currently allow only dumping the window itself - if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight) + // try to use on-screen buffer + Graphic3d_Vec2i aWinSize; + MyWindow->Size (aWinSize.x(), aWinSize.y()); + if (aFBOVPSize.x() != aWinSize.x() + || aFBOVPSize.y() != aWinSize.y()) { - return Standard_False; + isTiling = true; } + aFBOVPSize = aWinSize; + + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Warning, on screen buffer is used for image dump - content might be invalid"), Message_Warning); } + // backup camera parameters Handle(Graphic3d_Camera) aStoreMapping = new Graphic3d_Camera(); - Handle(Graphic3d_Camera) aCamera = Camera(); - aStoreMapping->Copy (aCamera); - if (aCamera->IsStereo()) { - switch (theStereoOptions) + switch (theParams.StereoOptions) { case V3d_SDO_MONO: { @@ -2987,57 +2971,95 @@ Standard_Boolean V3d_View::ToPixMap (Image_PixMap& theImage, } } } + if (theParams.ToAdjustAspect) + { + aCamera->SetAspect (Standard_Real(aTargetSize.x()) / Standard_Real(aTargetSize.y())); + } + AutoZFit(); // render immediate structures into back buffer rather than front const Standard_Boolean aPrevImmediateMode = myView->SetImmediateModeDrawToFront (Standard_False); - const Standard_Boolean toAutoUpdate = myImmediateUpdate; - myImmediateUpdate = Standard_False; - AutoZFit(); - myImmediateUpdate = toAutoUpdate; - - if (theToKeepAspect) - { - aCamera->SetAspect ((Standard_Real) aFBOVPSizeX / aFBOVPSizeY); - } - - Redraw(); - - myView->SetImmediateModeDrawToFront (aPrevImmediateMode); - - aCamera->Copy (aStoreMapping); - Standard_Boolean isSuccess = Standard_True; - - // allocate image buffer for dumping - if (theImage.IsEmpty() - || (Standard_Size )aFBOVPSizeX != theImage.SizeX() - || (Standard_Size )aFBOVPSizeY != theImage.SizeY()) + if (!isTiling) { - bool isBigEndian = Image_PixMap::IsBigEndianHost(); - Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN; - switch (theBufferType) + if (!aFBOPtr.IsNull()) { - case Graphic3d_BT_RGB: aFormat = isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR; break; - case Graphic3d_BT_RGBA: aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break; - case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break; + myView->FBOChangeViewport (aFBOPtr, aTargetSize.x(), aTargetSize.y()); } - - isSuccess = isSuccess && theImage.InitZero (aFormat, aFBOVPSizeX, aFBOVPSizeY); + Redraw(); + isSuccess = isSuccess && myView->BufferDump (theImage, theParams.BufferType); } - isSuccess = isSuccess && myView->BufferDump (theImage, theBufferType); + else + { + Image_PixMap aTilePixMap; + aTilePixMap.SetTopDown (theImage.IsTopDown()); - // FBO now useless, free resources + Graphic3d_Vec2i anOffset (0, 0); + for (; anOffset.y() < aTargetSize.y(); anOffset.y() += aFBOVPSize.y()) + { + anOffset.x() = 0; + for (; anOffset.x() < aTargetSize.x(); anOffset.x() += aFBOVPSize.x()) + { + Graphic3d_CameraTile aTile; + aTile.Offset = anOffset; + aTile.TotalSize = aTargetSize; + aTile.TileSize = aFBOVPSize; + if (!aFBOPtr.IsNull()) + { + // crop corners in case of FBO + // (no API to resize viewport of on-screen buffer - keep uncropped in this case) + aTile = aTile.Cropped(); + } + if (aTile.TileSize.x() < 1 + || aTile.TileSize.y() < 1) + { + continue; + } + + const Standard_Integer aLeft = aTile.Offset.x(); + Standard_Integer aBottom = aTile.Offset.y(); + if (theImage.IsTopDown()) + { + const Standard_Integer aTop = aTile.Offset.y() + aTile.TileSize.y(); + aBottom = aTargetSize.y() - aTop; + } + aTilePixMap.InitWrapper (theImage.Format(), theImage.ChangeData() + + theImage.SizeRowBytes() * aBottom + theImage.SizePixelBytes() * aLeft, + aTile.TileSize.x(), aTile.TileSize.y(), + theImage.SizeRowBytes()); + + aCamera->SetTile (aTile); + if (!aFBOPtr.IsNull()) + { + myView->FBOChangeViewport (aFBOPtr, aTile.TileSize.x(), aTile.TileSize.y()); + } + Redraw(); + isSuccess = isSuccess && myView->BufferDump (aTilePixMap, theParams.BufferType); + if (!isSuccess) + { + break; + } + } + if (!isSuccess) + { + break; + } + } + } + + // restore state + myView->SetImmediateModeDrawToFront (aPrevImmediateMode); + aCamera->Copy (aStoreMapping); if (aFBOPtr != aPrevFBOPtr) { myView->FBORelease (aFBOPtr); } else if (!aPrevFBOPtr.IsNull()) { - myView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSizeX, aPrevFBOVPSizeY); + myView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSize.x(), aPrevFBOVPSize.y()); } myView->SetFBO (aPrevFBOPtr); - return isSuccess; } diff --git a/src/V3d/V3d_View.hxx b/src/V3d/V3d_View.hxx index 38a1972b2f..0b75aaeaff 100644 --- a/src/V3d/V3d_View.hxx +++ b/src/V3d/V3d_View.hxx @@ -68,7 +68,7 @@ #include #include -#include +#include #include #include @@ -814,17 +814,32 @@ public: const Graphic3d_ExportFormat theFormat, const Graphic3d_SortType theSortType = Graphic3d_ST_BSP_Tree); - //! Dumps the full contents of the view - //! to a pixmap of pixel size * and - //! buffer type . If is true - //! the aspect ratio of view will be kept if and - //! define another ratio. - //! Pixmap will be automatically (re)allocated when needed. - //! When dumping stereographic camera - the corresponding - //! middle-point monographic projection will be used for dumping by default. - //! flags are to be used for dumping then left or - //! right eye projections. - Standard_EXPORT Standard_Boolean ToPixMap (Image_PixMap& theImage, const Standard_Integer theWidth, const Standard_Integer theHeight, const Graphic3d_BufferType& theBufferType = Graphic3d_BT_RGB, const Standard_Boolean theToKeepAspect = Standard_True, const V3d_StereoDumpOptions theStereoOptions = V3d_SDO_MONO); + //! Dumps the full contents of the view to a pixmap with specified parameters. + Standard_EXPORT Standard_Boolean ToPixMap (Image_PixMap& theImage, + const V3d_ImageDumpOptions& theParams); + + //! Dumps the full contents of the view to a pixmap. + //! @param theImage target image, will be re-allocated to match theWidth x theHeight + //! @param theWidth target image width + //! @param theHeight target image height + //! @param theBufferType type of the view buffer to dump (color / depth) + //! @param theToAdjustAspect when true, active view aspect ratio will be overridden by (theWidth / theHeight) + //! @param theStereoOptions how to dump stereographic camera + Standard_Boolean ToPixMap (Image_PixMap& theImage, + const Standard_Integer theWidth, + const Standard_Integer theHeight, + const Graphic3d_BufferType& theBufferType = Graphic3d_BT_RGB, + const Standard_Boolean theToAdjustAspect = Standard_True, + const V3d_StereoDumpOptions theStereoOptions = V3d_SDO_MONO) + { + V3d_ImageDumpOptions aParams; + aParams.Width = theWidth; + aParams.Height = theHeight; + aParams.BufferType = theBufferType; + aParams.StereoOptions = theStereoOptions; + aParams.ToAdjustAspect = theToAdjustAspect; + return ToPixMap (theImage, aParams); + } //! Manages display of the back faces //! When is TOBM_AUTOMATIC the object backfaces diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 33929d8948..0b1e63a022 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -807,11 +807,10 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, Standard_Integer anArgIter = 1; Standard_CString aFilePath = theArgVec[anArgIter++]; - Graphic3d_BufferType aBufferType = Graphic3d_BT_RGB; - V3d_StereoDumpOptions aStereoOpts = V3d_SDO_MONO; ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single; - Standard_Integer aWidth = 0; - Standard_Integer aHeight = 0; + V3d_ImageDumpOptions aParams; + aParams.BufferType = Graphic3d_BT_RGB; + aParams.StereoOptions = V3d_SDO_MONO; for (; anArgIter < theArgNb; ++anArgIter) { TCollection_AsciiString anArg (theArgVec[anArgIter]); @@ -828,15 +827,15 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, aBufArg.LowerCase(); if (aBufArg == "rgba") { - aBufferType = Graphic3d_BT_RGBA; + aParams.BufferType = Graphic3d_BT_RGBA; } else if (aBufArg == "rgb") { - aBufferType = Graphic3d_BT_RGB; + aParams.BufferType = Graphic3d_BT_RGB; } else if (aBufArg == "depth") { - aBufferType = Graphic3d_BT_Depth; + aParams.BufferType = Graphic3d_BT_Depth; } else { @@ -857,22 +856,22 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, if (aStereoArg == "l" || aStereoArg == "left") { - aStereoOpts = V3d_SDO_LEFT_EYE; + aParams.StereoOptions = V3d_SDO_LEFT_EYE; } else if (aStereoArg == "r" || aStereoArg == "right") { - aStereoOpts = V3d_SDO_RIGHT_EYE; + aParams.StereoOptions = V3d_SDO_RIGHT_EYE; } else if (aStereoArg == "mono") { - aStereoOpts = V3d_SDO_MONO; + aParams.StereoOptions = V3d_SDO_MONO; } else if (aStereoArg == "blended" || aStereoArg == "blend" || aStereoArg == "stereo") { - aStereoOpts = V3d_SDO_BLENDED; + aParams.StereoOptions = V3d_SDO_BLENDED; } else if (aStereoArg == "sbs" || aStereoArg == "sidebyside") @@ -893,24 +892,23 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, else if (anArg == "-rgba" || anArg == "rgba") { - aBufferType = Graphic3d_BT_RGBA; + aParams.BufferType = Graphic3d_BT_RGBA; } else if (anArg == "-rgb" || anArg == "rgb") { - aBufferType = Graphic3d_BT_RGB; + aParams.BufferType = Graphic3d_BT_RGB; } else if (anArg == "-depth" || anArg == "depth") { - aBufferType = Graphic3d_BT_Depth; + aParams.BufferType = Graphic3d_BT_Depth; } - else if (anArg == "-width" || anArg == "width" || anArg == "sizex") { - if (aWidth != 0) + if (aParams.Width != 0) { std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n"; return 1; @@ -920,13 +918,13 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, std::cout << "Error: integer value is expected right after 'width'\n"; return 1; } - aWidth = Draw::Atoi (theArgVec[anArgIter]); + aParams.Width = Draw::Atoi (theArgVec[anArgIter]); } else if (anArg == "-height" || anArg == "height" || anArg == "-sizey") { - if (aHeight != 0) + if (aParams.Height != 0) { std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n"; return 1; @@ -936,7 +934,17 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, std::cout << "Error: integer value is expected right after 'height'\n"; return 1; } - aHeight = Draw::Atoi (theArgVec[anArgIter]); + aParams.Height = Draw::Atoi (theArgVec[anArgIter]); + } + else if (anArg == "-tile" + || anArg == "-tilesize") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Error: integer value is expected right after 'tileSize'\n"; + return 1; + } + aParams.TileSize = Draw::Atoi (theArgVec[anArgIter]); } else { @@ -944,10 +952,10 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, return 1; } } - if ((aWidth <= 0 && aHeight > 0) - || (aWidth > 0 && aHeight <= 0)) + if ((aParams.Width <= 0 && aParams.Height > 0) + || (aParams.Width > 0 && aParams.Height <= 0)) { - std::cout << "Error: dimensions " << aWidth << "x" << aHeight << " are incorrect\n"; + std::cout << "Error: dimensions " << aParams.Width << "x" << aParams.Height << " are incorrect\n"; return 1; } @@ -958,16 +966,16 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, return 1; } - if (aWidth <= 0 || aHeight <= 0) + if (aParams.Width <= 0 || aParams.Height <= 0) { - aView->Window()->Size (aWidth, aHeight); + aView->Window()->Size (aParams.Width, aParams.Height); } Image_AlienPixMap aPixMap; bool isBigEndian = Image_PixMap::IsBigEndianHost(); Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN; - switch (aBufferType) + switch (aParams.BufferType) { case Graphic3d_BT_RGB: aFormat = isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR; break; case Graphic3d_BT_RGBA: aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break; @@ -978,22 +986,22 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, { case ViewerTest_SP_Single: { - if (!aView->ToPixMap (aPixMap, aWidth, aHeight, aBufferType, Standard_True, aStereoOpts)) + if (!aView->ToPixMap (aPixMap, aParams)) { theDI << "Fail: view dump failed!\n"; return 0; } - else if (aPixMap.SizeX() != Standard_Size(aWidth) - || aPixMap.SizeY() != Standard_Size(aHeight)) + else if (aPixMap.SizeX() != Standard_Size(aParams.Width) + || aPixMap.SizeY() != Standard_Size(aParams.Height)) { theDI << "Fail: dumped dimensions " << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY() - << " are lesser than requested " << aWidth << "x" << aHeight << "\n"; + << " are lesser than requested " << aParams.Width << "x" << aParams.Height << "\n"; } break; } case ViewerTest_SP_SideBySide: { - if (!aPixMap.InitZero (aFormat, aWidth * 2, aHeight)) + if (!aPixMap.InitZero (aFormat, aParams.Width * 2, aParams.Height)) { theDI << "Fail: not enough memory for image allocation!\n"; return 0; @@ -1001,12 +1009,15 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, Image_PixMap aPixMapL, aPixMapR; aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(), - aWidth, aHeight, aPixMap.SizeRowBytes()); - aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aWidth, - aWidth, aHeight, aPixMap.SizeRowBytes()); - if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE) - || !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE) - ) + aParams.Width, aParams.Height, aPixMap.SizeRowBytes()); + aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aParams.Width, + aParams.Width, aParams.Height, aPixMap.SizeRowBytes()); + + aParams.StereoOptions = V3d_SDO_LEFT_EYE; + Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams); + aParams.StereoOptions = V3d_SDO_RIGHT_EYE; + isOk = isOk && aView->ToPixMap (aPixMapR, aParams); + if (!isOk) { theDI << "Fail: view dump failed!\n"; return 0; @@ -1015,7 +1026,7 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, } case ViewerTest_SP_OverUnder: { - if (!aPixMap.InitZero (aFormat, aWidth, aHeight * 2)) + if (!aPixMap.InitZero (aFormat, aParams.Width, aParams.Height * 2)) { theDI << "Fail: not enough memory for image allocation!\n"; return 0; @@ -1023,11 +1034,15 @@ static Standard_Integer VDump (Draw_Interpretor& theDI, Image_PixMap aPixMapL, aPixMapR; aPixMapL.InitWrapper (aFormat, aPixMap.ChangeData(), - aWidth, aHeight, aPixMap.SizeRowBytes()); - aPixMapR.InitWrapper (aFormat, aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aHeight, - aWidth, aHeight, aPixMap.SizeRowBytes()); - if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE) - || !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE)) + aParams.Width, aParams.Height, aPixMap.SizeRowBytes()); + aPixMapR.InitWrapper (aFormat, aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aParams.Height, + aParams.Width, aParams.Height, aPixMap.SizeRowBytes()); + + aParams.StereoOptions = V3d_SDO_LEFT_EYE; + Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams); + aParams.StereoOptions = V3d_SDO_RIGHT_EYE; + isOk = isOk && aView->ToPixMap (aPixMapR, aParams); + if (!isOk) { theDI << "Fail: view dump failed!\n"; return 0; @@ -5672,6 +5687,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) "vdump ." DUMP_FORMATS " [-width Width -height Height]" "\n\t\t: [-buffer rgb|rgba|depth=rgb]" "\n\t\t: [-stereo mono|left|right|blend|sideBySide|overUnder=mono]" + "\n\t\t: [-tileSize Size=0]" "\n\t\t: Dumps content of the active view into image file", __FILE__,VDump,group); diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 3b38837b06..ff91e617b2 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -4278,6 +4278,108 @@ static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer th return 0; } +//============================================================================== +//function : VTile +//purpose : +//============================================================================== +static int VTile (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + Handle(V3d_View) aView = ViewerTest::CurrentView(); + if (aView.IsNull()) + { + std::cerr << "Error: no active viewer.\n"; + return 1; + } + + Graphic3d_CameraTile aTile = aView->Camera()->Tile(); + if (theArgNb < 2) + { + theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n" + << "Tile size: " << aTile.TileSize.x() << " " << aTile.TileSize.y() << "\n" + << "Lower left: " << aTile.Offset.x() << " " << aTile.Offset.y() << "\n"; + return 0; + } + + aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y()); + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) + { + TCollection_AsciiString anArg (theArgVec[anArgIter]); + anArg.LowerCase(); + if (anArg == "-lowerleft" + || anArg == "-upperleft") + { + if (anArgIter + 3 < theArgNb) + { + std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n"; + return 1; + } + aTile.IsTopDown = (anArg == "-upperleft") == Standard_True; + aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]); + aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]); + } + else if (anArg == "-total" + || anArg == "-totalsize" + || anArg == "-viewsize") + { + if (anArgIter + 3 < theArgNb) + { + std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n"; + return 1; + } + aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]); + aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]); + if (aTile.TotalSize.x() < 1 + || aTile.TotalSize.y() < 1) + { + std::cerr << "Error: total size is incorrect.\n"; + return 1; + } + } + else if (anArg == "-tilesize") + { + if (anArgIter + 3 < theArgNb) + { + std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n"; + return 1; + } + + aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]); + aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]); + if (aTile.TileSize.x() < 1 + || aTile.TileSize.y() < 1) + { + std::cerr << "Error: tile size is incorrect.\n"; + return 1; + } + } + else if (anArg == "-unset") + { + aView->Camera()->SetTile (Graphic3d_CameraTile()); + aView->Redraw(); + return 0; + } + } + + if (aTile.TileSize.x() < 1 + || aTile.TileSize.y() < 1) + { + std::cerr << "Error: tile size is undefined.\n"; + return 1; + } + else if (aTile.TotalSize.x() < 1 + || aTile.TotalSize.y() < 1) + { + std::cerr << "Error: total size is undefined.\n"; + return 1; + } + + aView->Camera()->SetTile (aTile); + aView->Redraw(); + return 0; +} + //============================================================================== //function : VZLayer //purpose : Test z layer operations for v3d viewer @@ -9064,6 +9166,14 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n" " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n", __FILE__,VGraduatedTrihedron,group); + theCommands.Add("vtile" , + "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]" + "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)." + "\n\t\t: -totalSize the size of virtual bigger viewport" + "\n\t\t: -tileSize tile size (the view size will be used if omitted)" + "\n\t\t: -lowerLeft tile offset as lower left corner" + "\n\t\t: -upperLeft tile offset as upper left corner", + __FILE__, VTile, group); theCommands.Add("vzlayer", "vzlayer add/del/get/settings/enable/disable [id]\n" " add - add new z layer to viewer and print its id\n" diff --git a/tests/v3d/glsl/tiles b/tests/v3d/glsl/tiles new file mode 100644 index 0000000000..d8906c9cc3 --- /dev/null +++ b/tests/v3d/glsl/tiles @@ -0,0 +1,94 @@ +puts "========" +puts "Tiled image dump" +puts "========" + +set aFontFile "" +catch { set aFontFile [locate_data_file DejaVuSans.ttf] } + +pload MODELING VISUALIZATION +box b 2 3 1 +box b2 50 20 30 + +set aLabelFont "Arial" +if { "$aFontFile" != "" } { + vfont add "$aFontFile" SansFont + set aLabelFont "SansFont" +} + +vclear +vinit View1 +vraytrace 0 +vsetgradientbg 180 200 255 180 180 180 2 +vsetdispmode 0 +vdisplay -dispMode 1 b +vfit +vrotate 0.5 0 0 +vzbufftrihedron + +catch { vzlayer del 1 } +vzlayer add 1 +vzlayer enable 1 depthclear + +vtrihedron trh +vdisplay -noupdate trh -layer 1 -trsfPers trihedron -trsfPersPos 1 1 100 + +text2brep tcc "Center" -font $aLabelFont -height 30 -pos -40 0 0 +vdisplay -noupdate tcc -2d -layer 1 -dispMode 1 +polyline lcc -50 -50 0 -50 50 0 50 50 0 50 0 0 0 -50 0 -50 -50 0 +vdisplay -noupdate lcc -2d -layer 1 +vsetwidth -noupdate lcc 2 + +text2brep tbl "Bottom-Left" -font $aLabelFont -height 30 -pos 0 3 5 +vdisplay -noupdate tbl -2d -layer 1 -trsfPersPos -1 -1 -dispMode 1 +polyline lbl 0 0 0 0 100 0 100 100 0 100 50 0 50 0 0 0 0 0 +vdisplay -noupdate lbl -2d -layer 1 -trsfPersPos -1 -1 +vsetwidth -noupdate lbl 2 + +text2brep ttl "Top-Left" -font $aLabelFont -height 30 -pos 0 -30 0 +vdisplay -noupdate ttl -2d -layer 1 -trsfPersPos -1 1 -dispMode 1 +polyline ltl 0 -100 0 0 0 0 100 0 0 100 -50 0 50 -100 0 0 -100 0 +vdisplay -noupdate ltl -2d -layer 1 -trsfPersPos -1 1 +vsetwidth -noupdate ltl 2 + +text2brep ttr "Top-Right" -font $aLabelFont -height 30 -pos -130 -30 0 +vdisplay -noupdate ttr -2d -layer 1 -trsfPersPos 1 1 -dispMode 1 +polyline ltr -100 -100 0 -100 0 0 0 0 0 0 -50 0 -50 -100 0 -100 -100 0 +vdisplay -noupdate ltr -2d -layer 1 -trsfPersPos 1 1 +vsetwidth -noupdate ltr 2 + +text2brep tbr "Bottom-Right" -font $aLabelFont -height 30 -pos -180 3 0 +vdisplay -noupdate tbr -2d -layer 1 -trsfPersPos 1 -1 -dispMode 1 +polyline lbr -100 0 0 -100 100 0 0 100 0 0 50 0 -50 0 0 -100 0 0 +vdisplay -noupdate lbr -2d -layer 1 -trsfPersPos 1 -1 +vsetwidth -noupdate lbr 2 + +vdrawtext t2 "Label" -pos 1 0 1 -font $aLabelFont +vdisplay b2 -trsfPers zoom -trsfPersPos 1 0 1 + +vdump $::imagedir/${::casename}_409x409@tile0.png +vdump $::imagedir/${::casename}_409x409@tile128.png -tileSize 128 +vdump $::imagedir/${::casename}_409x409@tile1024.png -tileSize 1024 +vdump $::imagedir/${::casename}_1920x1080@tile0.png -width 1920 -height 1920 +vdump $::imagedir/${::casename}_1920x1080@tile128.png -width 1920 -height 1920 -tileSize 128 +vdump $::imagedir/${::casename}_1920x1080@tile1024.png -width 1920 -height 1920 -tileSize 1024 +diffimage $::imagedir/${::casename}_409x409@tile0.png $::imagedir/${::casename}_409x409@tile128.png 0 0 0 $::imagedir/${::casename}_409x409@tile128diff.png + +# check dump with stereo +vstereo anaglyph +vdump $::imagedir/${::casename}_409x409@stereotile0.png -stereo blend +vdump $::imagedir/${::casename}_409x409@stereotile128.png -stereo blend -tileSize 128 +vdump $::imagedir/${::casename}_409x409@stereotile1024.png -stereo blend -tileSize 1024 +vdump $::imagedir/${::casename}_1920x1080@stereotile0.png -width 1920 -height 1920 -stereo blend +vdump $::imagedir/${::casename}_1920x1080@stereotile128.png -width 1920 -height 1920 -stereo blend -tileSize 128 +vdump $::imagedir/${::casename}_1920x1080@stereotile1024.png -width 1920 -height 1920 -stereo blend -tileSize 1024 +diffimage $::imagedir/${::casename}_409x409@stereotile0.png $::imagedir/${::casename}_409x409@stereotile128.png 0 0 0 $::imagedir/${::casename}_409x409@stereotile128diff.png + +# check dump with Ray Tracing +vraytrace 1 +vdump $::imagedir/${::casename}_409x409@rttile0.png -stereo blend +vdump $::imagedir/${::casename}_409x409@rttile128.png -stereo blend -tileSize 128 +vdump $::imagedir/${::casename}_409x409@rttile1024.png -stereo blend -tileSize 1024 +vdump $::imagedir/${::casename}_1920x1080@rttile0.png -width 1920 -height 1920 -stereo blend +vdump $::imagedir/${::casename}_1920x1080@rttile128.png -width 1920 -height 1920 -stereo blend -tileSize 128 +vdump $::imagedir/${::casename}_1920x1080@rttile1024.png -width 1920 -height 1920 -stereo blend -tileSize 1024 +vraytrace 0