Ignore:
Timestamp:
May 24, 2011 5:19:52 PM (13 years ago)
Author:
ldelgass
Message:

New heightmap command/object in vtkvis server - contour plot with vertical
displacement. Also initial work on supporting additional data set types
such as point clouds.

Location:
trunk/packages/vizservers/vtkvis
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/Makefile.in

    r2254 r2260  
    2323MKDIR_P         = @MKDIR_P@
    2424
     25GL_LIB_SPEC     = -lGL
     26
    2527TCL_LIB_SPEC    = @TCL_LIB_SPEC@
    2628TCL_INC_SPEC    = @TCL_INC_SPEC@
     
    3335
    3436LIBS            = \
     37                $(GL_LIB_SPEC) \
    3538                $(TCL_LIB_SPEC) \
    3639                $(VTK_LIB_SPEC) \
     
    6972                PPMWriter.cpp \
    7073                RpContour2D.cpp \
     74                RpHeightMap.cpp \
    7175                RpPolyData.cpp \
    7276                RpPseudoColor.cpp \
     
    117121RpContour2D.o: RpContour2D.h RpVtkDataSet.h Trace.h
    118122RpPolyData.o: RpPolyData.h RpVtkDataSet.h Trace.h
     123RpHeightMap.o: RpHeightMap.h RpVtkDataSet.h Trace.h
    119124RpPseudoColor.o: RpPseudoColor.h RpVtkDataSet.h Trace.h
    120125RpVtkDataSet.o: RpVtkDataSet.h Trace.h
    121126RpVtkRenderer.o: RpVtkRenderer.h RpVtkDataSet.h RpPolyData.h RpPseudoColor.h RpContour2D.h ColorMap.h Trace.h
    122 RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h ColorMap.h
    123 RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h
     127RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h CmdProc.h ColorMap.h PPMWriter.h TGAWriter.h
     128RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h PPMWriter.h TGAWriter.h
    124129Trace.o: Trace.h
    125130TGAWriter.o: TGAWriter.h Trace.h
  • trunk/packages/vizservers/vtkvis/PPMWriter.cpp

    r2100 r2260  
    3131 * routine could be made even simpler (faster) if the image data had top
    3232 * to bottom scanlines.
     33 *
     34 * \param[in] fd File descriptor that will be written to
     35 * \param[in] cmdName Command name to send (byte length will be appended)
     36 * \param[in] data Image data
     37 * \param[in] width Width of image in pixels
     38 * \param[in] height Height of image in pixels
    3339 */
    3440void
  • trunk/packages/vizservers/vtkvis/RpContour2D.cpp

    r2194 r2260  
    66 */
    77
     8#include <cassert>
     9
    810#include <vtkContourFilter.h>
    911#include <vtkPolyDataMapper.h>
     12#include <vtkUnstructuredGrid.h>
    1013#include <vtkProperty.h>
     14#include <vtkPointData.h>
     15#include <vtkDelaunay2D.h>
     16#include <vtkDelaunay3D.h>
     17#include <vtkDataSetSurfaceFilter.h>
    1118
    1219#include "RpContour2D.h"
     
    6875 * \brief Get the VTK Actor for the contour lines
    6976 */
    70 vtkActor *Contour2D::getActor()
     77vtkProp *Contour2D::getActor()
    7178{
    7279    return _contourActor;
     
    96103        return;
    97104    }
     105    vtkDataSet *ds = _dataSet->getVtkDataSet();
    98106
    99107    initActor();
     
    103111        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
    104112    }
    105 
    106     _contourFilter->SetInput(_dataSet->getVtkDataSet());
     113 
     114    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
     115    if (pd) {
     116        // DataSet is a vtkPolyData
     117        if (pd->GetNumberOfLines() == 0 &&
     118            pd->GetNumberOfPolys() == 0 &&
     119            pd->GetNumberOfStrips() == 0) {
     120            // DataSet is a point cloud
     121            if (_dataSet->is2D()) {
     122                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     123                mesher->SetInput(pd);
     124                pd = mesher->GetOutput();
     125                assert(pd);
     126                _contourFilter->SetInput(pd);
     127            } else {
     128                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
     129                mesher->SetInput(pd);
     130                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     131                gf->SetInput(mesher->GetOutput());
     132                gf->Update();
     133                pd = gf->GetOutput();
     134                assert(pd);
     135                _contourFilter->SetInput(pd);
     136             }
     137        } else {
     138            // DataSet is a vtkPolyData with lines and/or polygons
     139            _contourFilter->SetInput(ds);
     140        }
     141    } else {
     142        TRACE("Generating surface for data set");
     143        // DataSet is NOT a vtkPolyData
     144        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     145        gf->SetInput(ds);
     146        gf->Update();
     147        pd = gf->GetOutput();
     148        assert(pd);
     149        _contourFilter->SetInput(pd);
     150    }
    107151
    108152    _contourFilter->ComputeNormalsOff();
     
    130174        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    131175        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
     176        _contourMapper->SetInput(_contourFilter->GetOutput());
    132177        _contourActor->SetMapper(_contourMapper);
    133         _contourMapper->SetInput(_contourFilter->GetOutput());
    134178    }
    135179}
  • trunk/packages/vizservers/vtkvis/RpContour2D.h

    r2194 r2260  
    3434    DataSet *getDataSet();
    3535
    36     vtkActor *getActor();
     36    vtkProp *getActor();
    3737
    3838    void setContours(int numContours);
  • trunk/packages/vizservers/vtkvis/RpPolyData.cpp

    r2235 r2260  
    66 */
    77
     8#include <cassert>
     9
    810#include <vtkDataSet.h>
    911#include <vtkPolyData.h>
     12#include <vtkDataSetMapper.h>
     13#include <vtkUnstructuredGrid.h>
    1014#include <vtkPolyDataMapper.h>
    1115#include <vtkActor.h>
    1216#include <vtkProperty.h>
     17#include <vtkDelaunay2D.h>
     18#include <vtkDelaunay3D.h>
    1319
    1420#include "RpPolyData.h"
     
    4450 * \brief Get the VTK Actor for the mesh
    4551 */
    46 vtkActor *PolyData::getActor()
     52vtkProp *PolyData::getActor()
    4753{
    4854    return _pdActor;
     
    7884            ERROR("DataSet is not a PolyData");
    7985            return;
     86        } else {
     87            TRACE("DataSet is a vtkPolyData");
     88            vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
     89            assert(pd);
     90            TRACE("Verts: %d Lines: %d Polys: %d Strips: %d",
     91                  pd->GetNumberOfVerts(),
     92                  pd->GetNumberOfLines(),
     93                  pd->GetNumberOfPolys(),
     94                  pd->GetNumberOfStrips());
    8095        }
    81         TRACE("DataSet is a vtkPolyData");
    8296        _dataSet = dataSet;
    8397        update();
     
    111125    _pdActor->SetMapper(_pdMapper);
    112126
    113     _pdMapper->SetInput(vtkPolyData::SafeDownCast(_dataSet->getVtkDataSet()));
     127    vtkPolyData *pd = vtkPolyData::SafeDownCast(_dataSet->getVtkDataSet());
     128    assert(pd);
     129
     130    if (pd->GetNumberOfLines() == 0 &&
     131        pd->GetNumberOfPolys() == 0 &&
     132        pd->GetNumberOfStrips() == 0) {
     133        // Point cloud
     134        if (_dataSet->is2D()) {
     135            vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     136            mesher->SetInput(pd);
     137            _pdMapper->SetInput(mesher->GetOutput());
     138        } else {
     139            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
     140            mesher->SetInput(pd);
     141            // Delaunay3D returns an UnstructuredGrid, so feed it through a generic mapper
     142            // to get the grid boundary as a PolyData
     143            vtkSmartPointer<vtkDataSetMapper> dsMapper =  vtkSmartPointer<vtkDataSetMapper>::New();
     144            dsMapper->SetInput(mesher->GetOutput());
     145            dsMapper->StaticOn();
     146            _pdMapper = dsMapper->GetPolyDataMapper();
     147            _pdMapper->SetResolveCoincidentTopologyToPolygonOffset();
     148            _pdMapper->ScalarVisibilityOff();
     149        }
     150    } else {
     151        _pdMapper->SetInput(pd);
     152        _pdMapper->StaticOn();
     153    }
    114154}
    115155
  • trunk/packages/vizservers/vtkvis/RpPolyData.h

    r2137 r2260  
    3232    DataSet *getDataSet();
    3333
    34     vtkActor *getActor();
     34    vtkProp *getActor();
    3535
    3636    void setVisibility(bool state);
  • trunk/packages/vizservers/vtkvis/RpPseudoColor.cpp

    r2194 r2260  
    66 */
    77
     8#include <cassert>
     9
    810#include <vtkDataSet.h>
    911#include <vtkDataSetMapper.h>
     12#include <vtkUnstructuredGrid.h>
    1013#include <vtkProperty.h>
    1114#include <vtkPointData.h>
     15#include <vtkImageData.h>
    1216#include <vtkLookupTable.h>
     17#include <vtkDelaunay2D.h>
     18#include <vtkDelaunay3D.h>
     19#include <vtkGaussianSplatter.h>
     20#include <vtkExtractVOI.h>
     21#include <vtkDataSetSurfaceFilter.h>
    1322
    1423#include "RpPseudoColor.h"
     
    4453void PseudoColor::setDataSet(DataSet *dataSet)
    4554{
    46     _dataSet = dataSet;
    47     update();
     55    if (_dataSet != dataSet) {
     56        _dataSet = dataSet;
     57        update();
     58    }
    4859}
    4960
     
    7384        _dsMapper = vtkSmartPointer<vtkDataSetMapper>::New();
    7485    }
    75     _dsMapper->SetInput(ds);
    76     _dsMapper->StaticOff();
     86
     87    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
     88    if (pd) {
     89        // DataSet is a vtkPolyData
     90        if (pd->GetNumberOfLines() == 0 &&
     91            pd->GetNumberOfPolys() == 0 &&
     92            pd->GetNumberOfStrips() == 0) {
     93            // DataSet is a point cloud
     94            if (_dataSet->is2D()) {
     95#if 0
     96                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     97                mesher->SetInput(pd);
     98                pd = mesher->GetOutput();
     99#else
     100                vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
     101                splatter->SetInput(pd);
     102                int dims[3];
     103                splatter->GetSampleDimensions(dims);
     104                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
     105                dims[2] = 3;
     106                splatter->SetSampleDimensions(dims);
     107                double bounds[6];
     108                splatter->Update();
     109                splatter->GetModelBounds(bounds);
     110                TRACE("Model bounds: %g %g %g %g %g %g",
     111                      bounds[0], bounds[1],
     112                      bounds[2], bounds[3],
     113                      bounds[4], bounds[5]);
     114                vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
     115                slicer->SetInput(splatter->GetOutput());
     116                slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
     117                slicer->SetSampleRate(1, 1, 1);
     118                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     119                gf->SetInput(slicer->GetOutput());
     120                gf->Update();
     121                pd = gf->GetOutput();
     122#endif
     123                assert(pd);
     124                _dsMapper->SetInput(pd);
     125            } else {
     126                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
     127                mesher->SetInput(pd);
     128                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     129                gf->SetInput(mesher->GetOutput());
     130                gf->Update();
     131                pd = gf->GetOutput();
     132                assert(pd);
     133                _dsMapper->SetInput(pd);
     134             }
     135        } else {
     136            // DataSet is a vtkPolyData with lines and/or polygons
     137            _dsMapper->SetInput(ds);
     138        }
     139    } else {
     140        TRACE("Generating surface for data set");
     141        // DataSet is NOT a vtkPolyData
     142        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     143        gf->SetInput(ds);
     144        gf->Update();
     145        pd = gf->GetOutput();
     146        assert(pd);
     147        _dsMapper->SetInput(pd);
     148    }
     149
     150    //_dsMapper->StaticOn();
    77151
    78152    if (ds->GetPointData() == NULL ||
     
    106180 * \brief Get the VTK Actor for the colormapped dataset
    107181 */
    108 vtkActor *PseudoColor::getActor()
     182vtkProp *PseudoColor::getActor()
    109183{
    110184    return _dsActor;
  • trunk/packages/vizservers/vtkvis/RpPseudoColor.h

    r2137 r2260  
    3434    DataSet *getDataSet();
    3535
    36     vtkActor *getActor();
     36    vtkProp *getActor();
    3737
    3838    void setLookupTable(vtkLookupTable *lut);
  • trunk/packages/vizservers/vtkvis/RpVtkDataSet.cpp

    r2194 r2260  
    9191    _dataSet->GetScalarRange(_dataRange);
    9292
     93    TRACE("DataSet class: %s", _dataSet->GetClassName());
    9394    TRACE("Scalar Range: %.12e, %.12e", _dataRange[0], _dataRange[1]);
    9495    return true;
     
    9697
    9798/**
    98  * \brief Read dataset using supplied reader
     99 * \brief Set dataset from existing vtkDataSet object
    99100 */
    100101bool DataSet::setData(vtkDataSet *ds)
     
    105106    _dataSet->GetBounds(_bounds);
    106107
     108    TRACE("DataSet class: %s", _dataSet->GetClassName());
    107109    TRACE("Scalar Range: %.12e, %.12e", _dataRange[0], _dataRange[1]);
    108110    return true;
     
    134136
    135137/**
     138 * \brief Get the underlying VTK DataSet subclass class name
     139 */
     140const char *DataSet::getVtkType()
     141{
     142    return _dataSet->GetClassName();
     143}
     144
     145/**
    136146 * \brief Get the range of scalar values in the DataSet
    137147 */
  • trunk/packages/vizservers/vtkvis/RpVtkDataSet.h

    r2194 r2260  
    4141    vtkDataSet *getVtkDataSet();
    4242
     43    const char *getVtkType();
     44
    4345    void getDataRange(double minmax[2]);
    4446
  • trunk/packages/vizservers/vtkvis/RpVtkRenderServer.cpp

    r2194 r2260  
    1414#include <signal.h>
    1515
     16#ifdef WANT_TRACE
     17#include <sys/time.h>
     18#endif
     19
    1620#include "Trace.h"
    1721#include "RpVtkRenderServer.h"
     
    2933FILE *Rappture::VtkVis::g_fLog = NULL; ///< Trace logging file handle
    3034Renderer *Rappture::VtkVis::g_renderer = NULL; ///< Main render worker
     35
     36#define ELAPSED_TIME(t1, t2) \
     37    ((t1).tv_sec == (t2).tv_sec ? (((t2).tv_usec - (t1).tv_usec)/1.0e+3f) : \
     38     (((t2).tv_sec - (t1).tv_sec))*1.0e+3f + (float)((t2).tv_usec - (t1).tv_usec)/1.0e+3f)
    3139
    3240static void
     
    4452    }
    4553
     54#ifdef RENDER_TARGA
    4655    writeTGAFile("/tmp/frame.tga",
    4756                 imgData->GetPointer(0),
    4857                 g_renderer->getWindowWidth(),
    49                  g_renderer->getWindowHeight());
     58                 g_renderer->getWindowHeight(),
     59                 TARGA_BYTES_PER_PIXEL);
     60#else
     61    writeTGAFile("/tmp/frame.tga",
     62                 imgData->GetPointer(0),
     63                 g_renderer->getWindowWidth(),
     64                 g_renderer->getWindowHeight(),
     65                 TARGA_BYTES_PER_PIXEL,
     66                 true);
     67#endif
     68
    5069#else
    5170    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     
    6281            << xywh[1] << "} -bytes";
    6382
     83#ifdef RENDER_TARGA
     84        writeTGA(fd, oss.str().c_str(),
     85                 imgData->GetPointer(0),
     86                 g_renderer->getWindowWidth(),
     87                 g_renderer->getWindowHeight(),
     88                 TARGA_BYTES_PER_PIXEL);
     89#else
    6490        writePPM(fd, oss.str().c_str(),
    6591                 imgData->GetPointer(0),
    6692                 g_renderer->getWindowWidth(),
    6793                 g_renderer->getWindowHeight());
     94#endif
    6895    } else {
     96#ifdef RENDER_TARGA
     97        writeTGA(fd, "nv>image -type image -bytes",
     98                 imgData->GetPointer(0),
     99                 g_renderer->getWindowWidth(),
     100                 g_renderer->getWindowHeight(),
     101                 TARGA_BYTES_PER_PIXEL);
     102#else
    69103        writePPM(fd, "nv>image -type image -bytes",
    70104                 imgData->GetPointer(0),
    71105                 g_renderer->getWindowWidth(),
    72106                 g_renderer->getWindowHeight());
     107#endif
    73108    }
    74109#endif
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2254 r2260  
    99#include <cstring>
    1010#include <cassert>
     11
     12#include <GL/gl.h>
     13
     14#ifdef WANT_TRACE
     15#include <sys/time.h>
     16#endif
    1117
    1218#include <vtkMath.h>
     
    3137#include <vtkLookupTable.h>
    3238#include <vtkTextProperty.h>
     39#include <vtkOpenGLRenderWindow.h>
    3340
    3441#include "RpVtkRenderer.h"
    3542#include "ColorMap.h"
    3643#include "Trace.h"
     44
     45#define ELAPSED_TIME(t1, t2) \
     46    ((t1).tv_sec == (t2).tv_sec ? (((t2).tv_usec - (t1).tv_usec)/1.0e+3f) : \
     47     (((t2).tv_sec - (t1).tv_sec))*1.0e+3f + (float)((t2).tv_usec - (t1).tv_usec)/1.0e+3f)
    3748
    3849using namespace Rappture::VtkVis;
     
    4455    _cameraZoomRatio(1),
    4556    _useCumulativeRange(true),
    46     _cumulativeRangeOnlyVisible(false)
     57    _cumulativeRangeOnlyVisible(false),
     58    _cameraMode(PERSPECTIVE)
    4759{
    4860    _bgColor[0] = 0;
     
    7789    _renderer = vtkSmartPointer<vtkRenderer>::New();
    7890    _renderer->LightFollowCameraOn();
    79     _cameraMode = PERSPECTIVE;
    8091    initAxes();
    8192    initCamera();
     
    8596    _renderWindow->DoubleBufferOff();
    8697    _renderWindow->OffScreenRenderingOn();
     98#else
     99    _renderWindow->SwapBuffersOff();
    87100#endif
    88101    _renderWindow->SetSize(_windowWidth, _windowHeight);
     
    108121    }
    109122    _contours.clear();
     123    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     124             itr != _heightMaps.end(); ++itr) {
     125        delete itr->second;
     126    }
     127    _heightMaps.clear();
    110128    for (PolyDataHashmap::iterator itr = _polyDatas.begin();
    111129             itr != _polyDatas.end(); ++itr) {
     
    163181        PseudoColor *ps = itr->second;
    164182        if (ps->getActor())
    165             _renderer->RemoveActor(ps->getActor());
     183            _renderer->RemoveViewProp(ps->getActor());
    166184        delete ps;
    167185
     
    199217        Contour2D *contour = itr->second;
    200218        if (contour->getActor())
    201             _renderer->RemoveActor(contour->getActor());
     219            _renderer->RemoveViewProp(contour->getActor());
    202220        delete contour;
    203221
     
    209227
    210228/**
     229 * \brief Remove the HeightMap for the specified DataSet
     230 *
     231 * The underlying HeightMap is deleted, freeing its memory
     232 */
     233void Renderer::deleteHeightMap(const DataSetId& id)
     234{
     235    HeightMapHashmap::iterator itr;
     236
     237    bool doAll = false;
     238
     239    if (id.compare("all") == 0) {
     240        itr = _heightMaps.begin();
     241        doAll = true;
     242    } else {
     243        itr = _heightMaps.find(id);
     244    }
     245    if (itr == _heightMaps.end()) {
     246        ERROR("HeightMap not found: %s", id.c_str());
     247        return;
     248    }
     249
     250    TRACE("Deleting HeightMaps for %s", id.c_str());
     251
     252    do {
     253        HeightMap *hmap = itr->second;
     254        if (hmap->getActor())
     255            _renderer->RemoveViewProp(hmap->getActor());
     256        delete hmap;
     257
     258        _heightMaps.erase(itr);
     259    } while (doAll && ++itr != _heightMaps.end());
     260
     261    _needsRedraw = true;
     262}
     263
     264/**
    211265 * \brief Remove the PolyData mesh for the specified DataSet
    212266 *
     
    235289        PolyData *polyData = itr->second;
    236290        if (polyData->getActor())
    237             _renderer->RemoveActor(polyData->getActor());
     291            _renderer->RemoveViewProp(polyData->getActor());
    238292        delete polyData;
    239293
     
    247301 * \brief Remove the specified DataSet and associated rendering objects
    248302 *
    249  * The underlying DataSet and any associated Contour2D and PseudoColor
     303 * The underlying DataSet and any associated graphics
    250304 * objects are deleted, freeing the memory used.
    251305 */
     
    272326        deletePseudoColor(itr->second->getName());
    273327        deleteContour2D(itr->second->getName());
     328        deleteHeightMap(itr->second->getName());
    274329        deletePolyData(itr->second->getName());
    275330   
     
    359414        if (_renderer->HasViewProp(_cubeAxesActor)) {
    360415            TRACE("Removing 3D axes");
    361             _renderer->RemoveActor(_cubeAxesActor);
     416            _renderer->RemoveViewProp(_cubeAxesActor);
    362417        }
    363418        if (!_renderer->HasViewProp(_cubeAxesActor2D)) {
    364419            TRACE("Adding 2D axes");
    365             _renderer->AddActor(_cubeAxesActor2D);
     420            _renderer->AddViewProp(_cubeAxesActor2D);
    366421        }
    367422    } else {
    368423        if (_renderer->HasViewProp(_cubeAxesActor2D)) {
    369424            TRACE("Removing 2D axes");
    370             _renderer->RemoveActor(_cubeAxesActor2D);
     425            _renderer->RemoveViewProp(_cubeAxesActor2D);
    371426        }
    372427        if (!_renderer->HasViewProp(_cubeAxesActor)) {
    373428            TRACE("Adding 3D axes");
    374             _renderer->AddActor(_cubeAxesActor);
     429            _renderer->AddViewProp(_cubeAxesActor);
    375430        }
    376431        double bounds[6];
     
    442497    if (_cameraMode == IMAGE) {
    443498        if (!_renderer->HasViewProp(_cubeAxesActor2D))
    444             _renderer->AddActor(_cubeAxesActor2D);
     499            _renderer->AddViewProp(_cubeAxesActor2D);
    445500    } else {
    446501        if (!_renderer->HasViewProp(_cubeAxesActor))
    447             _renderer->AddActor(_cubeAxesActor);
     502            _renderer->AddViewProp(_cubeAxesActor);
    448503    }
    449504}
     
    724779        _scalarBarActor = vtkSmartPointer<vtkScalarBarActor>::New();
    725780        _scalarBarActor->UseOpacityOn();
    726         _legendRenderer->AddActor(_scalarBarActor);
     781        _legendRenderer->AddViewProp(_scalarBarActor);
    727782    }
    728783
     
    762817    _legendRenderWindow->Render();
    763818
     819#ifdef RENDER_TARGA
     820    _legendRenderWindow->MakeCurrent();
     821    // Must clear previous errors first.
     822    while (glGetError() != GL_NO_ERROR){
     823        ;
     824    }
     825    int bytesPerPixel = TARGA_BYTES_PER_PIXEL;
     826    int size = bytesPerPixel * width * height;
     827
     828    if (imgData->GetMaxId() + 1 != size)
     829    {
     830        imgData->SetNumberOfComponents(bytesPerPixel);
     831        imgData->SetNumberOfValues(size);
     832    }
     833    glDisable(GL_TEXTURE_2D);
     834    glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_renderWindow)->GetFrontLeftBuffer()));
     835    glPixelStorei(GL_PACK_ALIGNMENT, 1);
     836    if (bytesPerPixel == 4) {
     837        glReadPixels(0, 0, width, height, GL_BGRA,
     838                     GL_UNSIGNED_BYTE, imgData->GetPointer(0));
     839    } else {
     840        glReadPixels(0, 0, width, height, GL_BGR,
     841                     GL_UNSIGNED_BYTE, imgData->GetPointer(0));
     842    }
     843    if (glGetError() != GL_NO_ERROR) {
     844        ERROR("glReadPixels");
     845    }
     846#else
    764847    _legendRenderWindow->GetPixelData(0, 0, width-1, height-1,
    765848                                      !_legendRenderWindow->GetDoubleBuffer(),
    766849                                      imgData);
     850#endif
    767851    return true;
    768852}
     
    814898        pc->setLookupTable(lut);
    815899
    816         _renderer->AddActor(pc->getActor());
     900        _renderer->AddViewProp(pc->getActor());
    817901    } while (doAll && ++itr != _dataSets.end());
    818902
     
    11061190        contour->setDataSet(ds);
    11071191
    1108         _renderer->AddActor(contour->getActor());
     1192        _renderer->AddViewProp(contour->getActor());
    11091193    } while (doAll && ++itr != _dataSets.end());
    11101194
     
    13231407
    13241408/**
     1409 * \brief Create a new HeightMap and associate it with the named DataSet
     1410 */
     1411void Renderer::addHeightMap(const DataSetId& id)
     1412{
     1413    DataSetHashmap::iterator itr;
     1414
     1415    bool doAll = false;
     1416
     1417    if (id.compare("all") == 0) {
     1418        itr = _dataSets.begin();
     1419    } else {
     1420        itr = _dataSets.find(id);
     1421    }
     1422    if (itr == _dataSets.end()) {
     1423        ERROR("Unknown dataset %s", id.c_str());
     1424        return;
     1425    }
     1426
     1427    do {
     1428        DataSet *ds = itr->second;
     1429        const DataSetId& dsID = ds->getName();
     1430
     1431        if (getHeightMap(dsID)) {
     1432            WARN("Replacing existing HeightMap %s", dsID.c_str());
     1433            deleteHeightMap(dsID);
     1434        }
     1435
     1436        HeightMap *hmap = new HeightMap();
     1437        _heightMaps[dsID] = hmap;
     1438
     1439        hmap->setDataSet(ds);
     1440
     1441        // Use the default color map
     1442        vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
     1443        ColorMap *cmap = getColorMap("default");
     1444        lut->DeepCopy(cmap->getLookupTable());
     1445        if (_useCumulativeRange) {
     1446            lut->SetRange(_cumulativeDataRange);
     1447        } else {
     1448            double range[2];
     1449            ds->getDataRange(range);
     1450            lut->SetRange(range);
     1451        }
     1452
     1453        hmap->setLookupTable(lut);
     1454
     1455        _renderer->AddViewProp(hmap->getActor());
     1456    } while (doAll && ++itr != _dataSets.end());
     1457
     1458    initCamera();
     1459
     1460    _needsRedraw = true;
     1461}
     1462
     1463/**
     1464 * \brief Get the HeightMap associated with a named DataSet
     1465 */
     1466HeightMap *Renderer::getHeightMap(const DataSetId& id)
     1467{
     1468    HeightMapHashmap::iterator itr = _heightMaps.find(id);
     1469
     1470    if (itr == _heightMaps.end()) {
     1471        TRACE("HeightMap not found: %s", id.c_str());
     1472        return NULL;
     1473    } else
     1474        return itr->second;
     1475}
     1476
     1477/**
     1478 * \brief Set the volume slice used for mapping volumetric data
     1479 */
     1480void Renderer::setHeightMapVolumeSlice(const DataSetId& id, HeightMap::Axis axis, double ratio)
     1481{
     1482    HeightMapHashmap::iterator itr;
     1483
     1484    bool doAll = false;
     1485
     1486    if (id.compare("all") == 0) {
     1487        itr = _heightMaps.begin();
     1488        doAll = true;
     1489    } else {
     1490        itr = _heightMaps.find(id);
     1491    }
     1492
     1493    if (itr == _heightMaps.end()) {
     1494        ERROR("HeightMap not found: %s", id.c_str());
     1495        return;
     1496    }
     1497
     1498    do {
     1499        itr->second->selectVolumeSlice(axis, ratio);
     1500     } while (doAll && ++itr != _heightMaps.end());
     1501
     1502    initCamera();
     1503    _needsRedraw = true;
     1504}
     1505
     1506/**
     1507 * \brief Set amount to scale scalar values when creating elevations
     1508 * in the height map
     1509 */
     1510void Renderer::setHeightMapHeightScale(const DataSetId& id, double scale)
     1511{
     1512    HeightMapHashmap::iterator itr;
     1513
     1514    bool doAll = false;
     1515
     1516    if (id.compare("all") == 0) {
     1517        itr = _heightMaps.begin();
     1518        doAll = true;
     1519    } else {
     1520        itr = _heightMaps.find(id);
     1521    }
     1522
     1523    if (itr == _heightMaps.end()) {
     1524        ERROR("HeightMap not found: %s", id.c_str());
     1525        return;
     1526    }
     1527
     1528    do {
     1529        itr->second->setHeightScale(scale);
     1530     } while (doAll && ++itr != _heightMaps.end());
     1531
     1532    initCamera();
     1533    _needsRedraw = true;
     1534}
     1535
     1536/**
     1537 * \brief Associate an existing named color map with a DataSet
     1538 */
     1539void Renderer::setHeightMapColorMap(const DataSetId& id, const ColorMapId& colorMapId)
     1540{
     1541    HeightMapHashmap::iterator itr;
     1542
     1543    bool doAll = false;
     1544
     1545    if (id.compare("all") == 0) {
     1546        itr = _heightMaps.begin();
     1547        doAll = true;
     1548    } else {
     1549        itr = _heightMaps.find(id);
     1550    }
     1551
     1552    if (itr == _heightMaps.end()) {
     1553        ERROR("HeightMap not found: %s", id.c_str());
     1554        return;
     1555    }
     1556
     1557    ColorMap *cmap = getColorMap(colorMapId);
     1558    if (cmap == NULL) {
     1559        ERROR("Unknown colormap: %s", colorMapId.c_str());
     1560        return;
     1561    }
     1562
     1563    do {
     1564        TRACE("Set color map: %s for dataset %s", colorMapId.c_str(),
     1565              itr->second->getDataSet()->getName().c_str());
     1566
     1567        // Make a copy of the generic colormap lookup table, so
     1568        // data range can be set in the copy table to match the
     1569        // dataset being plotted
     1570        vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
     1571        lut->DeepCopy(cmap->getLookupTable());
     1572
     1573        if (_useCumulativeRange) {
     1574            lut->SetRange(_cumulativeDataRange);
     1575        } else {
     1576            if (itr->second->getDataSet() != NULL) {
     1577                double range[2];
     1578                itr->second->getDataSet()->getDataRange(range);
     1579                lut->SetRange(range);
     1580            }
     1581        }
     1582
     1583        itr->second->setLookupTable(lut);
     1584    } while (doAll && ++itr != _heightMaps.end());
     1585
     1586    _needsRedraw = true;
     1587}
     1588
     1589/**
     1590 * \brief Get the height map's color map (vtkLookupTable) for the given DataSet
     1591 *
     1592 * \return The associated lookup table or NULL if not found
     1593 */
     1594vtkLookupTable *Renderer::getHeightMapColorMap(const DataSetId& id)
     1595{
     1596    HeightMap *hm = getHeightMap(id);
     1597    if (hm)
     1598        return hm->getLookupTable();
     1599    else
     1600        return NULL;
     1601}
     1602
     1603/**
     1604 * \brief Set the number of equally spaced contour isolines for the given DataSet
     1605 */
     1606void Renderer::setHeightMapContours(const DataSetId& id, int numContours)
     1607{
     1608    HeightMapHashmap::iterator itr;
     1609
     1610    bool doAll = false;
     1611
     1612    if (id.compare("all") == 0) {
     1613        itr = _heightMaps.begin();
     1614        doAll = true;
     1615    } else {
     1616        itr = _heightMaps.find(id);
     1617    }
     1618    if (itr == _heightMaps.end()) {
     1619        ERROR("HeightMap not found: %s", id.c_str());
     1620        return;
     1621    }
     1622
     1623    do {
     1624        if (_useCumulativeRange) {
     1625            itr->second->setContours(numContours, _cumulativeDataRange);
     1626        } else {
     1627            itr->second->setContours(numContours);
     1628        }
     1629    } while (doAll && ++itr != _heightMaps.end());
     1630
     1631    _needsRedraw = true;
     1632}
     1633
     1634/**
     1635 * \brief Set a list of height map contour isovalues for the given DataSet
     1636 */
     1637void Renderer::setHeightMapContourList(const DataSetId& id, const std::vector<double>& contours)
     1638{
     1639    HeightMapHashmap::iterator itr;
     1640
     1641    bool doAll = false;
     1642
     1643    if (id.compare("all") == 0) {
     1644        itr = _heightMaps.begin();
     1645        doAll = true;
     1646    } else {
     1647        itr = _heightMaps.find(id);
     1648    }
     1649    if (itr == _heightMaps.end()) {
     1650        ERROR("HeightMap not found: %s", id.c_str());
     1651        return;
     1652    }
     1653
     1654    do {
     1655        itr->second->setContourList(contours);
     1656    } while (doAll && ++itr != _heightMaps.end());
     1657
     1658     _needsRedraw = true;
     1659}
     1660
     1661/**
     1662 * \brief Set opacity of height map for the given DataSet
     1663 */
     1664void Renderer::setHeightMapOpacity(const DataSetId& id, double opacity)
     1665{
     1666    HeightMapHashmap::iterator itr;
     1667
     1668    bool doAll = false;
     1669
     1670    if (id.compare("all") == 0) {
     1671        itr = _heightMaps.begin();
     1672        doAll = true;
     1673    } else {
     1674        itr = _heightMaps.find(id);
     1675    }
     1676    if (itr == _heightMaps.end()) {
     1677        ERROR("HeightMap not found: %s", id.c_str());
     1678        return;
     1679    }
     1680
     1681    do {
     1682        itr->second->setOpacity(opacity);
     1683    } while (doAll && ++itr != _heightMaps.end());
     1684
     1685    _needsRedraw = true;
     1686}
     1687
     1688/**
     1689 * \brief Turn on/off rendering height map for the given DataSet
     1690 */
     1691void Renderer::setHeightMapVisibility(const DataSetId& id, bool state)
     1692{
     1693    HeightMapHashmap::iterator itr;
     1694
     1695    bool doAll = false;
     1696
     1697    if (id.compare("all") == 0) {
     1698        itr = _heightMaps.begin();
     1699        doAll = true;
     1700    } else {
     1701        itr = _heightMaps.find(id);
     1702    }
     1703    if (itr == _heightMaps.end()) {
     1704        ERROR("HeightMap not found: %s", id.c_str());
     1705        return;
     1706    }
     1707
     1708    do {
     1709        itr->second->setVisibility(state);
     1710    } while (doAll && ++itr != _heightMaps.end());
     1711
     1712    _needsRedraw = true;
     1713}
     1714
     1715/**
     1716 * \brief Turn on/off rendering height map mesh edges for the given DataSet
     1717 */
     1718void Renderer::setHeightMapEdgeVisibility(const DataSetId& id, bool state)
     1719{
     1720    HeightMapHashmap::iterator itr;
     1721
     1722    bool doAll = false;
     1723
     1724    if (id.compare("all") == 0) {
     1725        itr = _heightMaps.begin();
     1726        doAll = true;
     1727    } else {
     1728        itr = _heightMaps.find(id);
     1729    }
     1730    if (itr == _heightMaps.end()) {
     1731        ERROR("HeightMap not found: %s", id.c_str());
     1732        return;
     1733    }
     1734
     1735    do {
     1736        itr->second->setEdgeVisibility(state);
     1737    } while (doAll && ++itr != _heightMaps.end());
     1738
     1739    _needsRedraw = true;
     1740}
     1741
     1742/**
     1743 * \brief Set the RGB height map mesh edge color for the specified DataSet
     1744 */
     1745void Renderer::setHeightMapEdgeColor(const DataSetId& id, float color[3])
     1746{
     1747    HeightMapHashmap::iterator itr;
     1748
     1749    bool doAll = false;
     1750
     1751    if (id.compare("all") == 0) {
     1752        itr = _heightMaps.begin();
     1753        doAll = true;
     1754    } else {
     1755        itr = _heightMaps.find(id);
     1756    }
     1757    if (itr == _heightMaps.end()) {
     1758        ERROR("HeightMap not found: %s", id.c_str());
     1759        return;
     1760    }
     1761
     1762    do {
     1763        itr->second->setEdgeColor(color);
     1764    } while (doAll && ++itr != _heightMaps.end());
     1765
     1766    _needsRedraw = true;
     1767}
     1768
     1769/**
     1770 * \brief Set the height map mesh edge width for the specified DataSet (may be a no-op)
     1771 *
     1772 * If the OpenGL implementation/hardware does not support wide lines,
     1773 * this function may not have an effect.
     1774 */
     1775void Renderer::setHeightMapEdgeWidth(const DataSetId& id, float edgeWidth)
     1776{
     1777    HeightMapHashmap::iterator itr;
     1778
     1779    bool doAll = false;
     1780
     1781    if (id.compare("all") == 0) {
     1782        itr = _heightMaps.begin();
     1783        doAll = true;
     1784    } else {
     1785        itr = _heightMaps.find(id);
     1786    }
     1787    if (itr == _heightMaps.end()) {
     1788        ERROR("HeightMap not found: %s", id.c_str());
     1789        return;
     1790    }
     1791
     1792    do {
     1793        itr->second->setEdgeWidth(edgeWidth);
     1794    } while (doAll && ++itr != _heightMaps.end());
     1795
     1796    _needsRedraw = true;
     1797}
     1798
     1799/**
     1800 * \brief Turn on/off rendering height map contour lines for the given DataSet
     1801 */
     1802void Renderer::setHeightMapContourVisibility(const DataSetId& id, bool state)
     1803{
     1804    HeightMapHashmap::iterator itr;
     1805
     1806    bool doAll = false;
     1807
     1808    if (id.compare("all") == 0) {
     1809        itr = _heightMaps.begin();
     1810        doAll = true;
     1811    } else {
     1812        itr = _heightMaps.find(id);
     1813    }
     1814    if (itr == _heightMaps.end()) {
     1815        ERROR("HeightMap not found: %s", id.c_str());
     1816        return;
     1817    }
     1818
     1819    do {
     1820        itr->second->setContourVisibility(state);
     1821    } while (doAll && ++itr != _heightMaps.end());
     1822
     1823    _needsRedraw = true;
     1824}
     1825
     1826/**
     1827 * \brief Set the RGB height map isoline color for the specified DataSet
     1828 */
     1829void Renderer::setHeightMapContourEdgeColor(const DataSetId& id, float color[3])
     1830{
     1831    HeightMapHashmap::iterator itr;
     1832
     1833    bool doAll = false;
     1834
     1835    if (id.compare("all") == 0) {
     1836        itr = _heightMaps.begin();
     1837        doAll = true;
     1838    } else {
     1839        itr = _heightMaps.find(id);
     1840    }
     1841    if (itr == _heightMaps.end()) {
     1842        ERROR("HeightMap not found: %s", id.c_str());
     1843        return;
     1844    }
     1845
     1846    do {
     1847        itr->second->setContourEdgeColor(color);
     1848    } while (doAll && ++itr != _heightMaps.end());
     1849
     1850    _needsRedraw = true;
     1851}
     1852
     1853/**
     1854 * \brief Set the height map isoline width for the specified DataSet (may be a no-op)
     1855 *
     1856 * If the OpenGL implementation/hardware does not support wide lines,
     1857 * this function may not have an effect.
     1858 */
     1859void Renderer::setHeightMapContourEdgeWidth(const DataSetId& id, float edgeWidth)
     1860{
     1861    HeightMapHashmap::iterator itr;
     1862
     1863    bool doAll = false;
     1864
     1865    if (id.compare("all") == 0) {
     1866        itr = _heightMaps.begin();
     1867        doAll = true;
     1868    } else {
     1869        itr = _heightMaps.find(id);
     1870    }
     1871    if (itr == _heightMaps.end()) {
     1872        ERROR("HeightMap not found: %s", id.c_str());
     1873        return;
     1874    }
     1875
     1876    do {
     1877        itr->second->setContourEdgeWidth(edgeWidth);
     1878    } while (doAll && ++itr != _heightMaps.end());
     1879
     1880    _needsRedraw = true;
     1881}
     1882
     1883/**
     1884 * \brief Turn height map lighting on/off for the specified DataSet
     1885 */
     1886void Renderer::setHeightMapLighting(const DataSetId& id, bool state)
     1887{
     1888    HeightMapHashmap::iterator itr;
     1889
     1890    bool doAll = false;
     1891
     1892    if (id.compare("all") == 0) {
     1893        itr = _heightMaps.begin();
     1894        doAll = true;
     1895    } else {
     1896        itr = _heightMaps.find(id);
     1897    }
     1898    if (itr == _heightMaps.end()) {
     1899        ERROR("HeightMap not found: %s", id.c_str());
     1900        return;
     1901    }
     1902
     1903    do {
     1904        itr->second->setLighting(state);
     1905    } while (doAll && ++itr != _heightMaps.end());
     1906    _needsRedraw = true;
     1907}
     1908
     1909/**
    13251910 * \brief Create a new PolyData and associate it with the named DataSet
    13261911 */
     
    13551940        polyData->setDataSet(ds);
    13561941
    1357         _renderer->AddActor(polyData->getActor());
     1942        _renderer->AddViewProp(polyData->getActor());
    13581943    } while (doAll && ++itr != _dataSets.end());
    13591944
     
    16012186void Renderer::setWindowSize(int width, int height)
    16022187{
     2188    // FIXME: Fix up panning on aspect change
     2189#ifdef notdef
     2190    if (_cameraPan[0] != 0.0) {
     2191        _cameraPan[0] *= ((double)_windowWidth / width);
     2192    }
     2193    if (_cameraPan[1] != 0.0) {
     2194        _cameraPan[1] *= ((double)_windowHeight / height);
     2195    }
     2196#endif
    16032197    _windowWidth = width;
    16042198    _windowHeight = height;
     
    16762270void Renderer::setCameraOrientation(double quat[4])
    16772271{
     2272    if (_cameraMode == IMAGE)
     2273        return;
    16782274    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    16792275    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     
    17132309        panCamera(panx, pany, true);
    17142310    }
     2311    _renderer->ResetCameraClippingRange();
    17152312    printCameraInfo(camera);
    17162313    _needsRedraw = true;
     
    19052502                              focalDepth,
    19062503                              oldPickPoint);
    1907  
     2504
    19082505        // Camera motion is reversed
    19092506        motionVector[0] = oldPickPoint[0] - newPickPoint[0];
     
    21762773                           const double *bounds1, const double *bounds2)
    21772774{
     2775    assert(boundsDest != NULL);
     2776    assert(bounds1 != NULL);
     2777    if (bounds2 == NULL) {
     2778        WARN("NULL bounds2 array");
     2779        return;
     2780    }
    21782781    for (int i = 0; i < 6; i++) {
    21792782        if (i % 2 == 0)
     
    22062809    for (Contour2DHashmap::iterator itr = _contours.begin();
    22072810             itr != _contours.end(); ++itr) {
     2811        if (!onlyVisible || itr->second->getVisibility())
     2812            mergeBounds(bounds, bounds, itr->second->getActor()->GetBounds());
     2813    }
     2814    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     2815             itr != _heightMaps.end(); ++itr) {
    22082816        if (!onlyVisible || itr->second->getVisibility())
    22092817            mergeBounds(bounds, bounds, itr->second->getActor()->GetBounds());
     
    22232831        }
    22242832    }
     2833    TRACE("Bounds: %g %g %g %g %g %g",
     2834          bounds[0],
     2835          bounds[1],
     2836          bounds[2],
     2837          bounds[3],
     2838          bounds[4],
     2839          bounds[5]);
    22252840}
    22262841
     
    22582873        }
    22592874    }
     2875    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     2876         itr != _heightMaps.end(); ++itr) {
     2877        vtkLookupTable *lut = itr->second->getLookupTable();
     2878        if (lut) {
     2879            if (useCumulative) {
     2880                lut->SetRange(_cumulativeDataRange);
     2881            } else {
     2882                double range[2];
     2883                if (itr->second->getDataSet()) {
     2884                    itr->second->getDataSet()->getDataRange(range);
     2885                    lut->SetRange(range);
     2886                }
     2887            }
     2888        }
     2889        // Only need to update contour range if using evenly spaced contours
     2890        if (itr->second->getContourList().empty()) {
     2891            if (useCumulative) {
     2892                itr->second->setContours(itr->second->getNumContours(), _cumulativeDataRange);
     2893            } else {
     2894                itr->second->setContours(itr->second->getNumContours());
     2895            }
     2896        }
     2897    }
    22602898}
    22612899
     
    22862924}
    22872925
    2288 #ifdef notdef
    2289 void Renderer::setPerspectiveCameraByBounds(double bounds[6])
    2290 {
    2291     vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    2292     camera->ParallelProjectionOff();
    2293     camera->Reset();
    2294 }
     2926/**
     2927 * \brief Initialize the camera zoom region to include the bounding volume given
     2928 */
     2929void Renderer::initCamera()
     2930{
     2931#ifdef WANT_TRACE
     2932    switch (_cameraMode) {
     2933    case IMAGE:
     2934        TRACE("Image camera");
     2935        break;
     2936    case ORTHO:
     2937        TRACE("Ortho camera");
     2938        break;
     2939    case PERSPECTIVE:
     2940        TRACE("Perspective camera");
     2941        break;
     2942    default:
     2943        TRACE("Unknown camera mode");
     2944    }
    22952945#endif
    2296 
    2297 /**
    2298  * \brief Initialize the camera zoom region to include the bounding volume given
    2299  */
    2300 void Renderer::initCamera()
    2301 {
    23022946    double bounds[6];
    23032947    collectBounds(bounds, false);
     
    23102954    _cameraZoomRatio = 1;
    23112955
    2312     if (_cameraMode == IMAGE) {
     2956    switch (_cameraMode) {
     2957    case IMAGE:
    23132958        _renderer->ResetCamera(bounds);
    23142959        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    23152960                            _imgWorldDims[0], _imgWorldDims[1]);
    23162961        resetAxes();
    2317     } else if (_cameraMode == ORTHO) {
     2962        break;
     2963    case ORTHO:
    23182964        _renderer->GetActiveCamera()->ParallelProjectionOn();
    23192965        resetAxes();
    23202966        _renderer->ResetCamera(bounds);
    23212967        computeScreenWorldCoords();
    2322     } else if (_cameraMode == PERSPECTIVE) {
     2968        break;
     2969    case PERSPECTIVE:
    23232970        _renderer->GetActiveCamera()->ParallelProjectionOff();
    23242971        resetAxes();
    23252972        _renderer->ResetCamera(bounds);
    23262973        computeScreenWorldCoords();
    2327     }
     2974        break;
     2975    default:
     2976        ERROR("Unknown camera mode");
     2977    }
     2978#ifdef WANT_TRACE
     2979    printCameraInfo(_renderer->GetActiveCamera());
     2980#endif
    23282981}
    23292982
     
    23703023    if (id.compare("all") == 0 || getContour2D(id) != NULL)
    23713024        setContourOpacity(id, opacity);
     3025    if (id.compare("all") == 0 || getHeightMap(id) != NULL)
     3026        setHeightMapOpacity(id, opacity);
    23723027    if (id.compare("all") == 0 || getPolyData(id) != NULL)
    23733028        setPolyDataOpacity(id, opacity);
     
    24023057    if (id.compare("all") == 0 || getContour2D(id) != NULL)
    24033058        setContourVisibility(id, state);
     3059    if (id.compare("all") == 0 || getHeightMap(id) != NULL)
     3060        setHeightMapVisibility(id, state);
    24043061    if (id.compare("all") == 0 || getPolyData(id) != NULL)
    24053062        setPolyDataVisibility(id, state);
     
    24223079            for (Contour2DHashmap::iterator itr = _contours.begin();
    24233080                 itr != _contours.end(); ++itr) {
     3081                itr->second->setClippingPlanes(_clippingPlanes);
     3082            }
     3083            for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     3084                 itr != _heightMaps.end(); ++itr) {
    24243085                itr->second->setClippingPlanes(_clippingPlanes);
    24253086            }
     
    24373098                itr->second->setClippingPlanes(NULL);
    24383099            }
     3100            for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     3101                 itr != _heightMaps.end(); ++itr) {
     3102                itr->second->setClippingPlanes(NULL);
     3103            }
    24393104            for (PolyDataHashmap::iterator itr = _polyDatas.begin();
    24403105                 itr != _polyDatas.end(); ++itr) {
     
    24663131void Renderer::getRenderedFrame(vtkUnsignedCharArray *imgData)
    24673132{
     3133#ifdef RENDER_TARGA
     3134    _renderWindow->MakeCurrent();
     3135    // Must clear previous errors first.
     3136    while (glGetError() != GL_NO_ERROR){
     3137        ;
     3138    }
     3139    int bytesPerPixel = TARGA_BYTES_PER_PIXEL;
     3140    int size = bytesPerPixel * _windowWidth * _windowHeight;
     3141
     3142    if (imgData->GetMaxId() + 1 != size)
     3143    {
     3144        imgData->SetNumberOfComponents(bytesPerPixel);
     3145        imgData->SetNumberOfValues(size);
     3146    }
     3147    glDisable(GL_TEXTURE_2D);
     3148    if (_renderWindow->GetDoubleBuffer()) {
     3149        glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_renderWindow)->GetBackLeftBuffer()));
     3150    } else {
     3151        glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_renderWindow)->GetFrontLeftBuffer()));
     3152    }
     3153    glPixelStorei(GL_PACK_ALIGNMENT, 1);
     3154#ifdef WANT_TRACE
     3155    struct timeval t1, t2;
     3156    glFinish();
     3157    gettimeofday(&t1, 0);
     3158#endif
     3159    if (bytesPerPixel == 4) {
     3160        glReadPixels(0, 0, _windowWidth, _windowHeight, GL_BGRA,
     3161                     GL_UNSIGNED_BYTE, imgData->GetPointer(0));
     3162    } else {
     3163        glReadPixels(0, 0, _windowWidth, _windowHeight, GL_BGR,
     3164                     GL_UNSIGNED_BYTE, imgData->GetPointer(0));
     3165    }
     3166#ifdef WANT_TRACE
     3167    gettimeofday(&t2, 0);
     3168    static unsigned int numFrames = 0;
     3169    static double accum = 0;
     3170    numFrames++;
     3171    accum += ELAPSED_TIME(t1, t2);
     3172#endif
     3173    TRACE("Readback time: %g ms", ELAPSED_TIME(t1, t2));
     3174    TRACE("Readback avg: %g ms", accum/numFrames);
     3175    if (glGetError() != GL_NO_ERROR) {
     3176        ERROR("glReadPixels");
     3177    }
     3178#else
    24683179    _renderWindow->GetPixelData(0, 0, _windowWidth-1, _windowHeight-1,
    24693180                                !_renderWindow->GetDoubleBuffer(), imgData);
     3181#endif
    24703182    TRACE("Image data size: %d", imgData->GetSize());
    24713183}
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.h

    r2230 r2260  
    3030#include "RpPseudoColor.h"
    3131#include "RpContour2D.h"
     32#include "RpHeightMap.h"
    3233#include "RpPolyData.h"
     34#include "Trace.h"
     35
     36// Controls if TGA format is sent to client
     37//#define RENDER_TARGA
     38#define TARGA_BYTES_PER_PIXEL 3
    3339
    3440namespace Rappture {
     
    7076    typedef std::tr1::unordered_map<DataSetId, PseudoColor *> PseudoColorHashmap;
    7177    typedef std::tr1::unordered_map<DataSetId, Contour2D *> Contour2DHashmap;
     78    typedef std::tr1::unordered_map<DataSetId, HeightMap *> HeightMapHashmap;
    7279    typedef std::tr1::unordered_map<DataSetId, PolyData *> PolyDataHashmap;
    7380
     
    217224
    218225    void setContourLighting(const DataSetId& id, bool state);
     226
     227    // Height maps
     228
     229    void addHeightMap(const DataSetId& id);
     230
     231    void deleteHeightMap(const DataSetId& id);
     232
     233    HeightMap *getHeightMap(const DataSetId& id);
     234
     235    void setHeightMapVolumeSlice(const DataSetId& id, HeightMap::Axis axis, double ratio);
     236
     237    void setHeightMapHeightScale(const DataSetId& id, double scale);
     238
     239    void setHeightMapColorMap(const DataSetId& id, const ColorMapId& colorMapId);
     240
     241    vtkLookupTable *getHeightMapColorMap(const DataSetId& id);
     242
     243    void setHeightMapContours(const DataSetId& id, int numContours);
     244
     245    void setHeightMapContourList(const DataSetId& id, const std::vector<double>& contours);
     246
     247    void setHeightMapOpacity(const DataSetId& id, double opacity);
     248
     249    void setHeightMapVisibility(const DataSetId& id, bool state);
     250
     251    void setHeightMapEdgeVisibility(const DataSetId& id, bool state);
     252
     253    void setHeightMapEdgeColor(const DataSetId& id, float color[3]);
     254
     255    void setHeightMapEdgeWidth(const DataSetId& id, float edgeWidth);
     256
     257    void setHeightMapContourVisibility(const DataSetId& id, bool state);
     258
     259    void setHeightMapContourEdgeColor(const DataSetId& id, float color[3]);
     260
     261    void setHeightMapContourEdgeWidth(const DataSetId& id, float edgeWidth);
     262
     263    void setHeightMapLighting(const DataSetId& id, bool state);
    219264
    220265    // Meshes
     
    291336    PseudoColorHashmap _pseudoColors;
    292337    Contour2DHashmap _contours;
     338    HeightMapHashmap _heightMaps;
    293339    PolyDataHashmap _polyDatas;
    294340
  • trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2230 r2260  
    938938
    939939static int
     940HeightMapAddContourListOp(ClientData clientData, Tcl_Interp *interp, int objc,
     941                          Tcl_Obj *const *objv)
     942{
     943    std::vector<double> contourList;
     944
     945    int clistc;
     946    Tcl_Obj **clistv;
     947
     948    if (Tcl_ListObjGetElements(interp, objv[3], &clistc, &clistv) != TCL_OK) {
     949        return TCL_ERROR;
     950    }
     951
     952    for (int i = 0; i < clistc; i++) {
     953        double val;
     954        if (Tcl_GetDoubleFromObj(interp, clistv[i], &val) != TCL_OK) {
     955            return TCL_ERROR;
     956        }
     957        contourList.push_back(val);
     958    }
     959
     960    if (objc == 5) {
     961        const char *name = Tcl_GetString(objv[4]);
     962        g_renderer->addHeightMap(name);
     963        g_renderer->setHeightMapContourList(name, contourList);
     964    } else {
     965        g_renderer->addHeightMap("all");
     966        g_renderer->setHeightMapContourList("all", contourList);
     967    }
     968    return TCL_OK;
     969}
     970
     971static int
     972HeightMapAddNumContoursOp(ClientData clientData, Tcl_Interp *interp, int objc,
     973                          Tcl_Obj *const *objv)
     974{
     975    int numContours;
     976    if (Tcl_GetIntFromObj(interp, objv[3], &numContours) != TCL_OK) {
     977        return TCL_ERROR;
     978    }
     979    if (objc == 5) {
     980        const char *name = Tcl_GetString(objv[4]);
     981        g_renderer->addHeightMap(name);
     982        g_renderer->setHeightMapContours(name, numContours);
     983    } else {
     984        g_renderer->addHeightMap("all");
     985        g_renderer->setHeightMapContours("all", numContours);
     986    }
     987    return TCL_OK;
     988}
     989
     990static Rappture::CmdSpec heightmapAddOps[] = {
     991    {"contourlist", 1, HeightMapAddContourListOp, 4, 5, "contourList ?dataSetName?"},
     992    {"numcontours", 1, HeightMapAddNumContoursOp, 4, 5, "numContours ?dataSetName?"}
     993};
     994static int nHeightmapAddOps = NumCmdSpecs(heightmapAddOps);
     995
     996static int
     997HeightMapAddOp(ClientData clientData, Tcl_Interp *interp, int objc,
     998               Tcl_Obj *const *objv)
     999{
     1000    Tcl_ObjCmdProc *proc;
     1001
     1002    proc = Rappture::GetOpFromObj(interp, nHeightmapAddOps, heightmapAddOps,
     1003                                  Rappture::CMDSPEC_ARG2, objc, objv, 0);
     1004    if (proc == NULL) {
     1005        return TCL_ERROR;
     1006    }
     1007    return (*proc) (clientData, interp, objc, objv);
     1008}
     1009
     1010static int
     1011HeightMapColorMapOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1012                    Tcl_Obj *const *objv)
     1013{
     1014    const char *colorMapName = Tcl_GetString(objv[2]);
     1015    if (objc == 4) {
     1016        const char *dataSetName = Tcl_GetString(objv[3]);
     1017        g_renderer->setHeightMapColorMap(dataSetName, colorMapName);
     1018    } else {
     1019        g_renderer->setHeightMapColorMap("all", colorMapName);
     1020    }
     1021    return TCL_OK;
     1022}
     1023
     1024static int
     1025HeightMapContourLineColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1026                            Tcl_Obj *const *objv)
     1027{
     1028    float color[3];
     1029    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     1030        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     1031        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     1032        return TCL_ERROR;
     1033    }
     1034    if (objc == 6) {
     1035        const char *name = Tcl_GetString(objv[5]);
     1036        g_renderer->setHeightMapContourEdgeColor(name, color);
     1037    } else {
     1038        g_renderer->setHeightMapContourEdgeColor("all", color);
     1039    }
     1040    return TCL_OK;
     1041}
     1042
     1043static int
     1044HeightMapContourLineWidthOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1045                            Tcl_Obj *const *objv)
     1046{
     1047    float width;
     1048    if (GetFloatFromObj(interp, objv[2], &width) != TCL_OK) {
     1049        return TCL_ERROR;
     1050    }
     1051    if (objc == 4) {
     1052        const char *name = Tcl_GetString(objv[3]);
     1053        g_renderer->setHeightMapContourEdgeWidth(name, width);
     1054    } else {
     1055        g_renderer->setHeightMapContourEdgeWidth("all", width);
     1056    }
     1057    return TCL_OK;
     1058}
     1059
     1060static int
     1061HeightMapContourVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1062                          Tcl_Obj *const *objv)
     1063{
     1064    bool state;
     1065    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1066        return TCL_ERROR;
     1067    }
     1068    if (objc == 4) {
     1069        const char *name = Tcl_GetString(objv[3]);
     1070        g_renderer->setHeightMapContourVisibility(name, state);
     1071    } else {
     1072        g_renderer->setHeightMapContourVisibility("all", state);
     1073    }
     1074    return TCL_OK;
     1075}
     1076
     1077static int
     1078HeightMapDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1079                  Tcl_Obj *const *objv)
     1080{
     1081    if (objc == 3) {
     1082        const char *name = Tcl_GetString(objv[2]);
     1083        g_renderer->deleteHeightMap(name);
     1084    } else {
     1085        g_renderer->deleteHeightMap("all");
     1086    }
     1087    return TCL_OK;
     1088}
     1089
     1090static int
     1091HeightMapEdgeVisibilityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1092                          Tcl_Obj *const *objv)
     1093{
     1094    bool state;
     1095    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1096        return TCL_ERROR;
     1097    }
     1098    if (objc == 4) {
     1099        const char *name = Tcl_GetString(objv[3]);
     1100        g_renderer->setHeightMapEdgeVisibility(name, state);
     1101    } else {
     1102        g_renderer->setHeightMapEdgeVisibility("all", state);
     1103    }
     1104    return TCL_OK;
     1105}
     1106
     1107static int
     1108HeightMapHeightScaleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1109                       Tcl_Obj *const *objv)
     1110{
     1111    double scale;
     1112    if (Tcl_GetDoubleFromObj(interp, objv[2], &scale) != TCL_OK) {
     1113        return TCL_ERROR;
     1114    }
     1115    if (objc == 4) {
     1116        const char *name = Tcl_GetString(objv[3]);
     1117        g_renderer->setHeightMapHeightScale(name, scale);
     1118    } else {
     1119        g_renderer->setHeightMapHeightScale("all", scale);
     1120    }
     1121    return TCL_OK;
     1122}
     1123
     1124static int
     1125HeightMapLightingOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1126                    Tcl_Obj *const *objv)
     1127{
     1128    bool state;
     1129    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1130        return TCL_ERROR;
     1131    }
     1132    if (objc == 4) {
     1133        const char *name = Tcl_GetString(objv[3]);
     1134        g_renderer->setHeightMapLighting(name, state);
     1135    } else {
     1136        g_renderer->setHeightMapLighting("all", state);
     1137    }
     1138    return TCL_OK;
     1139}
     1140
     1141static int
     1142HeightMapLineColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1143                     Tcl_Obj *const *objv)
     1144{
     1145    float color[3];
     1146    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     1147        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     1148        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     1149        return TCL_ERROR;
     1150    }
     1151    if (objc == 6) {
     1152        const char *name = Tcl_GetString(objv[5]);
     1153        g_renderer->setHeightMapEdgeColor(name, color);
     1154    } else {
     1155        g_renderer->setHeightMapEdgeColor("all", color);
     1156    }
     1157    return TCL_OK;
     1158}
     1159
     1160static int
     1161HeightMapLineWidthOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1162                     Tcl_Obj *const *objv)
     1163{
     1164    float width;
     1165    if (GetFloatFromObj(interp, objv[2], &width) != TCL_OK) {
     1166        return TCL_ERROR;
     1167    }
     1168    if (objc == 4) {
     1169        const char *name = Tcl_GetString(objv[3]);
     1170        g_renderer->setHeightMapEdgeWidth(name, width);
     1171    } else {
     1172        g_renderer->setHeightMapEdgeWidth("all", width);
     1173    }
     1174    return TCL_OK;
     1175}
     1176
     1177static int
     1178HeightMapOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1179                   Tcl_Obj *const *objv)
     1180{
     1181    double opacity;
     1182    if (Tcl_GetDoubleFromObj(interp, objv[2], &opacity) != TCL_OK) {
     1183        return TCL_ERROR;
     1184    }
     1185    if (objc == 4) {
     1186        const char *name = Tcl_GetString(objv[3]);
     1187        g_renderer->setHeightMapOpacity(name, opacity);
     1188    } else {
     1189        g_renderer->setHeightMapOpacity("all", opacity);
     1190    }
     1191    return TCL_OK;
     1192}
     1193
     1194static int
     1195HeightMapVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1196                   Tcl_Obj *const *objv)
     1197{
     1198    bool state;
     1199    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1200        return TCL_ERROR;
     1201    }
     1202    if (objc == 4) {
     1203        const char *name = Tcl_GetString(objv[3]);
     1204        g_renderer->setHeightMapVisibility(name, state);
     1205    } else {
     1206        g_renderer->setHeightMapVisibility("all", state);
     1207    }
     1208    return TCL_OK;
     1209}
     1210
     1211static int
     1212HeightMapVolumeSliceOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1213                       Tcl_Obj *const *objv)
     1214{
     1215    double ratio;
     1216    if (Tcl_GetDoubleFromObj(interp, objv[3], &ratio) != TCL_OK) {
     1217        return TCL_ERROR;
     1218    }
     1219    const char *string = Tcl_GetString(objv[2]);
     1220    char c = string[0];
     1221    HeightMap::Axis axis;
     1222    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     1223        axis = HeightMap::X_AXIS;
     1224    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     1225        axis = HeightMap::Y_AXIS;
     1226    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     1227        axis = HeightMap::Z_AXIS;
     1228    } else {
     1229        Tcl_AppendResult(interp, "bad axis option \"", string,
     1230                         "\": should be axisName ratio", (char*)NULL);
     1231        return TCL_ERROR;
     1232    }
     1233    if (objc == 5) {
     1234        const char *name = Tcl_GetString(objv[4]);
     1235        g_renderer->setHeightMapVolumeSlice(name, axis, ratio);
     1236    } else {
     1237        g_renderer->setHeightMapVolumeSlice("all", axis, ratio);
     1238    }
     1239    return TCL_OK;
     1240}
     1241
     1242static Rappture::CmdSpec heightmapOps[] = {
     1243    {"add",          1, HeightMapAddOp, 4, 5, "oper value ?dataSetName?"},
     1244    {"colormap",     1, HeightMapColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
     1245    {"delete",       1, HeightMapDeleteOp, 2, 3, "?dataSetName?"},
     1246    {"edges",        1, HeightMapEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
     1247    {"heightscale",  1, HeightMapHeightScaleOp, 3, 4, "value ?dataSetName?"},
     1248    {"isolinecolor", 8, HeightMapContourLineColorOp, 5, 6, "r g b ?dataSetName?"},
     1249    {"isolines",     8, HeightMapContourVisibleOp, 3, 4, "bool ?dataSetName?"},
     1250    {"isolinewidth", 8, HeightMapContourLineWidthOp, 3, 4, "width ?dataSetName?"},
     1251    {"lighting",     3, HeightMapLightingOp, 3, 4, "bool ?dataSetName?"},
     1252    {"linecolor",    5, HeightMapLineColorOp, 5, 6, "r g b ?dataSetName?"},
     1253    {"linewidth",    5, HeightMapLineWidthOp, 3, 4, "width ?dataSetName?"},
     1254    {"opacity",      1, HeightMapOpacityOp, 3, 4, "value ?dataSetName?"},
     1255    {"visible",      2, HeightMapVisibleOp, 3, 4, "bool ?dataSetName?"},
     1256    {"volumeslice",  2, HeightMapVolumeSliceOp, 4, 5, "axis ratio ?dataSetName?"}
     1257};
     1258static int nHeightmapOps = NumCmdSpecs(heightmapOps);
     1259
     1260static int
     1261HeightMapCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     1262             Tcl_Obj *const *objv)
     1263{
     1264    Tcl_ObjCmdProc *proc;
     1265
     1266    proc = Rappture::GetOpFromObj(interp, nHeightmapOps, heightmapOps,
     1267                                  Rappture::CMDSPEC_ARG1, objc, objv, 0);
     1268    if (proc == NULL) {
     1269        return TCL_ERROR;
     1270    }
     1271    return (*proc) (clientData, interp, objc, objv);
     1272}
     1273
     1274static int
    9401275LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    9411276          Tcl_Obj *const *objv)
     
    9741309
    9751310#ifdef DEBUG
    976     writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height);
     1311    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
     1312                 TARGA_BYTES_PER_PIXEL);
    9771313#else
    9781314    char cmd[256];
    9791315    snprintf(cmd, sizeof(cmd), "nv>legend %s", name);
     1316#ifdef RENDER_TARGA
     1317    writeTGA(g_fdOut, cmd, imgData->GetPointer(0), width, height,
     1318                 TARGA_BYTES_PER_PIXEL);
     1319#else
    9801320    writePPM(g_fdOut, cmd, imgData->GetPointer(0), width, height);
     1321#endif
    9811322#endif
    9821323
     
    14971838    Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   NULL, NULL);
    14981839    Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     NULL, NULL);
     1840    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    14991841    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    15001842    Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    NULL, NULL);
  • trunk/packages/vizservers/vtkvis/TGAWriter.cpp

    r2100 r2260  
    2121 * \brief Writes image command + data to supplied file descriptor.
    2222 *
    23  * The image data must be supplied in BGR order with bottom to
     23 * The image data must be supplied in BGR(A) order with bottom to
    2424 * top scanline ordering.
     25 *
     26 * \param[in] fd File descriptor that will be written to
     27 * \param[in] cmdName Command name to send (byte length will be appended)
     28 * \param[in] data Image data
     29 * \param[in] width Width of image in pixels
     30 * \param[in] height Height of image in pixels
     31 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
    2532 */
    2633void
    27 Rappture::VtkVis::writeTGA(int fd, const char *cmdName, const unsigned char *data,
    28                            int width, int height)
     34Rappture::VtkVis::writeTGA(int fd, const char *cmdName,
     35                           const unsigned char *data,
     36                           int width, int height,
     37                           int bytesPerPixel)
    2938{
    3039    TRACE("(%dx%d)\n", width, height);
     
    3948    header[14] = (char)height;
    4049    header[15] = (char)(height >> 8);
    41     header[16] = (char)24; // bits per pixel
     50    header[16] = (char)(bytesPerPixel*8); // bits per pixel
    4251
    43     size_t dataLength = width * height * 3;
     52    size_t dataLength = width * height * bytesPerPixel;
    4453
    4554    char command[200];
    46     snprintf(command, sizeof(command), "%simage -type image -bytes %lu\n", cmdName,
     55    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
    4756             (unsigned long)headerLength + dataLength);
    4857
     
    5968    iov[1].iov_base = header;
    6069    iov[1].iov_len = headerLength;
    61     // Image data **must be BGR!**
     70    // Image data **must be BGR(A)!**
    6271    iov[2].iov_base = const_cast<unsigned char *>(data);
    6372    iov[2].iov_len = dataLength;
     
    7483 * \brief Writes image data to supplied file name
    7584 *
    76  * The image data must be supplied in BGR order with bottom to
    77  * top scanline ordering.
     85 * The image data must be supplied with bottom to top
     86 * scanline ordering.  Source data should have BGR(A)
     87 * ordering, unless srcIsRGB is true, in which case
     88 * the source data will be converted from RGB(A) to
     89 * BGR(A).  Note that this is slow and it is better
     90 * to pass in BGR(A) data.
     91 *
     92 * \param[in] filename Path to file that will be written
     93 * \param[in] imgData Image data
     94 * \param[in] width Width of image in pixels
     95 * \param[in] height Height of image in pixels
     96 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
     97 * \param[in] srcIsRGB If true source data will be re-ordered
    7898 */
    7999void
    80 Rappture::VtkVis::writeTGAFile(const char *filename, const unsigned char *imgData,
    81                                int width, int height)
     100Rappture::VtkVis::writeTGAFile(const char *filename,
     101                               const unsigned char *imgData,
     102                               int width, int height,
     103                               int bytesPerPixel,
     104                               bool srcIsRGB)
    82105{
    83106    TRACE("%s (%dx%d)\n", filename, width, height);
     
    91114    header[14] = (char)height;
    92115    header[15] = (char)(height >> 8);
    93     header[16] = (char)24; // bits per pixel
     116    header[16] = (char)(bytesPerPixel*8); // bits per pixel
    94117
    95118    outfile.write(header, sizeof(header));
    96119
    97     // RGB -> BGR
    98     for (int i = 0; i < width * height; i++) {
    99         outfile << imgData[i*3+2]
    100                 << imgData[i*3+1]
    101                 << imgData[i*3];
     120    if (!srcIsRGB) {
     121        outfile.write((const char *)imgData, width * height * bytesPerPixel);
     122    } else {
     123        // RGB(A) -> BGR(A)
     124        for (int i = 0; i < width * height; i++) {
     125            outfile << imgData[i*bytesPerPixel+2]
     126                    << imgData[i*bytesPerPixel+1]
     127                    << imgData[i*bytesPerPixel];
     128            if (bytesPerPixel == 4) {
     129                outfile << imgData[i*bytesPerPixel+3];
     130            }
     131        }
    102132    }
    103133
  • trunk/packages/vizservers/vtkvis/TGAWriter.h

    r2100 r2260  
    1313
    1414extern
    15 void writeTGA(int fd, const char *cmdName, const unsigned char *data, int width, int height);
     15void writeTGA(int fd, const char *cmdName, const unsigned char *data,
     16              int width, int height, int bytesPerPixel);
    1617
    1718extern
    18 void writeTGAFile(const char *filename, const unsigned char *data, int width, int height);
     19void writeTGAFile(const char *filename, const unsigned char *data,
     20                  int width, int height, int bytesPerPixel,
     21                  bool srcIsRGB = false);
    1922
    2023}
  • trunk/packages/vizservers/vtkvis/protocol.txt

    r2230 r2260  
    8484contour2d visible <bool> <?datasetName?>
    8585
     86heightmap add numcontours <n> <?dataSetName?>
     87          Generate evenly spaced contours including range endpoints.  See also
     88          'dataset maprange' command.
     89heightmap add contourlist <list> <?dataSetName?>
     90          list = {isoval1 isoval2 isoval3...}
     91heightmap colormap <colorMapName> <?dataSetName?>
     92heightmap delete <?dataSetName?>
     93heightmap edges <bool> <?dataSetName?>
     94heightmap heightscale <value> <?dataSetName?>
     95heightmap isolinecolor <r> <g> <b> <?dataSetName?>
     96heightmap isolines <bool> <?dataSetName?>
     97heightmap isolinewidth <width> <?dataSetName?>
     98heightmap lighting <bool> <?dataSetName?>
     99heightmap linecolor <r> <g> <b> <?dataSetName?>
     100heightmap linewidth <width> <?dataSetName?>
     101heightmap opacity <value> <?dataSetName?>
     102heightmap visible <bool> <?dataSetName?>
     103heightmap volumeslice axis ratio <?dataSetName?>
     104          For 3D data, select a slice along a principle axis of the volume. The
     105          ratio is [0,1]
     106
    86107polydata add <?datasetName?>
    87108polydata color <r> <g> <b> <?datasetName?>
Note: See TracChangeset for help on using the changeset viewer.