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	12 Jun 2009 20:06:32 -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	12 Jun 2009 20:06:32 -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/CMakeLists.txt
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/Filters/CMakeLists.txt,v
retrieving revision 1.195
diff -u -r1.195 CMakeLists.txt
--- Servers/Filters/CMakeLists.txt	28 May 2009 19:02:11 -0000	1.195
+++ Servers/Filters/CMakeLists.txt	12 Jun 2009 20:06:32 -0000
@@ -98,6 +98,7 @@
   vtkPVMain.cxx
   vtkPVMergeTables.cxx
   vtkPVNullSource.cxx
+  vtkPVRecoverGeometryWireframe.cxx
   vtkPVRenderViewProxy.cxx
   vtkPVScalarBarActor.cxx
   vtkPVSelectionSource.cxx
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	12 Jun 2009 20:06:32 -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"
@@ -42,6 +43,7 @@
 #include "vtkPointData.h"
 #include "vtkPolyData.h"
 #include "vtkPolygon.h"
+#include "vtkPVRecoverGeometryWireframe.h"
 #include "vtkPVTrivialProducer.h"
 #include "vtkRectilinearGrid.h"
 #include "vtkRectilinearGridOutlineFilter.h"
@@ -53,11 +55,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 +130,13 @@
   this->UseOutline = 1;
   this->UseStrips = 0;
   this->GenerateCellNormals = 1;
+  this->NonlinearSubdivisionLevel = 1;
 
   this->DataSetSurfaceFilter = vtkDataSetSurfaceFilter::New();
   this->GenericGeometryFilter=vtkGenericGeometryFilter::New();
-  
+  this->UnstructuredGridGeometryFilter=vtkUnstructuredGridGeometryFilter::New();
+  this->RecoverWireframeFilter = vtkPVRecoverGeometryWireframe::New();
+
   // Setup a callback for the internal readers to report progress.
   this->InternalProgressObserver = vtkCallbackCommand::New();
   this->InternalProgressObserver->SetCallback(
@@ -154,13 +163,31 @@
 //----------------------------------------------------------------------------
 vtkPVGeometryFilter::~vtkPVGeometryFilter ()
 {
-  if(this->DataSetSurfaceFilter)
+  // Be careful how you delete these so that you don't foul up the garbage
+  // collector.
+  if (this->DataSetSurfaceFilter)
+    {
+    vtkDataSetSurfaceFilter *tmp = this->DataSetSurfaceFilter;
+    this->DataSetSurfaceFilter = NULL;
+    tmp->Delete();
+    }
+  if (this->GenericGeometryFilter)
     {
-    this->DataSetSurfaceFilter->Delete();
+    vtkGenericGeometryFilter *tmp = this->GenericGeometryFilter;
+    this->GenericGeometryFilter = NULL;
+    tmp->Delete();
     }
-  if(this->GenericGeometryFilter!=0)
+  if (this->UnstructuredGridGeometryFilter)
     {
-    this->GenericGeometryFilter->Delete();
+    vtkUnstructuredGridGeometryFilter *tmp=this->UnstructuredGridGeometryFilter;
+    this->UnstructuredGridGeometryFilter = NULL;
+    tmp->Delete();
+    }
+  if (this->RecoverWireframeFilter)
+    {
+    vtkPVRecoverGeometryWireframe *tmp = this->RecoverWireframeFilter;
+    this->RecoverWireframeFilter = NULL;
+    tmp->Delete();
     }
   this->OutlineSource->Delete();
   this->InternalProgressObserver->Delete();
@@ -1009,7 +1036,93 @@
   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 in vtkPVRecoverGeometryWireframe.  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());
+
+      // Flag the data set surface filter to record original cell ids, but do it
+      // in a specially named array that vtkPVRecoverGeometryWireframe will
+      // recognize.  Note that because the data set comes from
+      // UnstructuredGridGeometryFilter, the ids will represent the faces rather
+      // than the original cells, which is important.
+      this->DataSetSurfaceFilter->PassThroughCellIdsOn();
+      this->DataSetSurfaceFilter->SetOriginalCellIdsName(
+                            vtkPVRecoverGeometryWireframe::ORIGINAL_FACE_IDS());
+      }
+
     this->DataSetSurfaceExecute(input, output);
+
+    if (handleSubdivision)
+      {
+      // Restore state of DataSetSurfaceFilter.
+      this->DataSetSurfaceFilter->SetPassThroughCellIds(
+                                                      this->PassThroughCellIds);
+      this->DataSetSurfaceFilter->SetOriginalCellIdsName(NULL);
+
+      // Now use vtkPVRecoverGeometryWireframe to create an edge flag attribute
+      // that will cause the wireframe to be rendered correctly.
+      VTK_CREATE(vtkPolyData, nextStageInput);
+      nextStageInput->ShallowCopy(output);  // Yes output is correct.
+      this->RecoverWireframeFilter->SetInput(nextStageInput);
+
+      // 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->RecoverWireframeFilter->AddObserver(
+                                                vtkCommand::ProgressEvent,
+                                                this->InternalProgressObserver);
+      this->RecoverWireframeFilter->Update();
+      // The internal filter finished.  Remove the observer.
+      this->RecoverWireframeFilter->RemoveObserver(
+                                                this->InternalProgressObserver);
+
+      this->RecoverWireframeFilter->SetInput(NULL);
+
+      // Get what should be the final output.
+      output->ShallowCopy(this->RecoverWireframeFilter->GetOutput());
+      }
+
     return;
     }
   
