source: trunk/packages/vizservers/vtkvis/PolyData.cpp @ 3774

Last change on this file since 3774 was 3774, checked in by ldelgass, 11 years ago

Generate normals for polydata if none are supplied. Add Image/Text3D to
Makefile

  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2012  HUBzero Foundation, LLC
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cassert>
9
10#include <vtkDataSet.h>
11#include <vtkPolyData.h>
12#include <vtkPolyDataNormals.h>
13#include <vtkPointData.h>
14#include <vtkCellData.h>
15#include <vtkUnstructuredGrid.h>
16#include <vtkPolyDataMapper.h>
17#include <vtkActor.h>
18#include <vtkProperty.h>
19#include <vtkTransform.h>
20#include <vtkDelaunay2D.h>
21#include <vtkDelaunay3D.h>
22#include <vtkDataSetSurfaceFilter.h>
23#include <vtkVertexGlyphFilter.h>
24
25#include "PolyData.h"
26#include "Trace.h"
27
28using namespace VtkVis;
29
30PolyData::PolyData() :
31    GraphicsObject(),
32    _cloudStyle(CLOUD_MESH)
33{
34}
35
36PolyData::~PolyData()
37{
38#ifdef WANT_TRACE
39    if (_dataSet != NULL)
40        TRACE("Deleting PolyData for %s", _dataSet->getName().c_str());
41    else
42        TRACE("Deleting PolyData with NULL DataSet");
43#endif
44}
45
46/**
47 * \brief Internal method to set up pipeline after a state change
48 */
49void PolyData::update()
50{
51    if (_dataSet == NULL) {
52        return;
53    }
54
55    vtkDataSet *ds = _dataSet->getVtkDataSet();
56
57    if (_mapper == NULL) {
58        _mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
59        _mapper->SetResolveCoincidentTopologyToPolygonOffset();
60        // If there are color scalars, use them without lookup table (if scalar visibility is on)
61        _mapper->SetColorModeToDefault();
62        // Use Point data if available, else cell data
63        _mapper->SetScalarModeToDefault();
64        _mapper->ScalarVisibilityOff();
65    }
66
67    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
68    if (pd) {
69        TRACE("Points: %d Verts: %d Lines: %d Polys: %d Strips: %d",
70              pd->GetNumberOfPoints(),
71              pd->GetNumberOfVerts(),
72              pd->GetNumberOfLines(),
73              pd->GetNumberOfPolys(),
74              pd->GetNumberOfStrips());
75    }
76    bool hasNormals = false;
77    if ((ds->GetPointData() != NULL &&
78         ds->GetPointData()->GetNormals() != NULL) ||
79        (ds->GetCellData() != NULL &&
80         ds->GetCellData()->GetNormals() != NULL)) {
81        hasNormals = true;
82    }
83
84    if (_dataSet->isCloud()) {
85        // DataSet is a point cloud
86        PrincipalPlane plane;
87        double offset;
88        if (_cloudStyle == CLOUD_POINTS ||
89            _dataSet->numDimensions() < 2 || ds->GetNumberOfPoints() < 3) { // 0D or 1D or not enough points to mesh
90            vtkSmartPointer<vtkVertexGlyphFilter> vgf = vtkSmartPointer<vtkVertexGlyphFilter>::New();
91#ifdef USE_VTK6
92            vgf->SetInputData(ds);
93#else
94            vgf->SetInput(ds);
95#endif
96            _mapper->SetInputConnection(vgf->GetOutputPort());
97        } else if (_dataSet->is2D(&plane, &offset)) {
98            vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
99            if (plane == PLANE_ZY) {
100                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
101                trans->RotateWXYZ(90, 0, 1, 0);
102                if (offset != 0.0) {
103                    trans->Translate(-offset, 0, 0);
104                }
105                mesher->SetTransform(trans);
106            } else if (plane == PLANE_XZ) {
107                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
108                trans->RotateWXYZ(-90, 1, 0, 0);
109                if (offset != 0.0) {
110                    trans->Translate(0, -offset, 0);
111                }
112                mesher->SetTransform(trans);
113            } else if (offset != 0.0) {
114                // XY with Z offset
115                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
116                trans->Translate(0, 0, -offset);
117                mesher->SetTransform(trans);
118            }
119#ifdef USE_VTK6
120            mesher->SetInputData(ds);
121#else
122            mesher->SetInput(ds);
123#endif
124            mesher->ReleaseDataFlagOn();
125            mesher->Update();
126            vtkPolyData *outpd = mesher->GetOutput();
127            TRACE("Delaunay2D Verts: %d Lines: %d Polys: %d Strips: %d",
128                  outpd->GetNumberOfVerts(),
129                  outpd->GetNumberOfLines(),
130                  outpd->GetNumberOfPolys(),
131                  outpd->GetNumberOfStrips());
132            if (outpd->GetNumberOfPolys() == 0) {
133                WARN("Delaunay2D mesher failed");
134                vtkSmartPointer<vtkVertexGlyphFilter> vgf = vtkSmartPointer<vtkVertexGlyphFilter>::New();
135#ifdef USE_VTK6
136                vgf->SetInputData(ds);
137#else
138                vgf->SetInput(ds);
139#endif
140                _mapper->SetInputConnection(vgf->GetOutputPort());
141            } else {
142                _mapper->SetInputConnection(mesher->GetOutputPort());
143                vtkSmartPointer<vtkPolyDataNormals> normalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
144                normalFilter->SetInputConnection(mesher->GetOutputPort());
145                _mapper->SetInputConnection(normalFilter->GetOutputPort());
146            }
147        } else {
148            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
149#ifdef USE_VTK6
150            mesher->SetInputData(ds);
151#else
152            mesher->SetInput(ds);
153#endif
154            mesher->ReleaseDataFlagOn();
155            mesher->Update();
156            vtkUnstructuredGrid *grid = mesher->GetOutput();
157            TRACE("Delaunay3D Cells: %d",
158                  grid->GetNumberOfCells());
159            if (grid->GetNumberOfCells() == 0) {
160                WARN("Delaunay3D mesher failed");
161                vtkSmartPointer<vtkVertexGlyphFilter> vgf = vtkSmartPointer<vtkVertexGlyphFilter>::New();
162#ifdef USE_VTK6
163                vgf->SetInputData(ds);
164#else
165                vgf->SetInput(ds);
166#endif
167                _mapper->SetInputConnection(vgf->GetOutputPort());
168            } else {
169                // Delaunay3D returns an UnstructuredGrid, so feed it
170                // through a surface filter to get the grid boundary
171                // as a PolyData
172                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
173                gf->UseStripsOn();
174                gf->ReleaseDataFlagOn();
175                gf->SetInputConnection(mesher->GetOutputPort());
176                vtkSmartPointer<vtkPolyDataNormals> normalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
177                normalFilter->SetInputConnection(gf->GetOutputPort());
178                _mapper->SetInputConnection(normalFilter->GetOutputPort());
179            }
180        }
181    } else if (pd) {
182        // DataSet is a vtkPolyData with cells
183        if (hasNormals) {
184#ifdef USE_VTK6
185            _mapper->SetInputData(pd);
186#else
187            _mapper->SetInput(pd);
188#endif
189        } else {
190            vtkSmartPointer<vtkPolyDataNormals> normalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
191#ifdef USE_VTK6
192            normalFilter->SetInputData(pd);
193#else
194            normalFilter->SetInput(pd);
195#endif
196            _mapper->SetInputConnection(normalFilter->GetOutputPort());
197        }
198    } else {
199        // DataSet is NOT a vtkPolyData
200        TRACE("DataSet is not a PolyData");
201        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
202        gf->UseStripsOn();
203        gf->ReleaseDataFlagOn();
204#ifdef USE_VTK6
205        gf->SetInputData(ds);
206#else
207        gf->SetInput(ds);
208#endif
209        vtkSmartPointer<vtkPolyDataNormals> normalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
210        normalFilter->SetInputConnection(gf->GetOutputPort());
211        _mapper->SetInputConnection(normalFilter->GetOutputPort());
212    }
213
214    initProp();
215    getActor()->SetMapper(_mapper);
216    _mapper->Update();
217#ifdef WANT_TRACE
218    double *b = getBounds();
219    TRACE("bounds: %g %g %g %g %g %g", b[0], b[1], b[2], b[3], b[4], b[5]);
220#endif
221}
222
223/**
224 * \brief Set a group of world coordinate planes to clip rendering
225 *
226 * Passing NULL for planes will remove all cliping planes
227 */
228void PolyData::setClippingPlanes(vtkPlaneCollection *planes)
229{
230    if (_mapper != NULL) {
231        _mapper->SetClippingPlanes(planes);
232    }
233}
234
235void PolyData::setCloudStyle(CloudStyle style)
236{
237    if (style != _cloudStyle) {
238        _cloudStyle = style;
239        if (_dataSet != NULL) {
240            update();
241        }
242    }
243}
Note: See TracBrowser for help on using the repository browser.