Index: Qt/Components/pqDisplayProxyEditor.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Qt/Components/pqDisplayProxyEditor.cxx,v
retrieving revision 1.75
diff -u -r1.75 pqDisplayProxyEditor.cxx
--- Qt/Components/pqDisplayProxyEditor.cxx	9 Jun 2009 17:33:32 -0000	1.75
+++ Qt/Components/pqDisplayProxyEditor.cxx	10 Jun 2009 19:40:59 -0000
@@ -384,6 +384,15 @@
     "value", SIGNAL(editingFinished()),
     reprProxy, reprProxy->GetProperty("Opacity"));
 
+  // setup of nonlinear subdivision
+  if (reprProxy->GetProperty("NonlinearSubdivisionLevel"))
+    {
+    this->Internal->Links->addPropertyLink(
+                this->Internal->NonlinearSubdivisionLevel,
+                "value", SIGNAL(valueChanged(int)),
+                reprProxy, reprProxy->GetProperty("NonlinearSubdivisionLevel"));
+    }
+
   // setup for map scalars
   this->Internal->Links->addPropertyLink(
     this->Internal->ColorMapScalars, "checked", SIGNAL(stateChanged(int)),
Index: Qt/Components/Resources/UI/pqDisplayProxyEditor.ui
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Qt/Components/Resources/UI/pqDisplayProxyEditor.ui,v
retrieving revision 1.42
diff -u -r1.42 pqDisplayProxyEditor.ui
--- Qt/Components/Resources/UI/pqDisplayProxyEditor.ui	9 Jun 2009 17:33:32 -0000	1.42
+++ Qt/Components/Resources/UI/pqDisplayProxyEditor.ui	10 Jun 2009 19:40:59 -0000
@@ -669,14 +669,44 @@
         </property>
        </spacer>
       </item>
-      <item row="7" column="0" >
+      <item row="7" column="0">
+       <widget class="QLabel" name="label_17">
+        <property name="text">
+         <string>Subdivision</string>
+        </property>
+       </widget>
+      </item>
+      <item row="7" column="1">
+       <widget class="QSpinBox" name="NonlinearSubdivisionLevel">
+        <property name="toolTip">
+         <string>Nonlinear faces are approximated with flat polygons.  This parameter controls how many times to subdivide nonlinear surface cells.  Higher subdivisions generate closer approximations but take more memory and rendering time.  Subdivision is recursive, so the number of output polygons can grow exponentially with this parameter.</string>
+        </property>
+        <property name="maximum">
+         <number>4</number>
+        </property>
+       </widget>
+      </item>
+      <item row="7" column="2">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="8" column="0" >
        <widget class="QLabel" name="label_19" >
         <property name="text" >
          <string>Volume mapper</string>
         </property>
        </widget>
       </item>
-      <item row="7" column="1" colspan="2" >
+      <item row="8" column="1" colspan="2" >
        <widget class="QComboBox" name="SelectedMapperIndex" >
         <property name="toolTip" >
          <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the mapper to use for volume rendering.&lt;/p>&lt;/body>&lt;/html></string>
@@ -1217,6 +1247,7 @@
   <tabstop>StylePointSize</tabstop>
   <tabstop>StyleLineWidth</tabstop>
   <tabstop>Opacity</tabstop>
+  <tabstop>NonlinearSubdivisionLevel</tabstop>
   <tabstop>SelectedMapperIndex</tabstop>
   <tabstop>EdgeColor</tabstop>
   <tabstop>SpecularIntensity</tabstop>
Index: Servers/Filters/vtkPVGeometryFilter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/Filters/vtkPVGeometryFilter.cxx,v
retrieving revision 1.94
diff -u -r1.94 vtkPVGeometryFilter.cxx
--- Servers/Filters/vtkPVGeometryFilter.cxx	8 May 2009 14:07:39 -0000	1.94
+++ Servers/Filters/vtkPVGeometryFilter.cxx	10 Jun 2009 19:40:59 -0000
@@ -18,6 +18,7 @@
 #include "vtkCallbackCommand.h"
 #include "vtkCellArray.h"
 #include "vtkCellData.h"
+#include "vtkCellTypes.h"
 #include "vtkCleanArrays.h"
 #include "vtkCommand.h"
 #include "vtkCompositeDataIterator.h"
@@ -53,11 +54,15 @@
 #include "vtkUnsignedCharArray.h"
 #include "vtkUnsignedIntArray.h"
 #include "vtkUnstructuredGrid.h"
+#include "vtkUnstructuredGridGeometryFilter.h"
 
 #include <vtkstd/map>
 #include <vtkstd/string>
 #include <assert.h>
 
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
 vtkCxxRevisionMacro(vtkPVGeometryFilter, "$Revision: 1.94 $");
 vtkStandardNewMacro(vtkPVGeometryFilter);
 
@@ -124,10 +129,12 @@
   this->UseOutline = 1;
   this->UseStrips = 0;
   this->GenerateCellNormals = 1;
+  this->NonlinearSubdivisionLevel = 1;
 
   this->DataSetSurfaceFilter = vtkDataSetSurfaceFilter::New();
   this->GenericGeometryFilter=vtkGenericGeometryFilter::New();
-  
+  this->UnstructuredGridGeometryFilter=vtkUnstructuredGridGeometryFilter::New();
+
   // Setup a callback for the internal readers to report progress.
   this->InternalProgressObserver = vtkCallbackCommand::New();
   this->InternalProgressObserver->SetCallback(
@@ -154,13 +161,25 @@
 //----------------------------------------------------------------------------
 vtkPVGeometryFilter::~vtkPVGeometryFilter ()
 {
-  if(this->DataSetSurfaceFilter)
+  // Be careful how you delete these so that you don't foul up the garbage
+  // collector.
+  if (this->DataSetSurfaceFilter)
     {
-    this->DataSetSurfaceFilter->Delete();
+    vtkDataSetSurfaceFilter *tmp = this->DataSetSurfaceFilter;
+    this->DataSetSurfaceFilter = NULL;
+    tmp->Delete();
     }
-  if(this->GenericGeometryFilter!=0)
+  if (this->GenericGeometryFilter)
     {
-    this->GenericGeometryFilter->Delete();
+    vtkGenericGeometryFilter *tmp = this->GenericGeometryFilter;
+    this->GenericGeometryFilter = NULL;
+    tmp->Delete();
+    }
+  if (this->UnstructuredGridGeometryFilter)
+    {
+    vtkUnstructuredGridGeometryFilter *tmp=this->UnstructuredGridGeometryFilter;
+    this->UnstructuredGridGeometryFilter = NULL;
+    tmp->Delete();
     }
   this->OutlineSource->Delete();
   this->InternalProgressObserver->Delete();
@@ -1009,6 +1028,51 @@
   if (!this->UseOutline)
     {
     this->OutlineFlag = 0;
+
+    bool handleSubdivision = false;
+    if (this->NonlinearSubdivisionLevel > 0)
+      {
+      // Check to see if the data actually has nonlinear cells.  Handling
+      // nonlinear cells adds unnecessary work if we only have linear cells.
+      vtkUnsignedCharArray *types = input->GetCellTypesArray();
+      vtkIdType numCells = input->GetNumberOfCells();
+      for (vtkIdType i = 0; i < numCells; i++)
+        {
+        if (!vtkCellTypes::IsLinear(types->GetValue(i)))
+          {
+          handleSubdivision = true;
+          break;
+          }
+        }
+      }
+
+    if (handleSubdivision)
+      {
+      // Use the vtkUnstructuredGridGeometryFilter to extract 2D surface cells
+      // from the geometry.  This is important to extract an appropriate
+      // wireframe.  Also, at the time of this writing vtkDataSetSurfaceFilter
+      // only properly subdivides 2D cells past level 1.
+      VTK_CREATE(vtkUnstructuredGrid, inputClone);
+      inputClone->ShallowCopy(input);
+      this->UnstructuredGridGeometryFilter->SetInput(inputClone);
+
+      // Observe the progress of the internal filter.
+      // TODO: Make the consecutive internal filter execution have monotonically
+      // increasing progress rather than restarting for every internal filter.
+      this->UnstructuredGridGeometryFilter->AddObserver(
+                                                vtkCommand::ProgressEvent,
+                                                this->InternalProgressObserver);
+      this->UnstructuredGridGeometryFilter->Update();
+      // The internal filter finished.  Remove the observer.
+      this->UnstructuredGridGeometryFilter->RemoveObserver(
+                                                this->InternalProgressObserver);
+
+      this->UnstructuredGridGeometryFilter->SetInput(NULL);
+
+      // Feed the extracted surface as the input to the rest of the processing.
+      input->ShallowCopy(this->UnstructuredGridGeometryFilter->GetOutput());
+      }
+
     this->DataSetSurfaceExecute(input, output);
     return;
     }
@@ -1132,6 +1196,8 @@
                             "DataSetSurfaceFilter");
   vtkGarbageCollectorReport(collector, this->GenericGeometryFilter,
                             "GenericGeometryFilter");
+  vtkGarbageCollectorReport(collector, this->UnstructuredGridGeometryFilter,
+                            "UnstructuredGridGeometryFilter");
 }
 
 //----------------------------------------------------------------------------
@@ -1152,6 +1218,8 @@
   os << indent << "UseStrips: " << (this->UseStrips?"on":"off") << endl;
   os << indent << "GenerateCellNormals: " 
      << (this->GenerateCellNormals?"on":"off") << endl;
+  os << indent << "NonlinearSubdivisionLevel: "
+     << this->NonlinearSubdivisionLevel << endl;
   os << indent << "Controller: " << this->Controller << endl;
 
   os << indent << "PassThroughCellIds: " 
@@ -1235,3 +1303,20 @@
     this->StripSettingMTime.Modified();
     }
 }
