1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkFixedPointVolumeRayCastCompositeHelper.cxx
5 Language: C++
6
7 Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
8 All rights reserved.
9 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10
11 This software is distributed WITHOUT ANY WARRANTY; without even
12 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 PURPOSE. See the above copyright notice for more information.
14
15 =========================================================================*/
16 #include "vtkFixedPointVolumeRayCastCompositeHelper.h"
17
18 #include "vtkCommand.h"
19 #include "vtkDataArray.h"
20 #include "vtkFixedPointRayCastImage.h"
21 #include "vtkFixedPointVolumeRayCastMapper.h"
22 #include "vtkImageData.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkRectilinearGrid.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkVolume.h"
27 #include "vtkVolumeProperty.h"
28
29 #include <cmath>
30
31 vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeHelper);
32
33 // Construct a new vtkFixedPointVolumeRayCastCompositeHelper with default values
34 vtkFixedPointVolumeRayCastCompositeHelper::vtkFixedPointVolumeRayCastCompositeHelper() = default;
35
36 // Destruct a vtkFixedPointVolumeRayCastCompositeHelper - clean up any memory used
37 vtkFixedPointVolumeRayCastCompositeHelper::~vtkFixedPointVolumeRayCastCompositeHelper() = default;
38
39 // This method is used when the interpolation type is nearest neighbor and
40 // the data has one component and scale == 1.0 and shift == 0.0. In the inner
41 // loop we get the data value as an unsigned short, and use this index to
42 // lookup a color and opacity for this sample. We then composite this into
43 // the color computed so far along the ray, and check if we can terminate at
44 // this point (if the accumulated opacity is higher than some threshold).
45 // Finally we move on to the next sample along the ray.
46 template <class T>
vtkFixedPointCompositeHelperGenerateImageOneSimpleNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))47 void vtkFixedPointCompositeHelperGenerateImageOneSimpleNN(T* data, int threadID, int threadCount,
48 vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
49 {
50 VTKKWRCHelper_InitializationAndLoopStartNN();
51 VTKKWRCHelper_InitializeCompositeOneNN();
52 VTKKWRCHelper_SpaceLeapSetup();
53
54 for (k = 0; k < numSteps; k++)
55 {
56
57 if (k)
58 {
59 VTKKWRCHelper_MoveToNextSampleNN();
60 }
61
62 VTKKWRCHelper_SpaceLeapCheck();
63 VTKKWRCHelper_CroppingCheckNN(pos);
64
65 unsigned short val = static_cast<unsigned short>(((*dptr)));
66
67 VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
68
69 if (tmp[3])
70 {
71 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
72 }
73 }
74
75 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
76 VTKKWRCHelper_IncrementAndLoopEnd();
77 }
78
79 // This method is used when the interpolation type is nearest neighbor and
80 // the data has one component. In the inner loop we get the data value as
81 // an unsigned short using the scale/shift, and use this index to lookup
82 // a color and opacity for this sample. We then composite this into the
83 // color computed so far along the ray, and check if we can terminate at
84 // this point (if the accumulated opacity is higher than some threshold).
85 // Finally we move on to the next sample along the ray.
86 template <class T>
vtkFixedPointCompositeHelperGenerateImageOneNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))87 void vtkFixedPointCompositeHelperGenerateImageOneNN(T* data, int threadID, int threadCount,
88 vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
89 {
90 VTKKWRCHelper_InitializationAndLoopStartNN();
91 VTKKWRCHelper_InitializeCompositeOneNN();
92 VTKKWRCHelper_SpaceLeapSetup();
93
94 for (k = 0; k < numSteps; k++)
95 {
96 if (k)
97 {
98 VTKKWRCHelper_MoveToNextSampleNN();
99 }
100
101 VTKKWRCHelper_SpaceLeapCheck();
102 VTKKWRCHelper_CroppingCheckNN(pos);
103
104 unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0]) * scale[0]);
105
106 VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
107
108 if (tmp[3])
109 {
110 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
111 }
112 }
113
114 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
115 VTKKWRCHelper_IncrementAndLoopEnd();
116 }
117
118 // This method is used when the interpolation type is nearest neighbor and
119 // the data has two components which are not considered independent. In the
120 // inner loop we compute the two unsigned short index values from the data
121 // values (using the scale/shift). We use the first index to lookup a color,
122 // and we use the second index to look up the opacity. We then composite
123 // the color into the color computed so far along this ray, and check to
124 // see if we can terminate here (if the opacity accumulated exceed some
125 // threshold). Finally we move to the next sample along the ray.
126 template <class T>
vtkFixedPointCompositeHelperGenerateImageTwoDependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))127 void vtkFixedPointCompositeHelperGenerateImageTwoDependentNN(T* data, int threadID, int threadCount,
128 vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
129 {
130 VTKKWRCHelper_InitializationAndLoopStartNN();
131 VTKKWRCHelper_InitializeCompositeOneNN();
132 VTKKWRCHelper_SpaceLeapSetup();
133
134 for (k = 0; k < numSteps; k++)
135 {
136 if (k)
137 {
138 VTKKWRCHelper_MoveToNextSampleNN();
139 }
140
141 VTKKWRCHelper_SpaceLeapCheck();
142 VTKKWRCHelper_CroppingCheckNN(pos);
143
144 unsigned short val[2];
145 val[1] = static_cast<unsigned short>(((*(dptr + 1)) + shift[1]) * scale[1]);
146
147 tmp[3] = scalarOpacityTable[0][val[1]];
148 if (!tmp[3])
149 {
150 continue;
151 }
152
153 val[0] = static_cast<unsigned short>(((*(dptr)) + shift[0]) * scale[0]);
154
155 tmp[0] = static_cast<unsigned short>(
156 (colorTable[0][3 * val[0]] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
157 tmp[1] = static_cast<unsigned short>(
158 (colorTable[0][3 * val[0] + 1] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
159 tmp[2] = static_cast<unsigned short>(
160 (colorTable[0][3 * val[0] + 2] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
161
162 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
163 }
164
165 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
166 VTKKWRCHelper_IncrementAndLoopEnd();
167 }
168
169 // This method is used when the interpolation type is nearest neighbor and
170 // the data has four components which are not considered independent . This
171 // means that the first three components directly represent color, and this
172 // data must be of unsigned char type. In the inner loop we directly access
173 // the four data values (no scale/shift is needed). The first three are the
174 // color of this sample and the fourth is used to look up an opacity in the
175 // scalar opacity transfer function. We then composite this color into the
176 // color we have accumulated so far along the ray, and check if we can
177 // terminate here (if our accumulated opacity has exceed some threshold).
178 // Finally we move onto the next sample along the ray.
179 template <class T>
vtkFixedPointCompositeHelperGenerateImageFourDependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))180 void vtkFixedPointCompositeHelperGenerateImageFourDependentNN(T* data, int threadID,
181 int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
182 {
183 VTKKWRCHelper_InitializationAndLoopStartNN();
184 VTKKWRCHelper_InitializeCompositeOneNN();
185 VTKKWRCHelper_SpaceLeapSetup();
186
187 for (k = 0; k < numSteps; k++)
188 {
189 if (k)
190 {
191 VTKKWRCHelper_MoveToNextSampleNN();
192 }
193
194 VTKKWRCHelper_SpaceLeapCheck();
195 VTKKWRCHelper_CroppingCheckNN(pos);
196
197 unsigned short val[4];
198 val[3] = static_cast<unsigned short>(((*(dptr + 3)) + shift[3]) * scale[3]);
199
200 tmp[3] = scalarOpacityTable[0][val[3]];
201 if (!tmp[3])
202 {
203 continue;
204 }
205
206 val[0] = *(dptr);
207 val[1] = *(dptr + 1);
208 val[2] = *(dptr + 2);
209
210 tmp[0] = (val[0] * tmp[3] + 0x7f) >> (8);
211 tmp[1] = (val[1] * tmp[3] + 0x7f) >> (8);
212 tmp[2] = (val[2] * tmp[3] + 0x7f) >> (8);
213
214 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
215 }
216
217 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
218 VTKKWRCHelper_IncrementAndLoopEnd();
219 }
220
221 // This method is used when the interpolation type is nearest neighbor and
222 // the data has more than one component and the components are considered to
223 // be independent. In the inner loop we access each component value, using
224 // the scale/shift to turn the data value into an unsigned short index. We
225 // then lookup the color/opacity for each component and combine them according
226 // to the weighting value for each component. We composite this resulting
227 // color into the color already accumulated for this ray, and we check
228 // whether we can terminate here (if the accumulated opacity exceeds some
229 // threshold). Finally we increment to the next sample on the ray.
230 template <class T>
vtkFixedPointCompositeHelperGenerateImageIndependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)231 void vtkFixedPointCompositeHelperGenerateImageIndependentNN(
232 T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
233 {
234 VTKKWRCHelper_InitializeWeights();
235 VTKKWRCHelper_InitializationAndLoopStartNN();
236 VTKKWRCHelper_InitializeCompositeMultiNN();
237
238 for (k = 0; k < numSteps; k++)
239 {
240 if (k)
241 {
242 VTKKWRCHelper_MoveToNextSampleNN();
243 }
244
245 VTKKWRCHelper_CroppingCheckNN(pos);
246
247 for (c = 0; c < components; c++)
248 {
249 val[c] = static_cast<unsigned short>(((*(dptr + c)) + shift[c]) * scale[c]);
250 }
251
252 VTKKWRCHelper_LookupAndCombineIndependentColorsUS(
253 colorTable, scalarOpacityTable, val, weights, components, tmp);
254 if (tmp[3])
255 {
256 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
257 }
258 }
259
260 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
261 VTKKWRCHelper_IncrementAndLoopEnd();
262 }
263
264 // This method is used when the interpolation type is linear and the data
265 // has one component and scale = 1.0 and shift = 0.0. In the inner loop we
266 // get the data value for the eight cell corners (if we have changed cells)
267 // as an unsigned short (the range must be right and we don't need the
268 // scale/shift). We compute our weights within the cell according to our
269 // fractional position within the cell, apply trilinear interpolation to
270 // compute the index, and use this index to lookup a color and opacity for
271 // this sample. We then composite this into the color computed so far along
272 // the ray, and check if we can terminate at this point (if the accumulated
273 // opacity is higher than some threshold). Finally we move on to the next
274 // sample along the ray.
275 template <class T>
vtkFixedPointCompositeHelperGenerateImageOneSimpleTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))276 void vtkFixedPointCompositeHelperGenerateImageOneSimpleTrilin(T* data, int threadID,
277 int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
278 {
279 VTKKWRCHelper_InitializationAndLoopStartTrilin();
280 VTKKWRCHelper_InitializeCompositeOneTrilin();
281 VTKKWRCHelper_SpaceLeapSetup();
282
283 for (k = 0; k < numSteps; k++)
284 {
285 if (k)
286 {
287 mapper->FixedPointIncrement(pos, dir);
288 }
289
290 VTKKWRCHelper_SpaceLeapCheck();
291 VTKKWRCHelper_CroppingCheckTrilin(pos);
292
293 mapper->ShiftVectorDown(pos, spos);
294
295 if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
296 {
297 oldSPos[0] = spos[0];
298 oldSPos[1] = spos[1];
299 oldSPos[2] = spos[2];
300
301 dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
302 VTKKWRCHelper_GetCellScalarValuesSimple(dptr);
303 }
304
305 VTKKWRCHelper_ComputeWeights(pos);
306 VTKKWRCHelper_InterpolateScalar(val);
307
308 VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
309 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
310 }
311
312 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
313 VTKKWRCHelper_IncrementAndLoopEnd();
314 }
315
316 // This method is used when the interpolation type is linear and the data
317 // has one component and scale != 1.0 or shift != 0.0. In the inner loop we
318 // get the data value for the eight cell corners (if we have changed cells)
319 // as an unsigned short (we use the scale/shift to ensure the correct range).
320 // We compute our weights within the cell according to our fractional position
321 // within the cell, apply trilinear interpolation to compute the index, and use
322 // this index to lookup a color and opacity for this sample. We then composite
323 // this into the color computed so far along the ray, and check if we can
324 // terminate at this point (if the accumulated opacity is higher than some
325 // threshold). Finally we move on to the next sample along the ray.
326 template <class T>
vtkFixedPointCompositeHelperGenerateImageOneTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))327 void vtkFixedPointCompositeHelperGenerateImageOneTrilin(T* data, int threadID, int threadCount,
328 vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
329 {
330 VTKKWRCHelper_InitializationAndLoopStartTrilin();
331 VTKKWRCHelper_InitializeCompositeOneTrilin();
332 VTKKWRCHelper_SpaceLeapSetup();
333
334 for (k = 0; k < numSteps; k++)
335 {
336 if (k)
337 {
338 mapper->FixedPointIncrement(pos, dir);
339 }
340
341 VTKKWRCHelper_SpaceLeapCheck();
342 VTKKWRCHelper_CroppingCheckTrilin(pos);
343
344 mapper->ShiftVectorDown(pos, spos);
345 if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
346 {
347 oldSPos[0] = spos[0];
348 oldSPos[1] = spos[1];
349 oldSPos[2] = spos[2];
350
351 dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
352 VTKKWRCHelper_GetCellScalarValues(dptr, scale[0], shift[0]);
353 }
354
355 VTKKWRCHelper_ComputeWeights(pos);
356 VTKKWRCHelper_InterpolateScalar(val);
357
358 VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
359 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
360 }
361
362 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
363 VTKKWRCHelper_IncrementAndLoopEnd();
364 }
365
366 // This method is used when the interpolation type is linear, the data has
367 // two components and the components are not considered independent. In the
368 // inner loop we get the data value for the eight cell corners (if we have
369 // changed cells) for both components as an unsigned shorts (we use the
370 // scale/shift to ensure the correct range). We compute our weights within
371 // the cell according to our fractional position within the cell, and apply
372 // trilinear interpolation to compute the two index value. We use the first
373 // index to lookup a color and the second to look up an opacity for this sample.
374 // We then composite this into the color computed so far along the ray, and
375 // check if we can terminate at this point (if the accumulated opacity is
376 // higher than some threshold). Finally we move on to the next sample along
377 // the ray.
378 template <class T>
vtkFixedPointCompositeHelperGenerateImageTwoDependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))379 void vtkFixedPointCompositeHelperGenerateImageTwoDependentTrilin(T* data, int threadID,
380 int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
381 {
382 VTKKWRCHelper_InitializationAndLoopStartTrilin();
383 VTKKWRCHelper_InitializeCompositeMultiTrilin();
384 VTKKWRCHelper_SpaceLeapSetup();
385
386 for (k = 0; k < numSteps; k++)
387 {
388 if (k)
389 {
390 mapper->FixedPointIncrement(pos, dir);
391 }
392
393 VTKKWRCHelper_SpaceLeapCheck();
394 VTKKWRCHelper_CroppingCheckTrilin(pos);
395
396 mapper->ShiftVectorDown(pos, spos);
397 if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
398 {
399 oldSPos[0] = spos[0];
400 oldSPos[1] = spos[1];
401 oldSPos[2] = spos[2];
402
403 dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
404 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 0, scale[0], shift[0]);
405
406 dptr++;
407 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 1, scale[1], shift[1]);
408 }
409
410 VTKKWRCHelper_ComputeWeights(pos);
411 VTKKWRCHelper_InterpolateScalarComponent(val, c, 2);
412
413 tmp[3] = scalarOpacityTable[0][val[1]];
414 if (!tmp[3])
415 {
416 continue;
417 }
418
419 tmp[0] = static_cast<unsigned short>(
420 (colorTable[0][3 * val[0]] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
421 tmp[1] = static_cast<unsigned short>(
422 (colorTable[0][3 * val[0] + 1] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
423 tmp[2] = static_cast<unsigned short>(
424 (colorTable[0][3 * val[0] + 2] * tmp[3] + 0x7fff) >> (VTKKW_FP_SHIFT));
425
426 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
427 }
428
429 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
430 VTKKWRCHelper_IncrementAndLoopEnd();
431 }
432
433 // This method is used when the interpolation type is linear, the data has
434 // four components and the components are not considered independent. In the
435 // inner loop we get the data value for the eight cell corners (if we have
436 // changed cells) for all components as an unsigned shorts (we don't have to
437 // use the scale/shift because only unsigned char data is supported for four
438 // component data when the components are not independent). We compute our
439 // weights within the cell according to our fractional position within the cell,
440 // and apply trilinear interpolation to compute a value for each component. We
441 // use the first three directly as the color of the sample, and the fourth is
442 // used to look up an opacity for this sample. We then composite this into the
443 // color computed so far along the ray, and check if we can terminate at this
444 // point (if the accumulated opacity is higher than some threshold). Finally we
445 // move on to the next sample along the ray.
446 template <class T>
vtkFixedPointCompositeHelperGenerateImageFourDependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vtkNotUsed (vol))447 void vtkFixedPointCompositeHelperGenerateImageFourDependentTrilin(T* data, int threadID,
448 int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vtkNotUsed(vol))
449 {
450 VTKKWRCHelper_InitializationAndLoopStartTrilin();
451 VTKKWRCHelper_InitializeCompositeMultiTrilin();
452 VTKKWRCHelper_SpaceLeapSetup();
453
454 for (k = 0; k < numSteps; k++)
455 {
456 if (k)
457 {
458 mapper->FixedPointIncrement(pos, dir);
459 }
460
461 VTKKWRCHelper_SpaceLeapCheck();
462 VTKKWRCHelper_CroppingCheckTrilin(pos);
463
464 mapper->ShiftVectorDown(pos, spos);
465 if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
466 {
467 oldSPos[0] = spos[0];
468 oldSPos[1] = spos[1];
469 oldSPos[2] = spos[2];
470
471 dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
472 VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 0);
473
474 dptr++;
475 VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 1);
476
477 dptr++;
478 VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 2);
479
480 dptr++;
481 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 3, scale[3], shift[3]);
482 }
483
484 VTKKWRCHelper_ComputeWeights(pos);
485 VTKKWRCHelper_InterpolateScalarComponent(val, c, components);
486
487 tmp[3] = scalarOpacityTable[0][val[3]];
488 if (!tmp[3])
489 {
490 continue;
491 }
492
493 tmp[0] = (val[0] * tmp[3] + 0x7f) >> 8;
494 tmp[1] = (val[1] * tmp[3] + 0x7f) >> 8;
495 tmp[2] = (val[2] * tmp[3] + 0x7f) >> 8;
496
497 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
498 }
499
500 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
501 VTKKWRCHelper_IncrementAndLoopEnd();
502 }
503
504 // This method is used when the interpolation type is linear, the data has
505 // more than one component and the components are considered independent. In
506 // the inner loop we get the data value for the eight cell corners (if we have
507 // changed cells) for all components as an unsigned shorts (we have to use the
508 // scale/shift to ensure that we obtained unsigned short indices) We compute our
509 // weights within the cell according to our fractional position within the cell,
510 // and apply trilinear interpolation to compute a value for each component. We
511 // look up a color/opacity for each component and blend them according to the
512 // component weights. We then composite this resulting color into the
513 // color computed so far along the ray, and check if we can terminate at this
514 // point (if the accumulated opacity is higher than some threshold). Finally we
515 // move on to the next sample along the ray.
516 template <class T>
vtkFixedPointCompositeHelperGenerateImageIndependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)517 void vtkFixedPointCompositeHelperGenerateImageIndependentTrilin(
518 T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
519 {
520 VTKKWRCHelper_InitializeWeights();
521 VTKKWRCHelper_InitializationAndLoopStartTrilin();
522 VTKKWRCHelper_InitializeCompositeMultiTrilin();
523
524 for (k = 0; k < numSteps; k++)
525 {
526 if (k)
527 {
528 mapper->FixedPointIncrement(pos, dir);
529 }
530
531 VTKKWRCHelper_CroppingCheckTrilin(pos);
532
533 mapper->ShiftVectorDown(pos, spos);
534 if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
535 {
536 oldSPos[0] = spos[0];
537 oldSPos[1] = spos[1];
538 oldSPos[2] = spos[2];
539
540 dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
541 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 0, scale[0], shift[0]);
542
543 dptr++;
544 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 1, scale[1], shift[1]);
545
546 if (components > 2)
547 {
548 dptr++;
549 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 2, scale[2], shift[2]);
550 }
551
552 if (components > 3)
553 {
554 dptr++;
555 VTKKWRCHelper_GetCellComponentScalarValues(dptr, 3, scale[3], shift[3]);
556 }
557 }
558
559 VTKKWRCHelper_ComputeWeights(pos);
560 VTKKWRCHelper_InterpolateScalarComponent(val, c, components);
561
562 VTKKWRCHelper_LookupAndCombineIndependentColorsUS(
563 colorTable, scalarOpacityTable, val, weights, components, tmp);
564
565 VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
566 }
567
568 VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
569 VTKKWRCHelper_IncrementAndLoopEnd();
570 }
571
GenerateImage(int threadID,int threadCount,vtkVolume * vol,vtkFixedPointVolumeRayCastMapper * mapper)572 void vtkFixedPointVolumeRayCastCompositeHelper::GenerateImage(
573 int threadID, int threadCount, vtkVolume* vol, vtkFixedPointVolumeRayCastMapper* mapper)
574 {
575 void* data = mapper->GetCurrentScalars()->GetVoidPointer(0);
576 int scalarType = mapper->GetCurrentScalars()->GetDataType();
577
578 // Nearest Neighbor interpolate
579 if (mapper->ShouldUseNearestNeighborInterpolation(vol))
580 {
581 // One component data
582 if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 1)
583 {
584 // Scale == 1.0 and shift == 0.0 - simple case (faster)
585 if (mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0)
586 {
587 switch (scalarType)
588 {
589 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageOneSimpleNN(
590 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
591 }
592 }
593 else
594 {
595 switch (scalarType)
596 {
597 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageOneNN(
598 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
599 }
600 }
601 }
602 // More that one independent components
603 else if (vol->GetProperty()->GetIndependentComponents())
604 {
605 switch (scalarType)
606 {
607 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageIndependentNN(
608 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
609 }
610 }
611 // Dependent (color) components
612 else
613 {
614 // Two components - the first specifies color (through a lookup table)
615 // and the second specified opacity (through a lookup table)
616 if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 2)
617 {
618 switch (scalarType)
619 {
620 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageTwoDependentNN(
621 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
622 }
623 }
624 // Four components - they must be unsigned char, the first three directly
625 // specify color and the fourth specifies opacity (through a lookup
626 // table)
627 else
628 {
629 if (scalarType == VTK_UNSIGNED_CHAR)
630 {
631 vtkFixedPointCompositeHelperGenerateImageFourDependentNN(
632 static_cast<unsigned char*>(data), threadID, threadCount, mapper, vol);
633 }
634 else
635 {
636 vtkErrorMacro("Four component dependent data must be unsigned char!");
637 }
638 }
639 }
640 }
641 // Trilinear Interpolation
642 else
643 {
644 // One component
645 if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 1)
646 {
647 // Scale == 1.0 and shift == 0.0 - simple case (faster)
648 if (mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0)
649 {
650 switch (scalarType)
651 {
652 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageOneSimpleTrilin(
653 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
654 }
655 }
656 // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
657 else
658 {
659 switch (scalarType)
660 {
661 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageOneTrilin(
662 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
663 }
664 }
665 }
666 // Independent components (more than one)
667 else if (vol->GetProperty()->GetIndependentComponents())
668 {
669 switch (scalarType)
670 {
671 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageIndependentTrilin(
672 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
673 }
674 }
675 // Dependent components
676 else
677 {
678 // Two components - the first specifies color (through a lookup table)
679 // and the second specified opacity (through a lookup table)
680 if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 2)
681 {
682 switch (scalarType)
683 {
684 vtkTemplateMacro(vtkFixedPointCompositeHelperGenerateImageTwoDependentTrilin(
685 static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
686 }
687 }
688 // Four components - they must be unsigned char, the first three directly
689 // specify color and the fourth specifies opacity (through a lookup
690 // table)
691 else
692 {
693 if (scalarType == VTK_UNSIGNED_CHAR)
694 {
695 vtkFixedPointCompositeHelperGenerateImageFourDependentTrilin(
696 static_cast<unsigned char*>(data), threadID, threadCount, mapper, vol);
697 }
698 else
699 {
700 vtkErrorMacro("Four component dependent data must be unsigned char!");
701 }
702 }
703 }
704 }
705 }
706
707 // Print method for vtkFixedPointVolumeRayCastCompositeHelper
PrintSelf(ostream & os,vtkIndent indent)708 void vtkFixedPointVolumeRayCastCompositeHelper::PrintSelf(ostream& os, vtkIndent indent)
709 {
710 this->Superclass::PrintSelf(os, indent);
711 }
712