@@ -1132,6 +1245,10 @@
                             "DataSetSurfaceFilter");
   vtkGarbageCollectorReport(collector, this->GenericGeometryFilter,
                             "GenericGeometryFilter");
+  vtkGarbageCollectorReport(collector, this->UnstructuredGridGeometryFilter,
+                            "UnstructuredGridGeometryFilter");
+  vtkGarbageCollectorReport(collector, this->RecoverWireframeFilter,
+                            "RecoverWireframeFilter");
 }
 
 //----------------------------------------------------------------------------
@@ -1152,6 +1269,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 +1354,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	12 Jun 2009 20:06:32 -0000
@@ -35,9 +35,11 @@
 class vtkCompositeDataSet;
 class vtkMultiProcessController;
 class vtkOutlineSource;
+class vtkPVRecoverGeometryWireframe;
 class vtkRectilinearGrid;
 class vtkStructuredGrid;
 class vtkUnstructuredGrid;
+class vtkUnstructuredGridGeometryFilter;
 
 class VTK_EXPORT vtkPVGeometryFilter : public vtkPolyDataAlgorithm
 {
@@ -80,6 +82,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 +162,14 @@
   int UseOutline;
   int UseStrips;
   int GenerateCellNormals;
+  int NonlinearSubdivisionLevel;
 
   vtkMultiProcessController* Controller;
   vtkOutlineSource *OutlineSource;
   vtkDataSetSurfaceFilter* DataSetSurfaceFilter;
   vtkGenericGeometryFilter *GenericGeometryFilter;
+  vtkUnstructuredGridGeometryFilter *UnstructuredGridGeometryFilter;
+  vtkPVRecoverGeometryWireframe *RecoverWireframeFilter;
   
   int CheckAttributes(vtkDataObject* input);
 
Index: Servers/Filters/vtkPVRecoverGeometryWireframe.cxx
===================================================================
RCS file: Servers/Filters/vtkPVRecoverGeometryWireframe.cxx
diff -N Servers/Filters/vtkPVRecoverGeometryWireframe.cxx
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Servers/Filters/vtkPVRecoverGeometryWireframe.cxx	12 Jun 2009 20:06:32 -0000
@@ -0,0 +1,308 @@
+// -*- c++ -*-
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: pqBlotDialog.h,v $
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Copyright 2009 Sandia Corporation.
+  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+  the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------*/
+
+#include "vtkPVRecoverGeometryWireframe.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkIdTypeArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkUnsignedCharArray.h"
+
+#include "vtkSmartPointer.h"
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
+#include <vtkstd/algorithm>
+#include <vtkstd/vector>
+#include <vtksys/hash_map.hxx>
+
+static const unsigned char NO_EDGE_FLAG = static_cast<unsigned char >(-1);
+
+//=============================================================================
+namespace vtkPVRecoverGeometryWireframeNamespace
+{
+  // Description:
+  // Simple class used internally to define an edge based on the endpoints.  The
+  // endpoints are canonically identified by the lower and higher values.
+  class EdgeEndpoints
+  {
+  public:
+    EdgeEndpoints() : MinEndPoint(-1), MaxEndPoint(-1) {}
+    EdgeEndpoints(vtkIdType endpointA, vtkIdType endpointB)
+      : MinEndPoint((endpointA < endpointB) ? endpointA : endpointB),
+        MaxEndPoint((endpointA < endpointB) ? endpointB : endpointA)
+    {}
+    const vtkIdType MinEndPoint;
+    const vtkIdType MaxEndPoint;
+    inline bool operator==(const EdgeEndpoints &other) const {
+      return (   (this->MinEndPoint == other.MinEndPoint)
+              && (this->MaxEndPoint == other.MaxEndPoint) );
+    }
+  };
+  struct EdgeEndpointsHash {
+  public:
+    size_t operator()(const EdgeEndpoints &edge) const {
+      return static_cast<size_t>(edge.MinEndPoint + edge.MaxEndPoint);
+    }
+  };
+
+  // Description:
+  // Holds the information necessary for the facet this edge came from.
+  class EdgeInformation
+  {
+  public:
+    vtkIdType OriginalFaceId;
+    vtkIdType *StartPointIdP;
+  };
+
+  // Description:
+  // A map from edge endpoints to the information about that edge.
+  typedef vtksys::hash_map<EdgeEndpoints, EdgeInformation, EdgeEndpointsHash>
+    EdgeMapType;
+
+  void RecordEdgeFlag(vtkPolyData *output, const EdgeInformation &edgeInfo,
+                      vtkUnsignedCharArray *edgeFlagArray, unsigned char flag,
+                      vtkIdType *duplicatePointMap)
+  {
+    vtkIdType pt = edgeInfo.StartPointIdP[0];
+    if (edgeFlagArray->GetValue(pt) == flag)
+      {
+      // Edge flag already set correctly.  Nothing to do.
+      return;
+      }
+    if (edgeFlagArray->GetValue(pt) == NO_EDGE_FLAG)
+      {
+      // Nothing has set the edge flag yet.  Just set it and return.
+      edgeFlagArray->SetValue(pt, flag);
+      return;
+      }
+
+    // If we are here then some other cell has already put a flag on this
+    // point different than ours.  We have to adjust our cell topology to
+    // use a duplicate point.
+    if (duplicatePointMap[pt] == -1)
+      {
+      // No duplicate made.  We need to make one.
+      vtkPoints *points = output->GetPoints();
+      double coords[3];
+      points->GetPoint(pt, coords);
+      vtkIdType newPt = points->InsertNextPoint(coords);
+      duplicatePointMap[pt] = newPt;
+      // Copying attributes from yourself seems weird, but is valid.
+      vtkPointData *pd = output->GetPointData();
+      pd->CopyData(pd, pt, newPt);
+      edgeFlagArray->InsertValue(newPt, flag);
+      }
+    edgeInfo.StartPointIdP[0] = duplicatePointMap[pt];
+  }
+}
+using namespace vtkPVRecoverGeometryWireframeNamespace;
+
+//=============================================================================
+vtkCxxRevisionMacro(vtkPVRecoverGeometryWireframe, "$Revision$");
+vtkStandardNewMacro(vtkPVRecoverGeometryWireframe);
+
+//-----------------------------------------------------------------------------
+vtkPVRecoverGeometryWireframe::vtkPVRecoverGeometryWireframe()
+{
+}
+
+vtkPVRecoverGeometryWireframe::~vtkPVRecoverGeometryWireframe()
+{
+}
+
+void vtkPVRecoverGeometryWireframe::PrintSelf(ostream &os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+}
+
+//-----------------------------------------------------------------------------
+int vtkPVRecoverGeometryWireframe::RequestData(
+                                            vtkInformation *vtkNotUsed(request),
+                                            vtkInformationVector **inputVector,
+                                            vtkInformationVector *outputVector)
+{
+  vtkPolyData *input = vtkPolyData::GetData(inputVector[0]);
+  vtkPolyData *output = vtkPolyData::GetData(outputVector);
+
+  vtkIdType npts, *pts;
+  vtkstd::vector<vtkIdType> originalPts;
+
+  if (!input->GetCellData()->HasArray(ORIGINAL_FACE_IDS()))
+    {
+    // Did not find the field used to identify the face each linear patch comes
+    // from.  The original data was probably linear so using all the edges
+    // should be OK (and is at least the best we can do), so just pass the data.
+    output->ShallowCopy(input);
+    return 1;
+    }
+
+  vtkIdTypeArray *faceIds = vtkIdTypeArray::SafeDownCast(
+                   input->GetCellData()->GetAbstractArray(ORIGINAL_FACE_IDS()));
+  if (!faceIds)
+    {
+    vtkErrorMacro(<< ORIGINAL_FACE_IDS() << " array is not of expected type.");
+    return 0;
+    }
+
+  // Shallow copy the cell data.  All the cells get copied to output.
+  output->GetCellData()->PassData(input->GetCellData());
+
+  // Deep copy the point information and be ready to add points.
+  VTK_CREATE(vtkPoints, points);
+  points->DeepCopy(input->GetPoints());
+  output->SetPoints(points);
+  vtkPointData *inputPD = input->GetPointData();
+  vtkPointData *outputPD = output->GetPointData();
+  outputPD->CopyAllocate(inputPD);
+  vtkIdType numOriginalPoints = points->GetNumberOfPoints();
+  for (vtkIdType i = 0; i < numOriginalPoints; i++)
+    {
+    outputPD->CopyData(inputPD, i, i);
+    }
+
+  // Create an edge flag array.
+  VTK_CREATE(vtkUnsignedCharArray, edgeflags);
+  edgeflags->SetName("vtkEdgeFlags");
+  outputPD->AddArray(edgeflags);
+  outputPD->SetActiveAttribute("vtkEdgeFlags", vtkDataSetAttributes::EDGEFLAG);
+  edgeflags->SetNumberOfComponents(1);
+  edgeflags->SetNumberOfTuples(numOriginalPoints);
+  vtkstd::fill(edgeflags->GetPointer(0),
+               edgeflags->GetPointer(numOriginalPoints), NO_EDGE_FLAG);
+
+  // Some (probably many) points will have to be duplicated because different
+  // cells will need different edge flags.  This array maps the original
+  // point id to the duplicate id.
+  vtkstd::vector<vtkIdType> duplicatePointMap(numOriginalPoints);
+  vtkstd::fill(duplicatePointMap.begin(), duplicatePointMap.end(), -1);
+
+  // Shallow copy the verts.  Set the edge flags to true.
+  vtkCellArray *inputVerts = input->GetVerts();
+  output->SetVerts(inputVerts);
+  for (inputVerts->InitTraversal(); inputVerts->GetNextCell(npts, pts); )
+    {
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Shallow copy the lines. Set the edge flags to true.
+  vtkCellArray *inputLines = input->GetLines();
+  output->SetLines(inputLines);
+  for (inputLines->InitTraversal(); inputLines->GetNextCell(npts, pts); )
+    {
+    // No need to set edge flag for last index.
+    for (vtkIdType i = 0; i < npts-1; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Shallow copy the triangle strips.  Set the edge flags to true.
+  vtkCellArray *inputStrips = input->GetStrips();
+  output->SetStrips(inputStrips);
+  for (inputStrips->InitTraversal(); inputStrips->GetNextCell(npts, pts); )
+    {
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      edgeflags->SetValue(pts[i], 1);
+      }
+    }
+
+  // Deep copy the polygons because we will be changing some indices when we
+  // duplicate points.
+  VTK_CREATE(vtkCellArray, outputPolys);
+  outputPolys->DeepCopy(input->GetPolys());
+  output->SetPolys(outputPolys);
+
+  // Iterate over all the input facets and see which edge interfaces belonged to
+  // different faces.  We do that by recording the original face id in a map.
+  // When we find a pair of edges, we turn on the appropriate edge flag if they
+  // came from different faces, or turn it off if they came from the same face.
+  EdgeMapType edgeMap;
+  vtkIdType inputCellId
+    = inputVerts->GetNumberOfCells() + inputLines->GetNumberOfCells();
+  for (outputPolys->InitTraversal(); outputPolys->GetNextCell(npts, pts);
+       inputCellId++)
+    {
+    if ((inputCellId%1000) == 0)
+      {
+      this->UpdateProgress(static_cast<double>(inputCellId)
+                           /input->GetNumberOfCells());
+      if (this->GetAbortExecute()) return 0;
+      }
+    // Record the original points of the polygon.  As we iterate over edges,
+    // we may change the indices, but we allways compare edges by the original
+    // indices.
+    originalPts.resize(npts);
+    vtkstd::copy(pts, pts+npts, originalPts.begin());
+    vtkIdType originalFace = faceIds->GetValue(inputCellId);
+    for (vtkIdType i = 0; i < npts; i++)
+      {
+      EdgeEndpoints edge(originalPts[i], originalPts[(i+1)%npts]);
+      EdgeInformation edgeInfo;
+      edgeInfo.OriginalFaceId = originalFace;
+      edgeInfo.StartPointIdP = &pts[i];
+
+      EdgeMapType::iterator edgeMatch = edgeMap.find(edge);
+      if (edgeMatch == edgeMap.end())
+        {
+        // Not encountered yet.  Add to the map.
+        edgeMap.insert(vtkstd::make_pair(edge, edgeInfo));
+        }
+      else
+        {
+        // The edge flag is true if the edge connects two different faces.
+        unsigned char eflag = static_cast<unsigned char>(
+                              edgeMatch->second.OriginalFaceId != originalFace);
+        RecordEdgeFlag(output, edgeMatch->second, edgeflags, eflag,
+                       &duplicatePointMap.at(0));
+        RecordEdgeFlag(output, edgeInfo, edgeflags, eflag,
+                       &duplicatePointMap.at(0));
+        // Remove the edge from the map since we already found the pair.
+        edgeMap.erase(edgeMatch);
+        }
+      } // For each edge
+    } // For each cell.
+
+  // Everything left in the edge map has no match.  It must necessarily be
+  // on the outside of a face.
+  for (EdgeMapType::iterator iter = edgeMap.begin();
+       iter != edgeMap.end(); iter++)
+    {
+    RecordEdgeFlag(output, iter->second, edgeflags, 1,
+                   &duplicatePointMap.at(0));
+    }
+
+  // If any points are unmarked, set some edge flag on them (although they
+  // are probably not referenced by any cell).
+  for (vtkIdType i = 0; i < numOriginalPoints; i++)
+    {
+    if (edgeflags->GetValue(i) == NO_EDGE_FLAG) edgeflags->SetValue(i, 1);
+    }
+
+  return 1;
+}
Index: Servers/Filters/vtkPVRecoverGeometryWireframe.h
===================================================================
RCS file: Servers/Filters/vtkPVRecoverGeometryWireframe.h
diff -N Servers/Filters/vtkPVRecoverGeometryWireframe.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Servers/Filters/vtkPVRecoverGeometryWireframe.h	12 Jun 2009 20:06:32 -0000
@@ -0,0 +1,73 @@
+// -*- c++ -*-
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: pqBlotDialog.h,v $
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Copyright 2009 Sandia Corporation.
+  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+  the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------*/
+
+// .NAME vtkPVRecoverGeometryWireframe - Get corrected wireframe from tesselated facets
+//
+// .SECTION Description
+//
+// When vtkPVGeometryFilter tessellates nonlinear faces into linear
+// approximations, it introduces edges in the middle of the facets of the
+// original mesh (as any valid tessellation would).  To correct for this,
+// vtkPVGeometryFilter also writes out some fields that allows use to identify
+// the edges that are actually part of the original mesh.  This filter works in
+// conjunction with vtkPVGeometryFilter by taking its output, adding an edge
+// flag and making the appropriate adjustments so that rendering with line
+// fill mode will make the correct wireframe.
+//
+// .SECTION See Also
+// vtkPVGeometryFilter
+//
+
+#ifndef __vtkPVRecoverGeometryWireframe_h
+#define __vtkPVRecoverGeometryWireframe_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+class VTK_EXPORT vtkPVRecoverGeometryWireframe : public vtkPolyDataAlgorithm
+{
+public:
+  vtkTypeRevisionMacro(vtkPVRecoverGeometryWireframe, vtkPolyDataAlgorithm);
+  static vtkPVRecoverGeometryWireframe *New();
+  virtual void PrintSelf(ostream &os, vtkIndent indent);
+
+  // Description:
+  // In order to determine which edges existed in the original data, we need an
+  // identifier on each cell determining which face (not cell) it originally
+  // came from.  The ids should be put in a cell data array with this name.  The
+  // existance of this field is also a signal that this wireframe extraction is
+  // necessary.
+  static const char *ORIGINAL_FACE_IDS()
+    { return "vtkPVRecoverWireframeOriginalFaceIds"; }
+
+protected:
+  vtkPVRecoverGeometryWireframe();
+  ~vtkPVRecoverGeometryWireframe();
+
+  virtual int RequestData(vtkInformation *request,
+                          vtkInformationVector **inputVector,
+                          vtkInformationVector *outputVector);
+
+private:
+  vtkPVRecoverGeometryWireframe(const vtkPVRecoverGeometryWireframe &); // Not implemented
+  void operator=(const vtkPVRecoverGeometryWireframe &); // Not implemented
+};
+
+#endif //__vtkPVRecoverGeometryWireframe_h
Index: Servers/ServerManager/Resources/filters.xml
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/Servers/ServerManager/Resources/filters.xml,v
retrieving revision 1.353
diff -u -r1.353 filters.xml
--- Servers/ServerManager/Resources/filters.xml	12 Jun 2009 14:19:58 -0000	1.353
+++ Servers/ServerManager/Resources/filters.xml	12 Jun 2009 20:06:32 -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	12 Jun 2009 20:06:32 -0000
@@ -5861,7 +5861,7 @@
 
       <SubProxy>
         <!-- 
-          Geometry filter is used to conver non-polydata input to polydata.
+          Geometry filter is used to convert non-polydata input to polydata.
           It is also used to convert poly data to triangle strips when
           requested.
         -->
@@ -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	12 Jun 2009 20:06:32 -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	12 Jun 2009 20:06:32 -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/Filtering/vtkDataSetAttributes.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Filtering/vtkDataSetAttributes.cxx,v
retrieving revision 1.30
diff -u -r1.30 vtkDataSetAttributes.cxx
--- VTK/Filtering/vtkDataSetAttributes.cxx	9 Oct 2008 16:27:50 -0000	1.30
+++ VTK/Filtering/vtkDataSetAttributes.cxx	12 Jun 2009 20:06:32 -0000
@@ -43,7 +43,9 @@
   "TCoords",
   "Tensors",
   "GlobalIds",
-  "PedigreeIds" };
+  "PedigreeIds",
+  "EdgeFlag"
+};
 
 const char vtkDataSetAttributes
 ::LongAttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][35] =