+
+//-----------------------------------------------------------------------------
+void vtkPVGeometryFilter::SetNonlinearSubdivisionLevel(int newvalue)
+{
+  if (this->NonlinearSubdivisionLevel != newvalue)
+    {
+    this->NonlinearSubdivisionLevel = newvalue;
+
+    if (this->DataSetSurfaceFilter)
+      {
+      this->DataSetSurfaceFilter->SetNonlinearSubdivisionLevel(
+                                               this->NonlinearSubdivisionLevel);
+      }
+
+    this->Modified();
+    }
+}
Index: Servers/Filters/vtkPVGeometryFilter.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/Filters/vtkPVGeometryFilter.h,v
retrieving revision 1.45
diff -u -r1.45 vtkPVGeometryFilter.h
--- Servers/Filters/vtkPVGeometryFilter.h	22 Sep 2008 18:16:00 -0000	1.45
+++ Servers/Filters/vtkPVGeometryFilter.h	10 Jun 2009 19:40:59 -0000
@@ -38,6 +38,7 @@
 class vtkRectilinearGrid;
 class vtkStructuredGrid;
 class vtkUnstructuredGrid;
+class vtkUnstructuredGridGeometryFilter;
 
 class VTK_EXPORT vtkPVGeometryFilter : public vtkPolyDataAlgorithm
 {
@@ -80,6 +81,15 @@
   vtkBooleanMacro(GenerateCellNormals, int);
 
   // Description:
+  // Nonlinear faces are approximated with flat polygons.  This parameter
+  // controls how many times to subdivide nonlinear surface cells.  Higher
+  // subdivisions generate closer approximations but take more memory and
+  // rendering time.  Subdivision is recursive, so the number of output polygons
+  // can grow exponentially with this parameter.
+  virtual void SetNonlinearSubdivisionLevel(int);
+  vtkGetMacro(NonlinearSubdivisionLevel, int);
+
+  // Description:
   // Set and get the controller.
   virtual void SetController(vtkMultiProcessController*);
   vtkGetObjectMacro(Controller, vtkMultiProcessController);
@@ -151,11 +161,13 @@
   int UseOutline;
   int UseStrips;
   int GenerateCellNormals;
+  int NonlinearSubdivisionLevel;
 
   vtkMultiProcessController* Controller;
   vtkOutlineSource *OutlineSource;
   vtkDataSetSurfaceFilter* DataSetSurfaceFilter;
   vtkGenericGeometryFilter *GenericGeometryFilter;
+  vtkUnstructuredGridGeometryFilter *UnstructuredGridGeometryFilter;
   
   int CheckAttributes(vtkDataObject* input);
 
Index: Servers/ServerManager/Resources/filters.xml
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/ServerManager/Resources/filters.xml,v
retrieving revision 1.352
diff -u -r1.352 filters.xml
--- Servers/ServerManager/Resources/filters.xml	8 Jun 2009 15:02:01 -0000	1.352
+++ Servers/ServerManager/Resources/filters.xml	10 Jun 2009 19:40:59 -0000
@@ -1524,6 +1524,26 @@
          If the value of this property is set to 1, internal surfaces along process boundaries will be removed. NOTE: Enabling this option might cause multiple executions of the data source because more information is needed to remove internal surfaces.
        </Documentation>
      </IntVectorProperty>
+
+     <IntVectorProperty name="NonlinearSubdivisionLevel"
+                        command="SetNonlinearSubdivisionLevel"
+                        number_of_elements="1"
+                        default_values="1">
+       <IntRangeDomain name="range" min="0" max="4" />
+       <Documentation>
+         If the input is an unstructured grid with nonlinear faces, this
+         parameter determines how many times the face is subdivided into
+         linear faces.  If 0, the output is the equivalent of its linear
+         couterpart (and the midpoints determining the nonlinear
+         interpolation are discarded).  If 1, the nonlinear face is
+         triangulated based on the midpoints.  If greater than 1, the
+         triangulated pieces are recursively subdivided to reach the
+         desired subdivision.  Setting the value to greater than 1 may
+         cause some point data to not be passed even if no quadratic faces
+         exist.  This option has no effect if the input is not an
+         unstructured grid.
+       </Documentation>
+     </IntVectorProperty>
    <!-- End DataSetSurfaceFilter -->
    </SourceProxy>
 
@@ -6863,6 +6883,20 @@
           Toggle whether to generate an outline or a surface.
         </Documentation>
       </IntVectorProperty>
+      <IntVectorProperty name="NonlinearSubdivisionLevel"
+                         command="SetNonlinearSubdivisionLevel"
+                         number_of_elements="1"
+                         default_values="1">
+        <IntRangeDomain name="range" min="0" max="4" />
+        <Documentation>
+          Nonlinear faces are approximated with flat polygons.  This
+          parameter controls how many times to subdivide nonlinear surface
+          cells.  Higher subdivisions generate closer approximations but
+          take more memory and rendering time.  Subdivision is recursive,
+          so the number of output polygons can grow exponentially with this
+          parameter.
+        </Documentation>
+      </IntVectorProperty>
       <IntVectorProperty
         name="PassThroughIds"
         command="SetPassThroughCellIds"
Index: Servers/ServerManager/Resources/rendering.xml
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/ServerManager/Resources/rendering.xml,v
retrieving revision 1.352
diff -u -r1.352 rendering.xml
--- Servers/ServerManager/Resources/rendering.xml	9 Jun 2009 17:38:12 -0000	1.352
+++ Servers/ServerManager/Resources/rendering.xml	10 Jun 2009 19:40:59 -0000
@@ -5870,6 +5870,7 @@
         <ExposedProperties>
           <Property name="UseStrips" />
           <Property name="ForceStrips" />
+          <Property name="NonlinearSubdivisionLevel" />
         </ExposedProperties>
       </SubProxy>
   
@@ -6651,6 +6652,7 @@
           <!-- Geometry Filter properties -->
           <Property name="UseStrips" />
           <Property name="ForceStrips" />
+          <Property name="NonlinearSubdivisionLevel" />
 
           <!-- Mapper properties -->
           <Property name="LookupTable" />
Index: VTK/Filtering/vtkCellType.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Filtering/vtkCellType.h,v
retrieving revision 1.5
diff -u -r1.5 vtkCellType.h
--- VTK/Filtering/vtkCellType.h	7 May 2007 15:40:59 -0000	1.5
+++ VTK/Filtering/vtkCellType.h	10 Jun 2009 19:41:00 -0000
@@ -29,7 +29,8 @@
 // GetCell() and vtkGenericCell::SetCellType(). Also, to do the job right,
 // you'll also have to modify some filters (vtkGeometryFilter...) and
 // regression tests (example scripts) to reflect the new cell addition.
-// Also, make sure to update vtkCellTypesStrings in vtkCellTypes.cxx.
+// Also, make sure to update vtkCellTypesStrings in vtkCellTypes.cxx
+// and the vtkCellTypes::IsLinear method in vtkCellTypes.h.
 
 // .SECTION Caveats
 // An unstructured grid stores the types of its cells as a
Index: VTK/Filtering/vtkCellTypes.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Filtering/vtkCellTypes.h,v
retrieving revision 1.3
diff -u -r1.3 vtkCellTypes.h
--- VTK/Filtering/vtkCellTypes.h	11 Dec 2008 21:47:19 -0000	1.3
+++ VTK/Filtering/vtkCellTypes.h	10 Jun 2009 19:41:00 -0000
@@ -118,6 +118,13 @@
   // defined in vtkCellType.h)
   static int GetTypeIdFromClassName(const char* classname);
 
+  // Description:
+  // This convenience method is a fast check to determine if a cell type
+  // represents a linear or nonlinear cell.  This is generally much more
+  // efficient than getting the appropriate vtkCell and checking its IsLinear
+  // method.
+  static int IsLinear(unsigned char type);
+
 protected:
   vtkCellTypes();
   ~vtkCellTypes();
@@ -148,5 +155,11 @@
   return 0;
 }
 
