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