vtkOSPRayVolumeMapperNode.cxx 7.79 KB
Newer Older
1
/*=========================================================================
2

3
4
   Program:   Visualization Toolkit
   Module:    vtkOSPRayVolumeMapperNode.cxx
5

6
7
8
   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
   All rights reserved.
   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9

10
11
12
      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.
13

14
 =========================================================================*/
15
16
#include "vtkOSPRayVolumeMapperNode.h"

17
#include "vtkAbstractVolumeMapper.h"
18
#include "vtkCellData.h"
19
#include "vtkColorTransferFunction.h"
20
21
22
#include "vtkDataArray.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
23
#include "vtkOSPRayRendererNode.h"
24
25
26
27
#include "vtkPiecewiseFunction.h"
#include "vtkPointData.h"
#include "vtkVolume.h"
#include "vtkVolumeNode.h"
28
#include "vtkVolumeProperty.h"
29

30
31
#include <algorithm>

32
33
34
35
36
37
38
39
#include "ospray/ospray.h"

//============================================================================
vtkStandardNewMacro(vtkOSPRayVolumeMapperNode);

//----------------------------------------------------------------------------
vtkOSPRayVolumeMapperNode::vtkOSPRayVolumeMapperNode()
{
40
  this->SamplingRate=0.0;
41
  this->NumColors = 128;
42
43
  this->OSPRayVolume = NULL;
  this->TransferFunction = NULL;
44
45
46
47
48
}

//----------------------------------------------------------------------------
vtkOSPRayVolumeMapperNode::~vtkOSPRayVolumeMapperNode()
{
49
  delete this->OSPRayVolume;
50
  ospRelease(this->TransferFunction);
51
52
53
54
55
56
57
58
}

//----------------------------------------------------------------------------
void vtkOSPRayVolumeMapperNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