@@ -53,7 +55,9 @@
   "vtkDataSetAttributes::TCOORDS",
   "vtkDataSetAttributes::TENSORS",
   "vtkDataSetAttributes::GLOBALIDS",
-  "vtkDataSetAttributes::PEDIGREEIDS" };
+  "vtkDataSetAttributes::PEDIGREEIDS",
+  "vtkDataSetAttributes::EDGEFLAG"
+};
 
 //--------------------------------------------------------------------------
 // Construct object with copying turned on for all data.
@@ -1064,6 +1068,7 @@
   3,
   9,
   1,
+  1,
   1};
 
 //--------------------------------------------------------------------------
@@ -1076,6 +1081,7 @@
   MAX,
   EXACT,
   EXACT,
+  EXACT,
   EXACT};
 
 //--------------------------------------------------------------------------
Index: VTK/Filtering/vtkDataSetAttributes.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Filtering/vtkDataSetAttributes.h,v
retrieving revision 1.13
diff -u -r1.13 vtkDataSetAttributes.h
--- VTK/Filtering/vtkDataSetAttributes.h	11 Jun 2009 19:16:48 -0000	1.13
+++ VTK/Filtering/vtkDataSetAttributes.h	12 Jun 2009 20:06:32 -0000
@@ -90,6 +90,7 @@
     TENSORS=4,
     GLOBALIDS=5,
     PEDIGREEIDS=6,