+//-----------------------------------------------------------------------------
+inline int vtkCellTypes::IsLinear(unsigned char type)
+{
+  return ((type <= 20) || (type == VTK_CONVEX_POINT_SET));
+}
+
 
 #endif
Index: VTK/Graphics/vtkDataSetSurfaceFilter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Graphics/vtkDataSetSurfaceFilter.cxx,v
retrieving revision 1.70
diff -u -r1.70 vtkDataSetSurfaceFilter.cxx
--- VTK/Graphics/vtkDataSetSurfaceFilter.cxx	25 Mar 2009 14:35:52 -0000	1.70
+++ VTK/Graphics/vtkDataSetSurfaceFilter.cxx	10 Jun 2009 19:41:00 -0000
@@ -16,8 +16,10 @@
 
 #include "vtkCellArray.h"
 #include "vtkCellData.h"
+#include "vtkDoubleArray.h"
 #include "vtkGenericCell.h"
 #include "vtkHexahedron.h"
+#include "vtkIdTypeArray.h"
 #include "vtkInformation.h"
 #include "vtkInformationVector.h"
 #include "vtkMergePoints.h"
@@ -26,18 +28,19 @@
 #include "vtkPolyData.h"
 #include "vtkPyramid.h"
 #include "vtkRectilinearGrid.h"
