0022582: Visualization - provide an API for dumping a sub-region of the viewport
authorosa <osa@opencascade.com>
Sun, 21 Aug 2016 18:55:10 +0000 (21:55 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 1 Sep 2016 10:19:11 +0000 (13:19 +0300)
Graphic3d_Camera definition has been exended by optional Tile property (Graphic3d_CameraTile structure).
V3d_View::ToPixMap() now performs tiled dump when image size exceeds hardware limits.

OpenGl_View::Redraw() - fixed dump of immediate Z layers in no stereo and no MSAA case.

OpenGl_Context now tracks viewport values.
Draw Harness command vdump has been extended with new argument -tileSize.

28 files changed:
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_Camera.cxx
src/Graphic3d/Graphic3d_Camera.hxx
src/Graphic3d/Graphic3d_CameraTile.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_GraphicDriver.hxx
src/Graphic3d/Graphic3d_TransformPers.hxx
src/Graphic3d/Graphic3d_TransformUtils.hxx
src/Graphic3d/Graphic3d_TypeOfLimit.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_BackgroundArray.cxx
src/OpenGl/OpenGl_BackgroundArray.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_GraduatedTrihedron.cxx
src/OpenGl/OpenGl_GraphicDriver.cxx
src/OpenGl/OpenGl_GraphicDriver.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_Text.hxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Window.cxx
src/V3d/FILES
src/V3d/V3d_ImageDumpOptions.hxx [new file with mode: 0644]
src/V3d/V3d_View.cxx
src/V3d/V3d_View.hxx
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/glsl/tiles [new file with mode: 0644]

index 13c448d..3b2fe42 100755 (executable)
@@ -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
index 2288278..754af59 100644 (file)
@@ -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);
 }
 
 // =======================================================================
@@ -426,6 +427,21 @@ void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD
 }
 
 // =======================================================================
+// 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<Elem_t>&
     ? static_cast<Elem_t> (myZFocus * Distance())
     : static_cast<Elem_t> (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<Elem_t> (anOffset.x())                       / static_cast<Elem_t> (myTile.TotalSize.x());
+    aRight = -aDXHalf + aDXFull * static_cast<Elem_t> (anOffset.x() + myTile.TileSize.x()) / static_cast<Elem_t> (myTile.TotalSize.x());
+    aBot   = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y())                       / static_cast<Elem_t> (myTile.TotalSize.y());
+    aTop   = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y() + myTile.TileSize.y()) / static_cast<Elem_t> (myTile.TotalSize.y());
+  }
+
   switch (myProjType)
   {
     case Projection_Orthographic :
index dfb90bb..fe9e44b 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef _Graphic3d_Camera_HeaderFile
 #define _Graphic3d_Camera_HeaderFile
 
+#include <Graphic3d_CameraTile.hxx>
 #include <Graphic3d_Mat4d.hxx>
 #include <Graphic3d_Mat4.hxx>
 #include <Graphic3d_Vec3.hxx>
@@ -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<Standard_Real>      myMatricesD;
   mutable TransformMatrices<Standard_ShortReal> myMatricesF;
 
diff --git a/src/Graphic3d/Graphic3d_CameraTile.hxx b/src/Graphic3d/Graphic3d_CameraTile.hxx
new file mode 100644 (file)
index 0000000..9ad8051
--- /dev/null
@@ -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 <Graphic3d_Vec2.hxx>
+#include <Standard_Integer.hxx>
+#include <Standard_TypeDef.hxx>
+
+//! 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
index 2f7dede..01fddf3 100644 (file)
@@ -46,6 +46,7 @@
 #include <Graphic3d_ZLayerId.hxx>
 #include <Graphic3d_ZLayerSettings.hxx>
 #include <Graphic3d_CLight.hxx>
+#include <Graphic3d_TypeOfLimit.hxx>
 #include <TColStd_Array2OfReal.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 
@@ -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;
   
index fb3058a..6ce52b0 100644 (file)
@@ -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)
     {
index a2ba5cd..85fc7d3 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef _Graphic3d_TransformUtils_HeaderFile
 #define _Graphic3d_TransformUtils_HeaderFile
 
+#include <gp_Trsf.hxx>
 #include <Graphic3d_Vec.hxx>
 #include <Standard_math.hxx> // M_PI
 
diff --git a/src/Graphic3d/Graphic3d_TypeOfLimit.hxx b/src/Graphic3d/Graphic3d_TypeOfLimit.hxx
new file mode 100644 (file)
index 0000000..8cc1cbd
--- /dev/null
@@ -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
index 63f36bf..0dce18b 100644 (file)
@@ -18,6 +18,7 @@
 #include <Aspect_FillMethod.hxx>
 #include <NCollection_AlignedAllocator.hxx>
 #include <OpenGl_Texture.hxx>
+#include <OpenGl_View.hxx>
 #include <Graphic3d_TextureParams.hxx>
 
 // =======================================================================
 // =======================================================================
 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 <t> 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();
+}
index efdb1b6..8458736 100644 (file)
@@ -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
 
 };
 