+    EDGEFLAG=7,
     NUM_ATTRIBUTES
   };
 
@@ -165,6 +166,7 @@
   //  vtkDataSetAttributes::TENSORS = 4
   //  vtkDataSetAttributes::GLOBALIDS = 5
   //  vtkDataSetAttributes::PEDIGREEIDS = 6
+  //  vtkDataSetAttributes::EDGEFLAG = 7
   // Returns the index of the array if succesful, -1 if the array 
   // is not in the list of arrays.
   int SetActiveAttribute(const char* name, int attributeType);
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	12 Jun 2009 20:06:32 -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,10 @@
   this->PassThroughPointIds = 0;
   this->OriginalCellIds = NULL;
   this->OriginalPointIds = NULL;
+  this->OriginalCellIdsName = NULL;
+  this->OriginalPointIdsName = NULL;
+
+  this->NonlinearSubdivisionLevel = 1;
 }
 
 //----------------------------------------------------------------------------
@@ -179,7 +220,7 @@
         {
         //make a 1:1 mapping
         this->OriginalCellIds = vtkIdTypeArray::New();
-        this->OriginalCellIds->SetName("vtkOriginalCellIds");
+        this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
         this->OriginalCellIds->SetNumberOfComponents(1);
         vtkCellData *outputCD = output->GetCellData();
         outputCD->AddArray(this->OriginalCellIds);        
@@ -196,7 +237,7 @@
         {
         //make a 1:1 mapping
         this->OriginalPointIds = vtkIdTypeArray::New();
-        this->OriginalPointIds->SetName("vtkOriginalPointIds");
+        this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
         this->OriginalPointIds->SetNumberOfComponents(1);
         vtkPointData *outputPD = output->GetPointData();
         outputPD->AddArray(this->OriginalPointIds);        
@@ -348,14 +389,14 @@
   if (this->PassThroughCellIds)
     {
     this->OriginalCellIds = vtkIdTypeArray::New();
-    this->OriginalCellIds->SetName("vtkOriginalCellIds");
+    this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
     this->OriginalCellIds->SetNumberOfComponents(1);
     output->GetCellData()->AddArray(this->OriginalCellIds);
     }
   if (this->PassThroughPointIds)
     {
     this->OriginalPointIds = vtkIdTypeArray::New();
-    this->OriginalPointIds->SetName("vtkOriginalPointIds");
+    this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
     this->OriginalPointIds->SetNumberOfComponents(1);
     output->GetPointData()->AddArray(this->OriginalPointIds);
     }
@@ -916,6 +957,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 +992,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 +1000,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,21 +1031,28 @@
   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);
 
   if (this->PassThroughCellIds)
     {
     this->OriginalCellIds = vtkIdTypeArray::New();
-    this->OriginalCellIds->SetName("vtkOriginalCellIds");
+    this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
     this->OriginalCellIds->SetNumberOfComponents(1);
     }
   if (this->PassThroughPointIds)
     {
     this->OriginalPointIds = vtkIdTypeArray::New();
-    this->OriginalPointIds->SetName("vtkOriginalPointIds");
+    this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
     this->OriginalPointIds->SetNumberOfComponents(1);
     }
 
@@ -1201,14 +1260,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 +1317,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 +1387,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 +1515,10 @@
   cell->Delete();
   coords->Delete();
   pts->Delete();
+  parametricCoords->Delete();
+  parametricCoords2->Delete();
+  outPts->Delete();
+  outPts2->Delete();
 
   output->SetPoints(newPts);
   newPts->Delete();
@@ -1387,6 +1580,7 @@
     this->QuadHash[i] = NULL;
     this->PointMap[i] = -1;
     }