-#include "vtkStructuredGrid.h"
-#include "vtkUniformGrid.h"
 #include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkStructuredGrid.h"
 #include "vtkStructuredGridGeometryFilter.h"
 #include "vtkStructuredPoints.h"
 #include "vtkTetra.h"
+#include "vtkUniformGrid.h"
 #include "vtkUnsignedCharArray.h"
 #include "vtkUnstructuredGrid.h"
 #include "vtkVoxel.h"
 #include "vtkWedge.h"
-#include "vtkIdTypeArray.h"
 
+#include <vtkstd/algorithm>
+#include <vtksys/hash_map.hxx>
 
 static int sizeofFastQuad(int numPts)
 {
@@ -45,6 +48,39 @@
   return static_cast<int>(sizeof(vtkFastGeomQuad)+(numPts-4)*sizeof(vtkIdType));
 }
 
+class vtkDataSetSurfaceFilter::vtkEdgeInterpolationMap
+{
+public:
+  void AddEdge(vtkIdType endpoint1, vtkIdType endpoint2, vtkIdType midpoint) {
+    if (endpoint1 > endpoint2) vtkstd::swap(endpoint1, endpoint2);
+    Map.insert(vtkstd::make_pair(vtkstd::make_pair(endpoint1, endpoint2),
+                                 midpoint));
+  }
+  vtkIdType FindEdge(vtkIdType endpoint1, vtkIdType endpoint2) {
+    if (endpoint1 > endpoint2) vtkstd::swap(endpoint1, endpoint2);
+    MapType::iterator iter = Map.find(vtkstd::make_pair(endpoint1, endpoint2));
+    if (iter != Map.end())
+      {
+      return iter->second;
+      }
+    else
+      {
+      return -1;
+      }
+  }
+    
+protected:
+  struct HashFunction {
+  public:
+    size_t operator()(vtkstd::pair<vtkIdType,vtkIdType> edge) const {
+      return static_cast<size_t>(edge.first + edge.second);
+    }
+  };
+  typedef vtksys::hash_map<vtkstd::pair<vtkIdType, vtkIdType>, vtkIdType,
+                           HashFunction> MapType;
+  MapType Map;
+};
+
 vtkCxxRevisionMacro(vtkDataSetSurfaceFilter, "$Revision: 1.70 $");
 vtkStandardNewMacro(vtkDataSetSurfaceFilter);
 
