]> OCCT Git - occt.git/commitdiff
0033056: Visualization - add front face culling option
authorkgv <kgv@opencascade.com>
Wed, 6 Jul 2022 20:39:14 +0000 (23:39 +0300)
committersmoskvin <smoskvin@opencascade.com>
Thu, 7 Jul 2022 16:27:17 +0000 (19:27 +0300)
Added Graphic3d_TypeOfBackfacingModel_FrontCulled enumeration value.
OpenGl_Context::SetFaceCulling() now supports GL_FRONT in addition to GL_BACK.

Added -faceCulling option to vaspects Draw command.

src/BinMXCAFDoc/BinMXCAFDoc_VisMaterialDriver.cxx
src/Graphic3d/Graphic3d_TypeOfBackfacingModel.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/RWGltf/RWGltf_GltfMaterialMap.cxx
src/ViewerTest/ViewerTest.cxx
src/XDEDRAW/XDEDRAW_Colors.cxx
src/XmlMXCAFDoc/XmlMXCAFDoc_VisMaterialDriver.cxx
tests/opengl/data/general/cullface [new file with mode: 0644]

index 7e18a19043189bbdeafe1a01fb9e852a07c9f3c5..b6f80319786dc78c892e433f800254abb9b0d441 100644 (file)
@@ -54,6 +54,7 @@ static Standard_Byte faceCullToChar (Graphic3d_TypeOfBackfacingModel theMode)
   {
     case Graphic3d_TypeOfBackfacingModel_Auto:        return '0';
     case Graphic3d_TypeOfBackfacingModel_BackCulled:  return 'B';
+    case Graphic3d_TypeOfBackfacingModel_FrontCulled: return 'F';
     case Graphic3d_TypeOfBackfacingModel_DoubleSided: return '1';
   }
   return '0';
@@ -66,6 +67,7 @@ static Graphic3d_TypeOfBackfacingModel faceCullFromChar (Standard_Byte theMode)
   {
     case '0': return Graphic3d_TypeOfBackfacingModel_Auto;
     case 'B': return Graphic3d_TypeOfBackfacingModel_BackCulled;
+    case 'F': return Graphic3d_TypeOfBackfacingModel_FrontCulled;
     case '1': return Graphic3d_TypeOfBackfacingModel_DoubleSided;
   }
   return Graphic3d_TypeOfBackfacingModel_Auto;
index aae849b5cd8880f410e65f91b39a6d8e5e0f7318..20e7b8a0a515a2234c9ba50449d48d801ba08532 100644 (file)
@@ -23,7 +23,8 @@ enum Graphic3d_TypeOfBackfacingModel
   Graphic3d_TypeOfBackfacingModel_Auto,        //!< automatic back face culling enabled for opaque groups with closed flag
                                                //!  (e.g. solids, see Graphic3d_Group::IsClosed())
   Graphic3d_TypeOfBackfacingModel_DoubleSided, //!< no culling (double-sided shading)
-  Graphic3d_TypeOfBackfacingModel_BackCulled,  //!< back face culling
+  Graphic3d_TypeOfBackfacingModel_BackCulled,  //!< back  face culling
+  Graphic3d_TypeOfBackfacingModel_FrontCulled, //!< front face culling
   // old aliases
   Graphic3d_TOBM_AUTOMATIC  = Graphic3d_TypeOfBackfacingModel_Auto,
   Graphic3d_TOBM_FORCE      = Graphic3d_TypeOfBackfacingModel_DoubleSided,
index e3655c8d1ae5d402754a155d08d7a3dbe5633d43..9380b93672f9f2613b185eae15ff2696c773c559 100644 (file)
@@ -237,7 +237,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myRenderMode (GL_RENDER),
   myShadeModel (GL_SMOOTH),
   myPolygonMode (GL_FILL),
-  myToCullBackFaces (false),
+  myFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided),
   myReadBuffer (0),
   myDrawBuffers (0, 7),
   myDefaultVao (0),
@@ -547,26 +547,35 @@ void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb)
 }
 
 // =======================================================================
-// function : SetCullBackFaces
+// function : SetFaceCulling
 // purpose  :
 // =======================================================================