+  this->EdgeMap = new vtkEdgeInterpolationMap;
 }
 
 //----------------------------------------------------------------------------
@@ -1406,6 +1600,8 @@
   this->QuadHashLength = 0;
   delete [] this->PointMap;
   this->PointMap = NULL;
+  delete this->EdgeMap;
+  this->EdgeMap = NULL;
 }
 
 //----------------------------------------------------------------------------
@@ -1800,6 +1996,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	12 Jun 2009 20:06:32 -0000
@@ -80,6 +80,35 @@
   vtkGetMacro(PassThroughPointIds,int);
   vtkBooleanMacro(PassThroughPointIds,int);
 
+  // Description:
+  // If PassThroughCellIds or PassThroughPointIds is on, then these ivars
+  // control the name given to the field in which the ids are written into.  If
+  // set to NULL, then vtkOriginalCellIds or vtkOriginalPointIds (the default)
+  // is used, respectively.
+  vtkSetStringMacro(OriginalCellIdsName);
+  virtual const char *GetOriginalCellIdsName() {
+    return (  this->OriginalCellIdsName
+            ? this->OriginalCellIdsName : "vtkOriginalCellIds");
+  }
+  vtkSetStringMacro(OriginalPointIdsName);
+  virtual const char *GetOriginalPointIdsName() {
+    return (  this->OriginalPointIdsName
+            ? this->OriginalPointIdsName : "vtkOriginalPointIds");
+  }
+
+  // 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 +153,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;
   