59
//----------------------------------------------------------------------------
60
61
62
63
64
65
void vtkOSPRayVolumeMapperNode::Render(bool prepass)
{
  if (prepass)
    {
    vtkVolumeNode* volNode = vtkVolumeNode::SafeDownCast(this->Parent);
    vtkVolume* vol = vtkVolume::SafeDownCast(volNode->GetRenderable());
66
    if (vol->GetVisibility() == false)
67
68
69
      {
      return;
      }
70
    vtkAbstractVolumeMapper* mapper = vtkAbstractVolumeMapper::SafeDownCast(this->GetRenderable());
71
    if (!vol->GetProperty())
72
      {
73
      // this is OK, happens in paraview client side for instance
74
75
76
77
      return;
      }

    vtkOSPRayRendererNode *orn =
78
79
      static_cast<vtkOSPRayRendererNode *>(
        this->GetFirstAncestorOfType("vtkOSPRayRendererNode"));
80

81
    osp::Model* OSPRayModel = orn->GetOModel();
82
83
84
85

    // make sure that we have scalar input and update the scalar input
    if ( mapper->GetDataSetInput() == NULL )
      {
86
      vtkErrorMacro("VolumeMapper had no input!");
87
88
      return;
      }
89
90
    mapper->GetInputAlgorithm()->UpdateInformation();
    mapper->GetInputAlgorithm()->Update();
91
92
93
94

    vtkImageData *data = vtkImageData::SafeDownCast(mapper->GetDataSetInput());
    if (!data)
      {
95
      vtkErrorMacro("VolumeMapper's Input has no data!");
96
97
      return;
      }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    vtkDataArray *sa = mapper->GetDataSetInput()->GetPointData()->GetScalars();
    bool onPoints = true;
    if (!sa)
      {
      onPoints = false;
      sa = mapper->GetDataSetInput()->GetCellData()->GetScalars();
      }
    if (!sa)
      {
      vtkErrorMacro("VolumeMapper's Input has no scalar array!");
      return;
      }
    int ScalarDataType = sa->GetDataType();
    void* ScalarDataPointer = sa->GetVoidPointer(0);
112
113
    int dim[3];
    data->GetDimensions(dim);
114
115
116
117
118
119
    if (!onPoints)
      {
      dim[0] = dim[0]-1;
      dim[1] = dim[1]-1;
      dim[2] = dim[2]-1;
      }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

    std::string voxelType;
    if (ScalarDataType == VTK_FLOAT)
      {
      voxelType = "float";
      }
    else if (ScalarDataType == VTK_UNSIGNED_CHAR)
      {
      voxelType = "uchar";
      }
    else if (ScalarDataType == VTK_DOUBLE)
      {
      voxelType = "double";
      }
    else
      {
136
      vtkErrorMacro("ERROR: Unsupported data type for ospray volumes, current supported data types are: float, uchar, and double.");
137
138
139
      return;
      }

140
141
142
    if (!this->TransferFunction)
      {
      this->TransferFunction = ospNewTransferFunction("piecewise_linear");
143
144
      }

145
    // when input data is modified
Dave DeMarle's avatar
Dave DeMarle committed
146
147
    if (mapper->GetDataSetInput()->GetMTime() > this->BuildTime)
      {
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
      delete this->OSPRayVolume;
      this->OSPRayVolume = ospNewVolume("block_bricked_volume");

      //
      // Send Volumetric data to OSPRay
      //
      ospSet3i(this->OSPRayVolume, "dimensions", dim[0], dim[1], dim[2]);
      double origin[3];
      double scale[3];
      data->GetOrigin(origin);
      vol->GetScale(scale);
      double *bds = vol->GetBounds();
      origin[0] = bds[0];
      origin[1] = bds[2];
      origin[2] = bds[4];

      double spacing[3];
      data->GetSpacing(spacing);
      scale[0] = (bds[1]-bds[0])/double(dim[0]-1);
      scale[1] = (bds[3]-bds[2])/double(dim[1]-1);
      scale[2] = (bds[5]-bds[4])/double(dim[2]-1);

      ospSet3f(this->OSPRayVolume, "gridOrigin", origin[0], origin[1], origin[2]);
      ospSet3f(this->OSPRayVolume, "gridSpacing", scale[0], scale[1], scale[2]);
      ospSetString(this->OSPRayVolume, "voxelType", voxelType.c_str());

      osp::vec3i ll, uu;
      ll.x = 0, ll.y = 0, ll.z = 0;
      uu.x = dim[0], uu.y = dim[1], uu.z = dim[2];
      ospSetRegion(this->OSPRayVolume, ScalarDataPointer, ll, uu);

Dave DeMarle's avatar
Dave DeMarle committed
179
180
181
182
      ospSet2f(this->TransferFunction, "valueRange",
               data->GetScalarRange()[0], data->GetScalarRange()[1]);
      }

183
    // test for modifications to volume properties
184
    vtkVolumeProperty* volProperty = vol->GetProperty();
Dave DeMarle's avatar
Dave DeMarle committed
185
186
    if (vol->GetProperty()->GetMTime() > this->PropertyTime
        || mapper->GetDataSetInput()->GetMTime() > this->BuildTime)
187
      {
188
189
      vtkColorTransferFunction* colorTF =
        volProperty->GetRGBTransferFunction(0);
190
191
      vtkPiecewiseFunction *scalarTF = volProperty->GetScalarOpacity(0);

192
193
194
195
196
197
198
199
200
201
202
      this->TFVals.resize(this->NumColors*3);
      this->TFOVals.resize(this->NumColors);
      scalarTF->GetTable(data->GetScalarRange()[0],
                         data->GetScalarRange()[1],
                         this->NumColors,
                         &TFOVals[0]);
      colorTF->GetTable(data->GetScalarRange()[0],
                        data->GetScalarRange()[1],
                        this->NumColors,
                        &this->TFVals[0]);

203
204
205
      OSPData colorData = ospNewData(this->NumColors,
                                     OSP_FLOAT3,
                                     &this->TFVals[0]);
206
      ospSetData(this->TransferFunction, "colors", colorData);
207
208

      OSPData tfAlphaData = ospNewData(NumColors, OSP_FLOAT, &TFOVals[0]);
209
210
      ospSetData(this->TransferFunction, "opacities", tfAlphaData);

211
212
213
214
215
      ospSetObject(this->OSPRayVolume, "transferFunction",
                   this->TransferFunction);

      ospSet1i(this->OSPRayVolume, "gradientShadingEnabled",
               volProperty->GetShade());
216
217
218
      PropertyTime.Modified();
      ospRelease(colorData);
      ospRelease(tfAlphaData);
219
      }
220

221
    if (this->SamplingRate == 0.0f)  // 0 means automatic sampling rate
222
      {
223
      //automatically determine sampling rate
224
225
226
227
228
229
      int maxBound = std::max(dim[0],dim[1]);
      maxBound = std::max(maxBound,dim[2]);
      if (maxBound < 1000)
        {
        float s = 1000.0f - maxBound;
        s = (s/1000.0f*4.0f + 0.25f);
230
        ospSet1f(this->OSPRayVolume, "samplingRate", s);
231
232
233
        }
      else
        {
234
        ospSet1f(this->OSPRayVolume, "samplingRate", 0.25f);
235
236
237
238
        }
      }
    else
      {
239
      ospSet1f(this->OSPRayVolume, "samplingRate", this->SamplingRate);
240
      }
241
242
243
244
245

    this->RenderTime = volNode->GetMTime();
    this->BuildTime.Modified();

    ospCommit(this->TransferFunction);
246
    ospCommit(this->OSPRayVolume);
247
248
    ospAddVolume(OSPRayModel, this->OSPRayVolume);
    //ospCommit(OSPRayModel);
249
250
  }
}