index ccadcf6..42d5e62 100644 (file)
@@ -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)
 {
index e89b4d1..6a53922 100644 (file)
@@ -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)
index 8b81353..6f686a4 100644 (file)
@@ -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);
 }
 
 // =======================================================================
index cd12dfb..655043a 100755 (executable)
@@ -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<Standard_ShortReal> (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<Standard_ShortReal> (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(),
-                                                           aModelMat, aProjMat, aViewport,
+                                                           aModelMat, aProjMat, aContext->Viewport(),
                                                            anArrowStart.x(), anArrowStart.y(), anArrowStart.z());
   // Render axis line
   aModelMat = theMat;
index 1c1081b..83cf40d 100644 (file)
@@ -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;
 }
 
 // =======================================================================
index b0e5a00..29a40b9 100644 (file)
@@ -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;
index 1355473..cd7139c 100644 (file)
@@ -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();
index 039e560..157be50 100644 (file)
@@ -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<Standard_Real> (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);
index 0b1653a..36b6c03 100755 (executable)
@@ -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;
index 4d854ae..55d11d6 100644 (file)
@@ -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);
   }
 }
 
index 495b5f1..1c442e4 100644 (file)
@@ -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);
index 8354090..29439f7 100755 (executable)
@@ -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 (file)
index 0000000..368f7c8
--- /dev/null
@@ -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 <Graphic3d_BufferType.hxx>
+#include <V3d_StereoDumpOptions.hxx>
+
+//! 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
index dd5263d..b44dd5a 100644 (file)
 // 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 <V3d_View.hxx>
 
 #include <Aspect_GradientBackground.hxx>
 #include <Aspect_Grid.hxx>
@@ -82,6 +29,8 @@ To solve the problem (for lack of a better solution) I make 2 passes.
 #include <Graphic3d_TextureEnv.hxx>
 #include <Graphic3d_Vector.hxx>
 #include <Image_AlienPixMap.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
 #include <NCollection_Array1.hxx>
 #include <Precision.hxx>
 #include <Quantity_Color.hxx>
@@ -100,21 +49,10 @@ To solve the problem (for lack of a better solution) I make 2 passes.
 #include <V3d_Light.hxx>
 #include <V3d_StereoDumpOptions.hxx>
 #include <V3d_UnMapped.hxx>
-#include <V3d_View.hxx>
 #include <V3d_Viewer.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(V3d_View,MMgt_TShared)
 
-#define V3d_FLAG_COMPUTATION   0x00000004
-
-// Perspective
-#include <OSD_Environment.hxx>
-
-/*----------------------------------------------------------------------*/
-/*
-* 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,
       }
     }
   }
-
-  // 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)
+  if (theParams.ToAdjustAspect)
   {
-    aCamera->SetAspect ((Standard_Real) aFBOVPSizeX / aFBOVPSizeY);
+    aCamera->SetAspect (Standard_Real(aTargetSize.x()) / Standard_Real(aTargetSize.y()));
   }
+  AutoZFit();
 
-  Redraw();
-
-  myView->SetImmediateModeDrawToFront (aPrevImmediateMode);
-
-  aCamera->Copy (aStoreMapping);
+  // render immediate structures into back buffer rather than front
+  const Standard_Boolean aPrevImmediateMode = myView->SetImmediateModeDrawToFront (Standard_False);
 
   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());
     }
+    Redraw();
+    isSuccess = isSuccess && myView->BufferDump (theImage, theParams.BufferType);
+  }
+  else
+  {
+    Image_PixMap aTilePixMap;
+    aTilePixMap.SetTopDown (theImage.IsTopDown());
 
-    isSuccess = isSuccess && theImage.InitZero (aFormat, aFBOVPSizeX, aFBOVPSizeY);
+    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;
+      }
+    }
   }
-  isSuccess = isSuccess && myView->BufferDump (theImage, theBufferType);
 
-  // FBO now useless, free resources
+  // 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;
 }
 
index 38a1972..0b75aae 100644 (file)
@@ -68,7 +68,7 @@
 
 #include <V3d_Coordinate.hxx>
 #include <V3d_ListOfTransient.hxx>
-#include <V3d_StereoDumpOptions.hxx>
+#include <V3d_ImageDumpOptions.hxx>
 #include <V3d_TypeOfAxe.hxx>
 
 #include <V3d_TypeOfBackfacingModel.hxx>
@@ -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 <theWidth> * <theHeight> and
-  //! buffer type <theBufferType>. If <theToKeepAspect> is true
-  //! the aspect ratio of view will be kept if <theWidth> and <theHeight>
-  //! 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.
-  //! <theStereoOptions> 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 <aModel> is TOBM_AUTOMATIC the object backfaces
index 33929d8..0b1e63a 100644 (file)
@@ -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 <filename>." 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);
 
index 3b38837..ff91e61 100644 (file)
@@ -4279,6 +4279,108 @@ static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer th
 }
 
 //==============================================================================
+//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 (file)
index 0000000..d8906c9
--- /dev/null
@@ -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