@@ -144,10 +181,14 @@
   int PassThroughCellIds;
   void RecordOrigCellId(vtkIdType newIndex, vtkIdType origId);
   vtkIdTypeArray *OriginalCellIds;
+  char *OriginalCellIdsName;
 
   int PassThroughPointIds;
   void RecordOrigPointId(vtkIdType newIndex, vtkIdType origId);
   vtkIdTypeArray *OriginalPointIds;
+  char *OriginalPointIdsName;
+
+  int NonlinearSubdivisionLevel;
 
 private:
   vtkDataSetSurfaceFilter(const vtkDataSetSurfaceFilter&);  // Not implemented.
Index: VTK/Rendering/vtkLinesPainter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkLinesPainter.cxx,v
retrieving revision 1.6
diff -u -r1.6 vtkLinesPainter.cxx
--- VTK/Rendering/vtkLinesPainter.cxx	18 Jul 2008 19:12:16 -0000	1.6
+++ VTK/Rendering/vtkLinesPainter.cxx	12 Jun 2009 20:06:33 -0000
@@ -131,6 +131,9 @@
   // we just ignore the flag.
   idx &= (~VTK_PDM_FIELD_COLORS);
 
+  // Also ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   // draw all the elements, use fast path if available
   switch (idx)
     {
Index: VTK/Rendering/vtkOpenGLPainterDeviceAdapter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkOpenGLPainterDeviceAdapter.cxx,v
retrieving revision 1.27
diff -u -r1.27 vtkOpenGLPainterDeviceAdapter.cxx
--- VTK/Rendering/vtkOpenGLPainterDeviceAdapter.cxx	15 Jan 2009 15:54:21 -0000	1.27
+++ VTK/Rendering/vtkOpenGLPainterDeviceAdapter.cxx	12 Jun 2009 20:06:33 -0000
@@ -259,6 +259,7 @@
   case vtkDataSetAttributes::NORMALS:
   case vtkDataSetAttributes::SCALARS:
   case vtkDataSetAttributes::TCOORDS:
+  case vtkDataSetAttributes::EDGEFLAG:
     return 1;
     }
   return 0;