@@ -53,6 +89,7 @@
 {
   this->QuadHash = NULL;
   this->PointMap = NULL;
+  this->EdgeMap = NULL;
   this->QuadHashLength = 0;
   this->UseStrips = 0;
   this->NumberOfNewCells = 0;
@@ -70,6 +107,8 @@
   this->PassThroughPointIds = 0;
   this->OriginalCellIds = NULL;
   this->OriginalPointIds = NULL;
+
+  this->NonlinearSubdivisionLevel = 1;
 }
 
 //----------------------------------------------------------------------------
@@ -916,6 +955,8 @@
   os << indent << "PassThroughCellIds: " << (this->PassThroughCellIds ? "On\n" : "Off\n");
   os << indent << "PassThroughPointIds: " << (this->PassThroughPointIds ? "On\n" : "Off\n");
 
+  os << indent << "NonlinearSubdivisionLevel: "
+     << this->NonlinearSubdivisionLevel << endl;
 }
 
 //========================================================================
@@ -949,7 +990,6 @@
   vtkCellData *cd = input->GetCellData();
   vtkPointData *outputPD = output->GetPointData();
   vtkCellData *outputCD = output->GetCellData();
-  vtkIdType outPts[6];
   vtkFastGeomQuad *q;
   unsigned char* cellTypes = input->GetCellTypesArray()->GetPointer(0);
 
@@ -958,9 +998,19 @@
   vtkPoints *coords;
   vtkCell *face;
   int flag2D = 0;
+
+  // These are for subdividing quadratic cells
+  vtkDoubleArray *parametricCoords;
+  vtkDoubleArray *parametricCoords2;
+  vtkIdList *outPts;
+  vtkIdList *outPts2;
   
   pts = vtkIdList::New();  
   coords = vtkPoints::New();