-void OpenGl_Context::SetCullBackFaces (bool theToEnable)
+void OpenGl_Context::SetFaceCulling (Graphic3d_TypeOfBackfacingModel theMode)
 {
-  if (myToCullBackFaces == theToEnable)
+  if (myFaceCulling == theMode)
   {
     return;
   }
 
-  myToCullBackFaces = theToEnable;
-  if (theToEnable)
+  if (theMode == Graphic3d_TypeOfBackfacingModel_BackCulled)
   {
-    //glCullFace (GL_BACK); GL_BACK by default
+    if (myFaceCulling == Graphic3d_TypeOfBackfacingModel_FrontCulled)
+    {
+      core11fwd->glCullFace (GL_BACK);
+    }
+    core11fwd->glEnable (GL_CULL_FACE);
+  }
+  else if (theMode == Graphic3d_TypeOfBackfacingModel_FrontCulled)
+  {
+    core11fwd->glCullFace (GL_FRONT);
     core11fwd->glEnable (GL_CULL_FACE);
   }
   else
   {
+    core11fwd->glCullFace (GL_BACK);
     core11fwd->glDisable (GL_CULL_FACE);
   }
+  myFaceCulling = theMode;
 }
 
 // =======================================================================
@@ -3084,7 +3093,7 @@ void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer th
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode)
   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset)
-  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFaceCulling)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer)
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao)
index 2d42736de5c5dcc8fa4c0b7766696bd28c53cbe9..f86c4cc4618be365f01633aa959596aae9dcb952 100644 (file)
@@ -803,10 +803,19 @@ public: //! @name methods to alter or retrieve current state
   Standard_EXPORT bool SetSampleAlphaToCoverage (bool theToEnable);
 
   //! Return back face culling state.
-  bool ToCullBackFaces() const { return myToCullBackFaces; }
+  Graphic3d_TypeOfBackfacingModel FaceCulling() const { return myFaceCulling; }
 
   //! Enable or disable back face culling (glEnable (GL_CULL_FACE)).
-  Standard_EXPORT void SetCullBackFaces (bool theToEnable);
+  Standard_EXPORT void SetFaceCulling (Graphic3d_TypeOfBackfacingModel theMode);
+
+  //! Return back face culling state.
+  bool ToCullBackFaces() const { return myFaceCulling == Graphic3d_TypeOfBackfacingModel_BackCulled; }
+
+  //! Enable or disable back face culling (glCullFace() + glEnable(GL_CULL_FACE)).
+  void SetCullBackFaces (bool theToEnable)
+  {
+    SetFaceCulling (theToEnable ? Graphic3d_TypeOfBackfacingModel_BackCulled : Graphic3d_TypeOfBackfacingModel_DoubleSided);
+  }
 
   //! Fetch OpenGl context state. This class tracks value of several OpenGl
   //! state variables. Consulting the cached values is quicker than
@@ -1155,7 +1164,7 @@ private: //! @name fields tracking current state
   Standard_Integer              myShadeModel;      //!< currently used shade model (glShadeModel)
   Standard_Integer              myPolygonMode;     //!< currently used polygon rasterization mode (glPolygonMode)
   Graphic3d_PolygonOffset       myPolygonOffset;   //!< currently applied polygon offset
-  bool                          myToCullBackFaces; //!< back face culling mode enabled state (glIsEnabled (GL_CULL_FACE))
+  Graphic3d_TypeOfBackfacingModel myFaceCulling;   //!< back face culling mode enabled state (glIsEnabled (GL_CULL_FACE))
   Standard_Integer              myReadBuffer;      //!< current read buffer
   NCollection_Array1<Standard_Integer>
                                 myDrawBuffers;     //!< current draw buffers
index 5f1747ba4d889bb1a33c9e139d2eea2af9cdd1c4..151d1cc40aa45a202b6386a1a41ac3202e354ca9 100644 (file)
@@ -1030,10 +1030,9 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
       anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE),          anOrthoScale);
       aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
 
-      aCtx->core11fwd->glCullFace (GL_FRONT);
+      aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled);
       drawArray (theWorkspace, NULL, false);
-
-      aCtx->core11fwd->glCullFace (GL_BACK);
+      aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled);
     }
 
     if (isForcedBlend)