@@ -534,6 +535,18 @@
           return;
         }
       break;
+    case vtkDataSetAttributes::EDGEFLAG:        // Edge Flag
+      if (numcomp != 1)
+        {
+        vtkErrorMacro("Bad number of components.");
+        return;
+        }
+       switch (type)
+        {
+        vtkTemplateMacro(glEdgeFlag(static_cast<GLboolean>(
+                          reinterpret_cast<const VTK_TT*>(attribute)[offset])));
+        }
+      break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -715,6 +728,33 @@
         }
       glTexCoordPointer(numcomponents, gltype, stride, pointer);
       break;
+    case vtkDataSetAttributes::EDGEFLAG:        // Edge flag
+      if (numcomponents != 1)
+        {
+        vtkErrorMacro("Edge flag must have one component.");
+        return;
+        }
+      // Flag must be conformant to GLboolean
+      if ((type == VTK_FLOAT) || (type == GL_DOUBLE))
+        {
+        vtkErrorMacro("Unsupported type for edge flag: " << type);
+        return;
+        }
+      // Thus is an unfriendly way to force the array to be conformant to
+      // a GLboolean array.  At the very least there should be some indication
+      // in VTK outside of OpenGL to determine which VTK type to use.
+      switch (type)
+        {
+        vtkTemplateMacro(if (sizeof(VTK_TT) != sizeof(GLboolean))
+                           {
+                           vtkErrorMacro(<< "Unsupported tyep for edge flag: "
+                                         << type);
+                           return;
+                           }
+                         );
+        }
+      glEdgeFlagPointer(stride, pointer);
+      break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -735,6 +775,8 @@
       glEnableClientState(GL_COLOR_ARRAY);  break;
   case vtkDataSetAttributes::TCOORDS:
       glEnableClientState(GL_TEXTURE_COORD_ARRAY);  break;
+  case vtkDataSetAttributes::EDGEFLAG:
+      glEnableClientState(GL_EDGE_FLAG_ARRAY);  break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -753,6 +795,8 @@
       glDisableClientState(GL_COLOR_ARRAY);  break;
   case vtkDataSetAttributes::TCOORDS:
       glDisableClientState(GL_TEXTURE_COORD_ARRAY);  break;
+  case vtkDataSetAttributes::EDGEFLAG:
+      glDisableClientState(GL_EDGE_FLAG_ARRAY);  break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
Index: VTK/Rendering/vtkPointsPainter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkPointsPainter.cxx,v
retrieving revision 1.4
diff -u -r1.4 vtkPointsPainter.cxx
--- VTK/Rendering/vtkPointsPainter.cxx	23 Feb 2008 17:18:46 -0000	1.4
+++ VTK/Rendering/vtkPointsPainter.cxx	12 Jun 2009 20:06:33 -0000
@@ -107,6 +107,10 @@
   // since this painter does not deal with field colors specially,
   // we just ignore the flag.
   idx &= (~VTK_PDM_FIELD_COLORS);
+
+  // Also ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   switch (idx)
     {
   case 0://no cell/point attribs are present. 
Index: VTK/Rendering/vtkPolygonsPainter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkPolygonsPainter.cxx,v
retrieving revision 1.4
diff -u -r1.4 vtkPolygonsPainter.cxx
--- VTK/Rendering/vtkPolygonsPainter.cxx	23 Feb 2008 17:18:46 -0000	1.4
+++ VTK/Rendering/vtkPolygonsPainter.cxx	12 Jun 2009 20:06:33 -0000
@@ -181,6 +181,8 @@
     pd->GetLines()->GetNumberOfCells();
   vtkIdType cellNumStart = cellNum;
   vtkIdType totalCells = ca->GetNumberOfCells();
+  vtkUnsignedCharArray *ef = vtkUnsignedCharArray::SafeDownCast(
+              pd->GetPointData()->GetAttribute(vtkDataSetAttributes::EDGEFLAG));
   
   vtkPainterDeviceAdapter* device = ren->GetRenderWindow()->
     GetPainterDeviceAdapter();
@@ -188,6 +190,7 @@
   void *normals = 0;
   void *tcoords = 0;
   unsigned char *colors = 0;
+  unsigned char *edgeflags = 0;
   int primitive = VTK_POLYGON;
 
   if (ca->GetNumberOfCells() == 0)
@@ -211,12 +214,17 @@
     {
     tcoords = t->GetVoidPointer(0);
     }
+  if (ef)
+    {
+    edgeflags = ef->GetPointer(0);
+    }
   vtkIdType *ptIds = ca->GetPointer();
   vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries();
   int ptype = p->GetDataType();
   int ntype = (n)? n->GetDataType() : 0;
   int ttype = (t)? t->GetDataType() : 0;
   int tcomps = (t)? t->GetNumberOfComponents() : 0;
+  int eftype = (ef)? ef->GetDataType() : 0;
   int celloffset = 0;
   
   // since this painter does not deal with field colors specially,
@@ -412,9 +420,266 @@
           VTK_UNSIGNED_CHAR, colors); colors += 4;,
         celloffset = cellNum;);
       break;