+  parametricCoords = vtkDoubleArray::New();
+  parametricCoords2 = vtkDoubleArray::New();
+  outPts = vtkIdList::New();
+  outPts2 = vtkIdList::New();
   // might not be necessary to set the data type for coords
   // but certainly safer to do so
   coords->SetDataType(input->GetPoints()->GetData()->GetDataType());
@@ -979,8 +1029,15 @@
   newVerts = vtkCellArray::New();
   newLines = vtkCellArray::New();
 
-  outputPD->CopyGlobalIdsOn();
-  outputPD->CopyAllocate(inputPD, numPts, numPts/2);
+  if (this->NonlinearSubdivisionLevel <= 1)
+    {
+    outputPD->CopyGlobalIdsOn();
+    outputPD->CopyAllocate(inputPD, numPts, numPts/2);
+    }
+  else
+    {
+    outputPD->InterpolateAllocate(inputPD, numPts, numPts/2);
+    }
   outputCD->CopyGlobalIdsOn();
   outputCD->CopyAllocate(inputCD, numCells, numCells/2);
 
@@ -1201,14 +1258,40 @@
             if ( cellIds->GetNumberOfIds() <= 0)
               {
               // FIXME: Face could not be consistent. vtkOrderedTriangulator is a better option
-              face->Triangulate(0,pts,coords);
-              for (i=0; i < pts->GetNumberOfIds(); i+=3)
+              if (this->NonlinearSubdivisionLevel >= 1)
                 {
-                this->InsertTriInHash(pts->GetId(i), pts->GetId(i+1),
-                                      pts->GetId(i+2), cellId);
+                // TODO: Handle NonlinearSubdivisionLevel > 1 correctly.
+                face->Triangulate(0,pts,coords);
+                for (i=0; i < pts->GetNumberOfIds(); i+=3)
+                  {
+                  this->InsertTriInHash(pts->GetId(i), pts->GetId(i+1),
+                                        pts->GetId(i+2), cellId);
+                  }
                 }
-              }
-            }
+              else
+                {
+                switch (face->GetCellType())
+                  {
+                  case VTK_QUADRATIC_TRIANGLE:
+                    this->InsertTriInHash(face->PointIds->GetId(0),
+                                          face->PointIds->GetId(1),
+                                          face->PointIds->GetId(2), cellId);
+                    break;
+                  case VTK_QUADRATIC_QUAD:
+                  case VTK_BIQUADRATIC_QUAD:
+                  case VTK_QUADRATIC_LINEAR_QUAD:
+                    this->InsertQuadInHash(face->PointIds->GetId(0),
+                                           face->PointIds->GetId(1),
+                                           face->PointIds->GetId(2),
+                                           face->PointIds->GetId(3), cellId);
+                    break;
+                  default:
+                    vtkWarningMacro(<< "Encountered unknown nonlinear face.");
+                    break;
+                  } // switch cell type
+                } // subdivision level
+              } // cell has ids
+            } // for faces
           cellIds->Delete();
           } //3d cell
         } //nonlinear cell
@@ -1232,6 +1315,25 @@
     // Move to the next cell.
     cellPointer += (1 + *cellPointer);
 