index a59d494af362e2eee28ecb1b8bc551fdc6dbca6c..91d1fa604f4e946986e5189a79912004fb5fb58b 100644 (file)
@@ -255,27 +255,34 @@ const OpenGl_Aspects* OpenGl_Workspace::SetAspects (const OpenGl_Aspects* theAsp
 // =======================================================================
 const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects (bool theToBindTextures)
 {
-  bool toSuppressBackFaces = myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_BackCulled;
-  if (myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_Auto)
+  //bool toSuppressBackFaces = myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_BackCulled;
+  Graphic3d_TypeOfBackfacingModel aCullFacesMode = myView->BackfacingModel();
+  if (aCullFacesMode == Graphic3d_TypeOfBackfacingModel_Auto)
   {
-    toSuppressBackFaces = myAspectsSet->Aspect()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_BackCulled;
-    if (myAspectsSet->Aspect()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_Auto
-     && myToAllowFaceCulling)
+    aCullFacesMode = myAspectsSet->Aspect()->FaceCulling();
+    if (aCullFacesMode == Graphic3d_TypeOfBackfacingModel_Auto)
     {
-      toSuppressBackFaces = true;
-      if (myAspectsSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
-       || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
-       || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
-       || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend
-       || (myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
-        && myAspectsSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
+      aCullFacesMode = Graphic3d_TypeOfBackfacingModel_DoubleSided;
+      if (myToAllowFaceCulling)
       {
-        // disable culling in case of translucent shading aspect
-        toSuppressBackFaces = false;
+        if (myAspectsSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
+         || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
+         || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
+         || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend
+         || (myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
+          && myAspectsSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
+        {
+          // disable culling in case of translucent shading aspect
+          aCullFacesMode = Graphic3d_TypeOfBackfacingModel_DoubleSided;
+        }
+        else
+        {
+          aCullFacesMode = Graphic3d_TypeOfBackfacingModel_BackCulled;
+        }
       }
     }
   }
-  myGlContext->SetCullBackFaces (toSuppressBackFaces);
+  myGlContext->SetFaceCulling (aCullFacesMode);
 
   if (myAspectsSet->Aspect() == myAspectsApplied
    && myHighlightStyle == myAspectFaceAppliedWithHL)
index a5f4ee3e110f12043f73e3656fa96f1438466ccf..d3c8cee6c7e87895fdcd223da1b91c4a23d13426 100644 (file)
@@ -493,7 +493,8 @@ void RWGltf_GltfMaterialMap::DefineMaterial (const XCAFPrs_Style& theStyle,
     // as both may share the same material having "auto" flag
     if (theStyle.Material().IsNull()
      || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_Auto
-     || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided)
+     || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided
+     || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_FrontCulled) // front culling flag cannot be exported to glTF
     {
       myWriter->Key ("doubleSided");
       myWriter->Bool (true);
index 2acf5a4f4c449e1432e7f2b1c880e1073f08bec9..0d9fe25ead6637cd443aa72a09a264351dc162b9 100644 (file)
@@ -1683,6 +1683,9 @@ struct ViewerTest_AspectsChangeSet
   Graphic3d_AlphaMode          AlphaMode;
   Standard_ShortReal           AlphaCutoff;
 
+  Standard_Integer             ToSetFaceCulling;
+  Graphic3d_TypeOfBackfacingModel FaceCulling;
+
   Standard_Integer             ToSetMaterial;
   Graphic3d_NameOfMaterial     Material;
   TCollection_AsciiString      MatName;
@@ -1764,6 +1767,8 @@ struct ViewerTest_AspectsChangeSet
     ToSetAlphaMode    (0),
     AlphaMode         (Graphic3d_AlphaMode_BlendAuto),
     AlphaCutoff       (0.5f),
+    ToSetFaceCulling  (0),
+    FaceCulling       (Graphic3d_TypeOfBackfacingModel_Auto),
     ToSetMaterial     (0),
     Material          (Graphic3d_NameOfMaterial_DEFAULT),
     ToSetShowFreeBoundary      (0),
@@ -1811,6 +1816,7 @@ struct ViewerTest_AspectsChangeSet
         && ToSetLineWidth         == 0
         && ToSetTransparency      == 0
         && ToSetAlphaMode         == 0
+        && ToSetFaceCulling       == 0
         && ToSetColor             == 0
         && ToSetBackFaceColor     == 0
         && ToSetMaterial          == 0
@@ -2064,6 +2070,15 @@ struct ViewerTest_AspectsChangeSet
         theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff);
       }
     }
+    if (ToSetFaceCulling != 0)
+    {
+      if (ToSetFaceCulling != -1
+       || theDrawer->HasOwnShadingAspect())
+      {
+        toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
+        theDrawer->ShadingAspect()->Aspect()->SetFaceCulling (FaceCulling);
+      }
+    }
     if (ToSetHatch != 0)
     {
       if (ToSetHatch != -1
@@ -2557,6 +2572,47 @@ static Standard_Integer VAspects (Draw_Interpretor& theDI,
         }
       }
     }
+    else if (anArg == "-setfaceculling"
+          || anArg == "-faceculling")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        Message::SendFail() << "Error: wrong syntax at " << anArg;
+        return 1;
+      }
+
+      aChangeSet->ToSetFaceCulling = 1;
+      {
+        TCollection_AsciiString aParam (theArgVec[anArgIter]);
+        aParam.LowerCase();
+        if (aParam == "auto")
+        {
+          aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_Auto;
+        }
+        else if (aParam == "backculled"
+              || aParam == "backcull"
+              || aParam == "back")
+        {
+          aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_BackCulled;
+        }
+        else if (aParam == "frontculled"
+              || aParam == "frontcull"
+              || aParam == "front")
+        {
+          aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_FrontCulled;
+        }
+        else if (aParam == "doublesided"
+              || aParam == "off")
+        {
+          aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_DoubleSided;
+        }
+        else
+        {
+          Message::SendFail() << "Error: wrong syntax at '" << aParam << "'";
+          return 1;
+        }
+      }
+    }
     else if (anArg == "-setvis"
           || anArg == "-setvisibility"
           || anArg == "-visibility")
@@ -3192,6 +3248,8 @@ static Standard_Integer VAspects (Draw_Interpretor& theDI,
       aChangeSet->ToSetAlphaMode = -1;
       aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
       aChangeSet->AlphaCutoff = 0.5f;
+      aChangeSet->ToSetFaceCulling = -1;
+      aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_Auto;
       aChangeSet->ToSetColor = -1;
       aChangeSet->Color = DEFAULT_COLOR;
       //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor
@@ -6708,7 +6766,7 @@ vsub 0/1 (off/on) [obj] : Subintensity(on/off) of selected objects
 vaspects [-noupdate|-update] [name1 [name2 [...]] | -defaults] [-subshapes subname1 [subname2 [...]]]
          [-visibility {0|1}]
          [-color {ColorName | R G B}] [-unsetColor]
-         [-backfaceColor Color]
+         [-backfaceColor Color] [-faceCulling {auto|back|front|doublesided}]
          [-material MatName] [-unsetMaterial]
          [-transparency Transp] [-unsetTransparency]
          [-width LineWidth] [-unsetWidth]
index 2ab74cad059e5ceb83be73876f1e183c0d04eab6..faf8258d8376c065d4e0cf96bf8723c8ad29af7c 100644 (file)
@@ -99,6 +99,7 @@ static const char* faceCullToString (Graphic3d_TypeOfBackfacingModel theMode)
   {
     case Graphic3d_TypeOfBackfacingModel_Auto:        return "Auto";
     case Graphic3d_TypeOfBackfacingModel_BackCulled:  return "BackCulled";
+    case Graphic3d_TypeOfBackfacingModel_FrontCulled: return "FrontCulled";
     case Graphic3d_TypeOfBackfacingModel_DoubleSided: return "DoubleSided";
   }
   return "";
@@ -1161,6 +1162,12 @@ static Standard_Integer XAddVisMaterial (Draw_Interpretor& , Standard_Integer th
       {
         aMode = Graphic3d_TypeOfBackfacingModel_BackCulled;
       }
+      else if (aCullStr == "frontculled"
+            || aCullStr == "frontcull"
+            || aCullStr == "front")
+      {
+        aMode = Graphic3d_TypeOfBackfacingModel_FrontCulled;
+      }
       else if (aCullStr == "doublesided")
       {
         aMode = Graphic3d_TypeOfBackfacingModel_DoubleSided;
index c63fcd1905487e698e158b46acbab00351104a95..257620e455714e9b5b89fda11d1849d0b2c9febb 100644 (file)
@@ -256,11 +256,14 @@ Standard_Boolean XmlMXCAFDoc_VisMaterialDriver::Paste (const XmlObjMgt_Persisten
   aDoubleSidedStr.GetInteger (aDoubleSidedInt);
   Standard_ShortReal anAlphaCutOff = 0.5f;
   readReal (theSource, ::AlphaCutOff(), anAlphaCutOff);
-  aMat->SetFaceCulling (aDoubleSidedInt == 1
-                      ? Graphic3d_TypeOfBackfacingModel_DoubleSided
-                      : (aDoubleSidedInt == 2
-                       ? Graphic3d_TypeOfBackfacingModel_BackCulled
-                       : Graphic3d_TypeOfBackfacingModel_Auto));
+  switch (aDoubleSidedInt)
+  {
+    case 1:  aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided); break;
+    case 2:  aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled);  break;
+    case 3:  aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled); break;
+    case 0:
+    default: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_Auto); break;
+  }
   aMat->SetAlphaMode (alphaModeFromString (theSource.Element().getAttribute (::AlphaMode()).GetString()), anAlphaCutOff);
 
   Quantity_ColorRGBA aBaseColor;
@@ -307,11 +310,14 @@ void XmlMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSourc
                                            XmlObjMgt_SRelocationTable&  ) const
 {
   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource);
-  Standard_Integer aDoubleSidedInt = aMat->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided
-                                   ? 1
-                                   : (aMat->FaceCulling() == Graphic3d_TypeOfBackfacingModel_BackCulled
-                                    ? 2
-                                    : 0);
+  Standard_Integer aDoubleSidedInt = 0;
+  switch (aMat->FaceCulling())
+  {
+    case Graphic3d_TypeOfBackfacingModel_DoubleSided: aDoubleSidedInt = 1; break;
+    case Graphic3d_TypeOfBackfacingModel_BackCulled:  aDoubleSidedInt = 2; break;
+    case Graphic3d_TypeOfBackfacingModel_FrontCulled: aDoubleSidedInt = 3; break;
+    case Graphic3d_TypeOfBackfacingModel_Auto:        aDoubleSidedInt = 0; break;
+  }
   theTarget.Element().setAttribute (::IsDoubleSided(), aDoubleSidedInt);
   theTarget.Element().setAttribute (::AlphaMode(),     alphaModeToString (aMat->AlphaMode()));
   writeReal (theTarget, ::AlphaCutOff(), aMat->AlphaCutOff());
diff --git a/tests/opengl/data/general/cullface b/tests/opengl/data/general/cullface
new file mode 100644 (file)
index 0000000..9eddd98
--- /dev/null
@@ -0,0 +1,42 @@
+puts "========"
+puts "0033056: Visualization - add front face culling option"
+puts "Check face culling options"
+puts "========"
+
+set THE_NB_BOXES 4
+set THE_COLORS { ORANGE ORANGE ORANGE ORANGE }
+set THE_MODES  { AUTO BACK FRONT DOUBLESIDED }
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+vcamera -persp -fovy 80
+vfront
+
+set x 1
+set z 1
+for { set i 1 } { $i <= $THE_NB_BOXES } { incr i } {
+  box b$i [expr $x * 300] 0 [expr $z * 400] 200 300 300
+  vdisplay -dispMode 1 b$i
+  vsetcolor b$i [lindex $THE_COLORS [expr $i - 1]]
+  vaspects  b$i -faceCulling [lindex $THE_MODES [expr $i - 1]]
+  
+  vdrawtext t$i [lindex $THE_MODES [expr $i - 1]] -pos [expr $x * 300] 0 [expr $z * 400 + 300] -height 16 -color RED -font MONOSPACE -aspect BOLD -valign top
+
+  incr x
+  if { $i == 2 } {
+    set x 1
+    set z 2
+  }
+}
+vfit
+
+vaspects -faceBoundaryDraw 1 -faceBoundaryColor RED
+vdump $::imagedir/${::casename}_bnds.png
+
+vaspects -faceBoundaryDraw 0
+vclipplane c -equation 0 1 0 -100 -set
+vdump $::imagedir/${::casename}_clip.png
+
+vclipplane c off
+vdump $::imagedir/${::casename}.png