+
+    case VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);, ;,;);
+        }
+      break;
+
+    case VTK_PDM_NORMALS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+
+    case VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 4,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 4,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive, 
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 3,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive, 
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 3,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                              ttype, tcoords, tcomps**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                              ttype, tcoords, tcomps**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive, 
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                                ttype, tcoords, tcomps**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive, 
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::TCOORDS, 1,
+                                                ttype, tcoords, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;, 
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive, 
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,
+                        celloffset = cellNum;);
+      break;
+
     default:
       return 0; // let the delegate painter handle it.
     }
+
+  if (idx & VTK_PDM_EDGEFLAGS)
+    {
+    // Reset the edge flag to 1 so that if the next thing rendered does not
+    // have an edge flag, it will have all edges on.
+    unsigned char edgeflag = 1;
+    device->SendAttribute(vtkPointData::EDGEFLAG, 1, VTK_UNSIGNED_CHAR,
+                          &edgeflag, 0);
+    }
+
   return 1;
 }
 
Index: VTK/Rendering/vtkPrimitivePainter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkPrimitivePainter.cxx,v
retrieving revision 1.11
diff -u -r1.11 vtkPrimitivePainter.cxx
--- VTK/Rendering/vtkPrimitivePainter.cxx	8 Dec 2008 19:28:35 -0000	1.11
+++ VTK/Rendering/vtkPrimitivePainter.cxx	12 Jun 2009 20:06:33 -0000
@@ -159,6 +159,7 @@
   vtkUnsignedCharArray *c=NULL;
   vtkDataArray *n;
   vtkDataArray *t;
+  vtkDataArray *ef;
   int tDim;
   vtkPolyData *input = this->GetInputAsPolyData();
   int cellNormals;
@@ -269,6 +270,28 @@
     idx |= VTK_PDM_TCOORDS;
     }
 
+  // Edge flag
+  ef = input->GetPointData()->GetAttribute(vtkDataSetAttributes::EDGEFLAG);
+  if (ef)
+    {
+    if (ef->GetNumberOfComponents() != 1)
+      {
+      vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
+      ef = NULL;
+      }
+    if (!ef->IsA("vtkUnsignedCharArray"))
+      {
+      vtkDebugMacro(<< "Currently only unsigned char edge flags are suported.");
+      ef = NULL;
+      }
+    }
+
+  // Set the flags
+  if (ef)
+    {
+    idx |= VTK_PDM_EDGEFLAGS;
+    }
+
   if (!act)
     {
     vtkErrorMacro("No actor");
Index: VTK/Rendering/vtkPrimitivePainter.h
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkPrimitivePainter.h,v
retrieving revision 1.9
diff -u -r1.9 vtkPrimitivePainter.h
--- VTK/Rendering/vtkPrimitivePainter.h	28 Jul 2008 17:08:42 -0000	1.9
+++ VTK/Rendering/vtkPrimitivePainter.h	12 Jun 2009 20:06:33 -0000
@@ -49,14 +49,15 @@
 
   //BTX
   enum {
-    VTK_PDM_NORMALS = 0x01,
-    VTK_PDM_COLORS = 0x02,
-    VTK_PDM_TCOORDS = 0x04,
-    VTK_PDM_CELL_COLORS = 0x08,
-    VTK_PDM_CELL_NORMALS = 0x10,
-    VTK_PDM_OPAQUE_COLORS = 0x20,
-    VTK_PDM_FIELD_COLORS = 0x40,
-    VTK_PDM_GENERIC_VERTEX_ATTRIBUTES =0x80
+    VTK_PDM_NORMALS = 0x001,
+    VTK_PDM_COLORS = 0x002,
+    VTK_PDM_TCOORDS = 0x004,
+    VTK_PDM_CELL_COLORS = 0x008,
+    VTK_PDM_CELL_NORMALS = 0x010,
+    VTK_PDM_OPAQUE_COLORS = 0x020,
+    VTK_PDM_FIELD_COLORS = 0x040,
+    VTK_PDM_EDGEFLAGS = 0x080,
+    VTK_PDM_GENERIC_VERTEX_ATTRIBUTES = 0x100
   };
   //ETX
 
Index: VTK/Rendering/vtkTStripsPainter.cxx
===================================================================
RCS file: /cvsroot/ParaView3/ParaView3/VTK/Rendering/vtkTStripsPainter.cxx,v
retrieving revision 1.5
diff -u -r1.5 vtkTStripsPainter.cxx
--- VTK/Rendering/vtkTStripsPainter.cxx	23 Feb 2008 17:18:46 -0000	1.5
+++ VTK/Rendering/vtkTStripsPainter.cxx	12 Jun 2009 20:06:33 -0000
@@ -189,6 +189,9 @@
   int ttype = (t)? t->GetDataType() : 0;
   int tcomps = (t)? t->GetNumberOfComponents() : 0;
 
+  // Ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   // draw all the elements, use fast path if available
   switch (idx)
     {