+    // If we have a quadratic face and our subdivision level is zero, just treat
+    // it as a linear cell.  This should work so long as the first points of the
+    // quadratic cell correspond to all those of the equivalent linear cell
+    // (which all the current definitions do).
+    if (this->NonlinearSubdivisionLevel < 1)
+      {
+      switch (cellType)
+        {
+        case VTK_QUADRATIC_TRIANGLE:
+          cellType = VTK_TRIANGLE;  numCellPts = 3;
+          break;
+        case VTK_QUADRATIC_QUAD:
+        case VTK_BIQUADRATIC_QUAD:
+        case VTK_QUADRATIC_LINEAR_QUAD:
+          cellType = VTK_POLYGON;  numCellPts = 4;
+          break;
+        }
+      }
+
     // A couple of common cases to see if things go faster.
     if (cellType == VTK_PIXEL)
       { // Do we really want to insert the 2D cells into a hash?
@@ -1283,14 +1385,99 @@
            || cellType == VTK_BIQUADRATIC_QUAD
            || cellType == VTK_QUADRATIC_LINEAR_QUAD)
       {
+      // Note: we should not be here if this->NonlinearSubdivisionLevel is less
+      // than 1.  See the check above.
       input->GetCell( cellId, cell );
       cell->Triangulate( 0, pts, coords );
-      for ( i=0; i < pts->GetNumberOfIds(); i+=3 )
+      // Copy the level 1 subdivision points (which also exist in the input and
+      // can therefore just be copied over.  Note that the output of Triangulate
+      // records triangles in pts where each 3 points defines a triangle.  We
+      // will keep this invariant and also keep the same invariant in
+      // parametericCoords and outPts later.
+      outPts->Reset();
+      for ( i=0; i < pts->GetNumberOfIds(); i++ )
+        {
+        vtkIdType op;
+        op = this->GetOutputPointId(pts->GetId(i), input, newPts, outputPD);
+        outPts->InsertNextId(op);
+        }
+      // Do any further subdivision if necessary.
+      if (this->NonlinearSubdivisionLevel > 1)
+        {
+        // We are going to need parametric coordinates to further subdivide.
+        double *pc = cell->GetParametricCoords();
+        parametricCoords->Reset();
+        parametricCoords->SetNumberOfComponents(3);
+        for (i = 0; i < pts->GetNumberOfIds(); i++)
+          {
+          vtkIdType ptId = pts->GetId(i);
+          vtkIdType cellPtId;
+          for (cellPtId = 0; cell->GetPointId(cellPtId) != ptId; cellPtId++);
+          parametricCoords->InsertNextTupleValue(pc + 3*cellPtId);
+          }
+        // Subdivide these triangles as many more times as necessary.  Remember
+        // that we have already done the first subdivision.
+        for (j = 1; j < this->NonlinearSubdivisionLevel; j++)
+          {
+          parametricCoords2->Reset();
+          parametricCoords2->SetNumberOfComponents(3);
+          outPts2->Reset();
+          // Each triangle will be split into 4 triangles.
+          for (i = 0; i < outPts->GetNumberOfIds(); i += 3)
+            {
+            // Hold the input point ids and parametric coordinates.  First 3
+            // indices are the original points.  Second three are the midpoints
+            // in the edges (0,1), (1,2) and (2,0), respectively (see comment
+            // below).
+            vtkIdType inPts[6];
+            double inParamCoords[6][3];
+            int k;
+            for (k = 0; k < 3; k++)
+              {
+              inPts[k] = outPts->GetId(i+k);
+              parametricCoords->GetTupleValue(i+k, inParamCoords[k]);
+              }
+            for (k = 3; k < 6; k++)
+              {
+              int pt1 = k-3;
+              int pt2 = (pt1 < 2) ? (pt1 + 1) : 0;
+              inParamCoords[k][0] = 0.5*(inParamCoords[pt1][0] + inParamCoords[pt2][0]);
+              inParamCoords[k][1] = 0.5*(inParamCoords[pt1][1] + inParamCoords[pt2][1]);
+              inParamCoords[k][2] = 0.5*(inParamCoords[pt1][2] + inParamCoords[pt2][2]);
+              inPts[k] = GetInterpolatedPointId(inPts[pt1], inPts[pt2],
+                                                input, cell,
+                                                inParamCoords[k], newPts,
+                                                outputPD);
+              }
+            //       * 0
+            //      / \        Use the 6 points recorded
+            //     /   \       in inPts and inParamCoords
+            //  3 *-----* 5    to create the 4 triangles
+            //   / \   / \     shown here.
+            //  /   \ /   \    .
+            // *-----*-----*
+            // 1     4     2
+            const int subtriangles[12] = {0,3,5,   3,1,4,   3,4,5,   5,4,2};
+            for (k = 0; k < 12; k++)
+              {
+              int localId = subtriangles[k];
+              outPts2->InsertNextId(inPts[localId]);
+              parametricCoords2->InsertNextTupleValue(inParamCoords[localId]);
+              }
+            } // Iterate over triangles
+          // Now that we have recorded the subdivided triangles in outPts2 and
+          // parametricCoords2, swap them with outPts and parametricCoords to
+          // make them the current ones.
+          vtkstd::swap(outPts, outPts2);
+          vtkstd::swap(parametricCoords, parametricCoords2);
+          } // Iterate over subdivision levels
+        } // If further subdivision
+
+      // Now that we have done all the subdivisions and created all of the
+      // points, record the triangles.
+      for (i = 0; i < outPts->GetNumberOfIds(); i += 3)
         {
-        outPts[0] = this->GetOutputPointId( pts->GetId(i),   input, newPts, outputPD );
-        outPts[1] = this->GetOutputPointId( pts->GetId(i+1), input, newPts, outputPD );
-        outPts[2] = this->GetOutputPointId( pts->GetId(i+2), input, newPts, outputPD );
-        newPolys->InsertNextCell( 3, outPts );
+        newPolys->InsertNextCell(3, outPts->GetPointer(i));
         this->RecordOrigCellId(this->NumberOfNewCells, cellId);
         outputCD->CopyData(cd, cellId, this->NumberOfNewCells++);
         }
@@ -1326,6 +1513,10 @@
   cell->Delete();
   coords->Delete();
   pts->Delete();
+  parametricCoords->Delete();
+  parametricCoords2->Delete();
+  outPts->Delete();
+  outPts2->Delete();
 
   output->SetPoints(newPts);
   newPts->Delete();
@@ -1387,6 +1578,7 @@
     this->QuadHash[i] = NULL;
     this->PointMap[i] = -1;
     }
