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