+  this->EdgeMap = new vtkEdgeInterpolationMap;
 }
 
 //----------------------------------------------------------------------------
@@ -1406,6 +1598,8 @@
   this->QuadHashLength = 0;
   delete [] this->PointMap;
   this->PointMap = NULL;
+  delete this->EdgeMap;
+  this->EdgeMap = NULL;
 }
 
 //----------------------------------------------------------------------------
@@ -1800,6 +1994,34 @@
   return outPtId;
 }
 
+//-----------------------------------------------------------------------------
+vtkIdType vtkDataSetSurfaceFilter::GetInterpolatedPointId(vtkIdType edgePtA,
+                                                          vtkIdType edgePtB,
+                                                          vtkDataSet *input,
+                                                          vtkCell *cell,
+                                                          double pcoords[3],
+                                                          vtkPoints *outPts,
+                                                          vtkPointData *outPD)
+{
+  vtkIdType outPtId;
+
+  outPtId = this->EdgeMap->FindEdge(edgePtA, edgePtB);
+  if (outPtId == -1)
+    {
+    int subId = -1;
+    double wcoords[3];
+    double weights[100];  // Any reason to need more?
+    cell->EvaluateLocation(subId, pcoords, wcoords, weights);
+    outPtId = outPts->InsertNextPoint(wcoords);
+    outPD->InterpolatePoint(input->GetPointData(), outPtId,
+                            cell->GetPointIds(), weights);
+    this->RecordOrigPointId(outPtId, -1);
+    this->EdgeMap->AddEdge(edgePtA, edgePtB, outPtId);
+    }
+
+  return outPtId;
+}
+
 //----------------------------------------------------------------------------
 void vtkDataSetSurfaceFilter::RecordOrigCellId(vtkIdType destIndex, 
                                                vtkIdType originalId)
Index: VTK/Graphics/vtkDataSetSurfaceFilter.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Graphics/vtkDataSetSurfaceFilter.h,v
retrieving revision 1.26
diff -u -r1.26 vtkDataSetSurfaceFilter.h
--- VTK/Graphics/vtkDataSetSurfaceFilter.h	25 Mar 2009 14:35:54 -0000	1.26
+++ VTK/Graphics/vtkDataSetSurfaceFilter.h	10 Jun 2009 19:41:00 -0000
@@ -80,6 +80,19 @@
   vtkGetMacro(PassThroughPointIds,int);
   vtkBooleanMacro(PassThroughPointIds,int);
 
+  // Description:
+  // If the input is an unstructured grid with nonlinear faces, this parameter
+  // determines how many times the face is subdivided into linear faces.  If 0,
+  // the output is the equivalent of its linear couterpart (and the midpoints
+  // determining the nonlinear interpolation are discarded).  If 1 (the
+  // default), the nonlinear face is triangulated based on the midpoints.  If
+  // greater than 1, the triangulated pieces are recursively subdivided to reach
+  // the desired subdivision.  Setting the value to greater than 1 may cause
+  // some point data to not be passed even if no nonlinear faces exist.  This
+  // option has no effect if the input is not an unstructured grid.
+  vtkSetMacro(NonlinearSubdivisionLevel, int);
+  vtkGetMacro(NonlinearSubdivisionLevel, int);
+
 protected:
   vtkDataSetSurfaceFilter();
   ~vtkDataSetSurfaceFilter();
@@ -124,6 +137,14 @@
   vtkIdType *PointMap;
   vtkIdType GetOutputPointId(vtkIdType inPtId, vtkDataSet *input, 
                              vtkPoints *outPts, vtkPointData *outPD);
+//BTX
+  class vtkEdgeInterpolationMap;
+//ETX
+  vtkEdgeInterpolationMap *EdgeMap;
+  vtkIdType GetInterpolatedPointId(vtkIdType edgePtA, vtkIdType edgePtB,
+                                   vtkDataSet *input, vtkCell *cell,
+                                   double pcoords[3], vtkPoints *outPts,
+                                   vtkPointData *outPD);
   
   vtkIdType NumberOfNewCells;
   
@@ -149,6 +170,8 @@
   void RecordOrigPointId(vtkIdType newIndex, vtkIdType origId);
   vtkIdTypeArray *OriginalPointIds;
 
+  int NonlinearSubdivisionLevel;
+
 private:
   vtkDataSetSurfaceFilter(const vtkDataSetSurfaceFilter&);  // Not implemented.
   void operator=(const vtkDataSetSurfaceFilter&);  // Not implemented.
