1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFixedPointVolumeRayCastCompositeGOShadeHelper.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 "vtkFixedPointVolumeRayCastCompositeGOShadeHelper.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(vtkFixedPointVolumeRayCastCompositeGOShadeHelper);
31 
32 // Construct a new vtkFixedPointVolumeRayCastCompositeGOShadeHelper with default values
33 vtkFixedPointVolumeRayCastCompositeGOShadeHelper::vtkFixedPointVolumeRayCastCompositeGOShadeHelper() = default;
34 
35 // Destruct a vtkFixedPointVolumeRayCastCompositeGOShadeHelper - clean up any memory used
36 vtkFixedPointVolumeRayCastCompositeGOShadeHelper::~vtkFixedPointVolumeRayCastCompositeGOShadeHelper() = 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>
vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)47 void vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleNN( T *data,
48                                                           int threadID,
49                                                           int threadCount,
50                                                           vtkFixedPointVolumeRayCastMapper *mapper,
51                                                           vtkVolume *vol)
52 {
53   VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
54   VTKKWRCHelper_InitializeCompositeOneNN();
55   VTKKWRCHelper_InitializeCompositeShadeNN();
56   VTKKWRCHelper_InitializeCompositeGONN();
57   VTKKWRCHelper_SpaceLeapSetup();
58 
59   for ( k = 0; k < numSteps; k++ )
60   {
61     if ( k )
62     {
63       VTKKWRCHelper_MoveToNextSampleGOShadeNN();
64     }
65 
66     VTKKWRCHelper_SpaceLeapCheck();
67     VTKKWRCHelper_CroppingCheckNN( pos );
68     unsigned short val    = static_cast<unsigned short>(((*dptr)));
69     unsigned char  mag    = *magPtr;
70 
71 
72     VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
73                                    gradientOpacityTable[0], val, mag, tmp );
74 
75     if ( tmp[3] )
76     {
77       unsigned short normal = *dirPtr;
78       VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
79       VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
80     }
81   }
82 
83   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
84   VTKKWRCHelper_IncrementAndLoopEnd();
85 }
86 
87 // This method is used when the interpolation type is nearest neighbor and
88 // the data has one component. In the inner loop we get the data value as
89 // an unsigned short using the scale/shift, and use this index to lookup
90 // a color and opacity for this sample. We then composite this into the
91 // color computed so far along the ray, and check if we can terminate at
92 // this point (if the accumulated opacity is higher than some threshold).
93 // Finally we move on to the next sample along the ray.
94 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageOneNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)95 void vtkFixedPointCompositeGOShadeHelperGenerateImageOneNN( T *data,
96                                              int threadID,
97                                              int threadCount,
98                                              vtkFixedPointVolumeRayCastMapper *mapper,
99                                              vtkVolume *vol)
100 {
101   VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
102   VTKKWRCHelper_InitializeCompositeOneNN();
103   VTKKWRCHelper_InitializeCompositeShadeNN();
104   VTKKWRCHelper_InitializeCompositeGONN();
105   VTKKWRCHelper_SpaceLeapSetup();
106 
107   for ( k = 0; k < numSteps; k++ )
108   {
109     if ( k )
110     {
111       VTKKWRCHelper_MoveToNextSampleGOShadeNN();
112     }
113 
114     VTKKWRCHelper_SpaceLeapCheck();
115     VTKKWRCHelper_CroppingCheckNN( pos );
116     unsigned short val    = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
117     unsigned char  mag    = *magPtr;
118 
119     VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
120                                    gradientOpacityTable[0], val, mag, tmp );
121 
122     if ( tmp[3] )
123     {
124       unsigned short normal = *dirPtr;
125       VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
126       VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
127     }
128   }
129 
130   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
131   VTKKWRCHelper_IncrementAndLoopEnd();
132 }
133 
134 
135 // This method is used when the interpolation type is nearest neighbor and
136 // the data has two components which are not considered independent. In the
137 // inner loop we compute the two unsigned short index values from the data
138 // values (using the scale/shift). We use the first index to lookup a color,
139 // and we use the second index to look up the opacity. We then composite
140 // the color into the color computed so far along this ray, and check to
141 // see if we can terminate here (if the opacity accumulated exceed some
142 // threshold). Finally we move to the next sample along the ray.
143 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)144 void vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentNN( T *data,
145                                                       int threadID,
146                                                       int threadCount,
147                                                       vtkFixedPointVolumeRayCastMapper *mapper,
148                                                       vtkVolume *vol)
149 {
150   VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
151   VTKKWRCHelper_InitializeCompositeOneNN();
152   VTKKWRCHelper_InitializeCompositeShadeNN();
153   VTKKWRCHelper_InitializeCompositeGONN();
154   VTKKWRCHelper_SpaceLeapSetup();
155 
156   for ( k = 0; k < numSteps; k++ )
157   {
158     if ( k )
159     {
160       VTKKWRCHelper_MoveToNextSampleGOShadeNN();
161     }
162 
163     VTKKWRCHelper_SpaceLeapCheck();
164     VTKKWRCHelper_CroppingCheckNN( pos );
165     unsigned short val[2];
166 
167     val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
168     unsigned char  mag     = *magPtr;
169 
170     tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
171     if ( !tmp[3] )
172     {
173       continue;
174     }
175 
176     val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
177     unsigned short normal  = *dirPtr;
178 
179     tmp[0] = static_cast<unsigned short>
180       ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
181     tmp[1] = static_cast<unsigned short>
182       ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
183     tmp[2] = static_cast<unsigned short>
184       ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
185 
186     VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
187 
188     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
189   }
190 
191   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
192   VTKKWRCHelper_IncrementAndLoopEnd();
193 }
194 
195 // This method is used when the interpolation type is nearest neighbor and
196 // the data has four components which are not considered independent . This
197 // means that the first three components directly represent color, and this
198 // data must be of unsigned char type. In the inner loop we directly access
199 // the four data values (no scale/shift is needed). The first three are the
200 // color of this sample and the fourth is used to look up an opacity in the
201 // scalar opacity transfer function. We then composite this color into the
202 // color we have accumulated so far along the ray, and check if we can
203 // terminate here (if our accumulated opacity has exceed some threshold).
204 // Finally we move onto the next sample along the ray.
205 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)206 void vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentNN( T *data,
207                                                        int threadID,
208                                                        int threadCount,
209                                                        vtkFixedPointVolumeRayCastMapper *mapper,
210                                                        vtkVolume *vol)
211 {
212   VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
213   VTKKWRCHelper_InitializeCompositeOneNN();
214   VTKKWRCHelper_InitializeCompositeShadeNN();
215   VTKKWRCHelper_InitializeCompositeGONN();
216   VTKKWRCHelper_SpaceLeapSetup();
217 
218   for ( k = 0; k < numSteps; k++ )
219   {
220     if ( k )
221     {
222       VTKKWRCHelper_MoveToNextSampleGOShadeNN();
223     }
224 
225     VTKKWRCHelper_SpaceLeapCheck();
226     VTKKWRCHelper_CroppingCheckNN( pos );
227     unsigned short val[4];
228 
229     val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
230 
231     unsigned char  mag   = *magPtr;
232 
233     tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
234     if ( !tmp[3] )
235     {
236       continue;
237     }
238 
239     val[0] = *(dptr  );
240     val[1] = *(dptr+1);
241     val[2] = *(dptr+2);
242     unsigned short normal = *dirPtr;
243 
244     tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
245     tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
246     tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
247 
248     VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
249 
250     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
251   }
252 
253   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
254   VTKKWRCHelper_IncrementAndLoopEnd();
255 }
256 
257 // This method is used when the interpolation type is nearest neighbor and
258 // the data has more than one component and the components are considered to
259 // be independent. In the inner loop we access each component value, using
260 // the scale/shift to turn the data value into an unsigned short index. We
261 // then lookup the color/opacity for each component and combine them according
262 // to the weighting value for each component. We composite this resulting
263 // color into the color already accumulated for this ray, and we check
264 // whether we can terminate here (if the accumulated opacity exceeds some
265 // threshold). Finally we increment to the next sample on the ray.
266 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentNN(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)267 void vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentNN( T *data,
268                                                      int threadID,
269                                                      int threadCount,
270                                                      vtkFixedPointVolumeRayCastMapper *mapper,
271                                                      vtkVolume *vol)
272 {
273   VTKKWRCHelper_InitializeWeights();
274   VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
275   VTKKWRCHelper_InitializeCompositeMultiNN();
276   VTKKWRCHelper_InitializeCompositeShadeNN();
277   VTKKWRCHelper_InitializeCompositeGONN();
278 
279   for ( k = 0; k < numSteps; k++ )
280   {
281     if ( k )
282     {
283       VTKKWRCHelper_MoveToNextSampleGOShadeNN();
284     }
285 
286     VTKKWRCHelper_CroppingCheckNN( pos );
287     unsigned short normal[4];
288     unsigned char  mag[4] = { 1, 1, 1, 1};
289     for ( c = 0; c < components; c++ )
290     {
291       val[c]     = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
292       mag[c]     = static_cast<unsigned short>(*(magPtr+c));
293       normal[c]  = *(dirPtr+c);
294     }
295 
296     VTKKWRCHelper_LookupAndCombineIndependentColorsGOShadeUS( colorTable, scalarOpacityTable,
297                                                               gradientOpacityTable,
298                                                               diffuseShadingTable,
299                                                               specularShadingTable,
300                                                               val, mag, normal, weights,
301                                                               components, tmp );
302 
303     if ( tmp[3] )
304     {
305       VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
306     }
307   }
308 
309   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
310   VTKKWRCHelper_IncrementAndLoopEnd();
311 }
312 
313 // This method is used when the interpolation type is linear and the data
314 // has one component and scale = 1.0 and shift = 0.0. In the inner loop we
315 // get the data value for the eight cell corners (if we have changed cells)
316 // as an unsigned short (the range must be right and we don't need the
317 // scale/shift). We compute our weights within the cell according to our
318 // fractional position within the cell, apply trilinear interpolation to
319 // compute the index, and use this index to lookup a color and opacity for
320 // this sample. We then composite this into the color computed so far along
321 // the ray, and check if we can terminate at this point (if the accumulated
322 // opacity is higher than some threshold). Finally we move on to the next
323 // sample along the ray.
324 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)325 void vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleTrilin( T *data,
326                                                        int threadID,
327                                                        int threadCount,
328                                                        vtkFixedPointVolumeRayCastMapper *mapper,
329                                                        vtkVolume *vol)
330 {
331   VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
332   VTKKWRCHelper_InitializeCompositeOneTrilin();
333   VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
334   VTKKWRCHelper_InitializeCompositeOneGOTrilin();
335   VTKKWRCHelper_SpaceLeapSetup();
336 
337   int needToSampleDirection = 0;
338   int needToSampleMagnitude = 0;
339   for ( k = 0; k < numSteps; k++ )
340   {
341     if ( k )
342     {
343       mapper->FixedPointIncrement( pos, dir );
344     }
345 
346     VTKKWRCHelper_SpaceLeapCheck();
347     VTKKWRCHelper_CroppingCheckTrilin( pos );
348 
349     mapper->ShiftVectorDown( pos, spos );
350     if ( spos[0] != oldSPos[0] ||
351          spos[1] != oldSPos[1] ||
352          spos[2] != oldSPos[2] )
353     {
354       oldSPos[0] = spos[0];
355       oldSPos[1] = spos[1];
356       oldSPos[2] = spos[2];
357 
358       dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
359       VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
360 
361       magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
362       magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
363       needToSampleMagnitude = 1;
364 
365       dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
366       dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
367       needToSampleDirection = 1;
368     }
369 
370     VTKKWRCHelper_ComputeWeights(pos);
371     VTKKWRCHelper_InterpolateScalar(val);
372 
373     tmp[3] = scalarOpacityTable[0][val];
374     if ( !tmp[3] )
375     {
376       continue;
377     }
378 
379     if ( needToSampleMagnitude )
380     {
381       VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
382       needToSampleMagnitude = 0;
383     }
384     VTKKWRCHelper_InterpolateMagnitude(mag);
385     tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
386     if ( !tmp[3] )
387     {
388       continue;
389     }
390 
391     tmp[0] = static_cast<unsigned short>
392       ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
393     tmp[1] = static_cast<unsigned short>
394       ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
395     tmp[2] = static_cast<unsigned short>
396       ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
397 
398 
399     if ( needToSampleDirection )
400     {
401       VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
402       needToSampleDirection = 0;
403     }
404 
405     VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
406     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
407   }
408 
409   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
410   VTKKWRCHelper_IncrementAndLoopEnd();
411 }
412 
413 // This method is used when the interpolation type is linear and the data
414 // has one component and scale != 1.0 or shift != 0.0. In the inner loop we
415 // get the data value for the eight cell corners (if we have changed cells)
416 // as an unsigned short (we use the scale/shift to ensure the correct range).
417 // We compute our weights within the cell according to our fractional position
418 // within the cell, apply trilinear interpolation to compute the index, and use
419 // this index to lookup a color and opacity for this sample. We then composite
420 // this into the color computed so far along the ray, and check if we can
421 // terminate at this point (if the accumulated opacity is higher than some
422 // threshold). Finally we move on to the next sample along the ray.
423 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageOneTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)424 void vtkFixedPointCompositeGOShadeHelperGenerateImageOneTrilin( T *data,
425                                                  int threadID,
426                                                  int threadCount,
427                                                  vtkFixedPointVolumeRayCastMapper *mapper,
428                                                  vtkVolume *vol)
429 {
430   VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
431   VTKKWRCHelper_InitializeCompositeOneTrilin();
432   VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
433   VTKKWRCHelper_InitializeCompositeOneGOTrilin();
434   VTKKWRCHelper_SpaceLeapSetup();
435 
436   int needToSampleDirection = 0;
437   int needToSampleMagnitude = 0;
438   for ( k = 0; k < numSteps; k++ )
439   {
440     if ( k )
441     {
442       mapper->FixedPointIncrement( pos, dir );
443     }
444 
445     VTKKWRCHelper_SpaceLeapCheck();
446     VTKKWRCHelper_CroppingCheckTrilin( pos );
447 
448     mapper->ShiftVectorDown( pos, spos );
449     if ( spos[0] != oldSPos[0] ||
450          spos[1] != oldSPos[1] ||
451          spos[2] != oldSPos[2] )
452     {
453       oldSPos[0] = spos[0];
454       oldSPos[1] = spos[1];
455       oldSPos[2] = spos[2];
456 
457 
458       dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
459       VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
460 
461       magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
462       magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
463       needToSampleMagnitude = 1;
464 
465       dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
466       dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
467       needToSampleDirection = 1;
468     }
469 
470     VTKKWRCHelper_ComputeWeights(pos);
471     VTKKWRCHelper_InterpolateScalar(val);
472 
473     tmp[3] = scalarOpacityTable[0][val];
474     if ( !tmp[3] )
475     {
476       continue;
477     }
478 
479     if ( needToSampleMagnitude )
480     {
481       VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
482       needToSampleMagnitude = 0;
483     }
484     VTKKWRCHelper_InterpolateMagnitude(mag);
485     tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
486     if ( !tmp[3] )
487     {
488       continue;
489     }
490 
491     if ( needToSampleDirection )
492     {
493       VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
494       needToSampleDirection = 0;
495     }
496 
497     tmp[0] = static_cast<unsigned short>
498       ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
499     tmp[1] = static_cast<unsigned short>
500       ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
501     tmp[2] = static_cast<unsigned short>
502       ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
503 
504     VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
505     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
506   }
507 
508   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
509   VTKKWRCHelper_IncrementAndLoopEnd();
510 }
511 
512 
513 // This method is used when the interpolation type is linear, the data has
514 // two components and the components are not considered independent. In the
515 // inner loop we get the data value for the eight cell corners (if we have
516 // changed cells) for both components as an unsigned shorts (we use the
517 // scale/shift to ensure the correct range). We compute our weights within
518 // the cell according to our fractional position within the cell, and apply
519 // trilinear interpolation to compute the two index value. We use the first
520 // index to lookup a color and the second to look up an opacity for this sample.
521 // We then composite this into the color computed so far along the ray, and
522 // check if we can terminate at this point (if the accumulated opacity is
523 // higher than some threshold). Finally we move on to the next sample along
524 // the ray.
525 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)526 void vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentTrilin( T *data,
527                                                           int threadID,
528                                                           int threadCount,
529                                                           vtkFixedPointVolumeRayCastMapper *mapper,
530                                                           vtkVolume *vol)
531 {
532   VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
533   VTKKWRCHelper_InitializeCompositeMultiTrilin();
534   VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
535   VTKKWRCHelper_InitializeCompositeOneGOTrilin();
536   VTKKWRCHelper_SpaceLeapSetup();
537 
538   int needToSampleDirection = 0;
539   int needToSampleMagnitude = 0;
540   for ( k = 0; k < numSteps; k++ )
541   {
542     if ( k )
543     {
544       mapper->FixedPointIncrement( pos, dir );
545     }
546 
547     VTKKWRCHelper_SpaceLeapCheck();
548     VTKKWRCHelper_CroppingCheckTrilin( pos );
549 
550     mapper->ShiftVectorDown( pos, spos );
551     if ( spos[0] != oldSPos[0] ||
552          spos[1] != oldSPos[1] ||
553          spos[2] != oldSPos[2] )
554     {
555       oldSPos[0] = spos[0];
556       oldSPos[1] = spos[1];
557       oldSPos[2] = spos[2];
558 
559       dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
560       VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
561 
562       dptr++;
563       VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
564 
565       magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
566       magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
567       needToSampleMagnitude = 1;
568 
569       dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
570       dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
571       needToSampleDirection = 1;
572     }
573 
574     VTKKWRCHelper_ComputeWeights(pos);
575     VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
576 
577     tmp[3] = scalarOpacityTable[0][val[1]];
578     if ( !tmp[3] )
579     {
580       continue;
581     }
582 
583     if ( needToSampleMagnitude )
584     {
585       VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
586       needToSampleMagnitude = 0;
587     }
588     VTKKWRCHelper_InterpolateMagnitude(mag);
589     tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT);
590     if ( !tmp[3] )
591     {
592       continue;
593     }
594 
595     if ( needToSampleDirection )
596     {
597       VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
598       needToSampleDirection = 0;
599     }
600 
601     tmp[0] = static_cast<unsigned short>
602       ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
603     tmp[1] = static_cast<unsigned short>
604       ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
605     tmp[2] = static_cast<unsigned short>
606       ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
607 
608     VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
609 
610     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
611   }
612 
613   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
614   VTKKWRCHelper_IncrementAndLoopEnd();
615 }
616 
617 
618 
619 // This method is used when the interpolation type is linear, the data has
620 // four components and the components are not considered independent. In the
621 // inner loop we get the data value for the eight cell corners (if we have
622 // changed cells) for all components as an unsigned shorts (we don't have to
623 // use the scale/shift because only unsigned char data is supported for four
624 // component data when the components are not independent). We compute our
625 // weights within the cell according to our fractional position within the cell,
626 // and apply trilinear interpolation to compute a value for each component. We
627 // use the first three directly as the color of the sample, and the fourth is
628 // used to look up an opacity for this sample. We then composite this into the
629 // color computed so far along the ray, and check if we can terminate at this
630 // point (if the accumulated opacity is higher than some threshold). Finally we
631 // move on to the next sample along the ray.
632 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)633 void vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentTrilin( T *data,
634                                                            int threadID,
635                                                            int threadCount,
636                                                            vtkFixedPointVolumeRayCastMapper *mapper,
637                                                            vtkVolume *vol)
638 {
639   VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
640   VTKKWRCHelper_InitializeCompositeMultiTrilin();
641   VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
642   VTKKWRCHelper_InitializeCompositeOneGOTrilin();
643   VTKKWRCHelper_SpaceLeapSetup();
644 
645   int needToSampleDirection = 0;
646   int needToSampleMagnitude = 0;
647   for ( k = 0; k < numSteps; k++ )
648   {
649     if ( k )
650     {
651       mapper->FixedPointIncrement( pos, dir );
652     }
653 
654     VTKKWRCHelper_SpaceLeapCheck();
655     VTKKWRCHelper_CroppingCheckTrilin( pos );
656 
657     mapper->ShiftVectorDown( pos, spos );
658     if ( spos[0] != oldSPos[0] ||
659          spos[1] != oldSPos[1] ||
660          spos[2] != oldSPos[2] )
661     {
662       oldSPos[0] = spos[0];
663       oldSPos[1] = spos[1];
664       oldSPos[2] = spos[2];
665 
666       dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
667       VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
668 
669       dptr++;
670       VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
671 
672       dptr++;
673       VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
674 
675       dptr++;
676       VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
677 
678       magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
679       magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
680       needToSampleMagnitude = 1;
681 
682       dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
683       dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
684       needToSampleDirection = 1;
685     }
686 
687     VTKKWRCHelper_ComputeWeights(pos);
688     VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
689 
690     tmp[3] = scalarOpacityTable[0][val[3]];
691     if ( !tmp[3] )
692     {
693       continue;
694     }
695 
696     if ( needToSampleMagnitude )
697     {
698       VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
699       needToSampleMagnitude = 0;
700     }
701     VTKKWRCHelper_InterpolateMagnitude(mag);
702     tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT);
703     if ( !tmp[3] )
704     {
705       continue;
706     }
707 
708     if ( needToSampleDirection )
709     {
710       VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
711       needToSampleDirection = 0;
712     }
713 
714     tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
715     tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
716     tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
717 
718     VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
719     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
720   }
721 
722   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
723   VTKKWRCHelper_IncrementAndLoopEnd();
724 }
725 
726 // This method is used when the interpolation type is linear, the data has
727 // more than one component and the components are considered independent. In
728 // the inner loop we get the data value for the eight cell corners (if we have
729 // changed cells) for all components as an unsigned shorts (we have to use the
730 // scale/shift to ensure that we obtained unsigned short indices) We compute our
731 // weights within the cell according to our fractional position within the cell,
732 // and apply trilinear interpolation to compute a value for each component. We
733 // look up a color/opacity for each component and blend them according to the
734 // component weights. We then composite this resulting color into the
735 // color computed so far along the ray, and check if we can terminate at this
736 // point (if the accumulated opacity is higher than some threshold). Finally we
737 // move on to the next sample along the ray.
738 template <class T>
vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentTrilin(T * data,int threadID,int threadCount,vtkFixedPointVolumeRayCastMapper * mapper,vtkVolume * vol)739 void vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentTrilin( T *data,
740                                                          int threadID,
741                                                          int threadCount,
742                                                          vtkFixedPointVolumeRayCastMapper *mapper,
743                                                          vtkVolume *vol)
744 {
745   VTKKWRCHelper_InitializeWeights();
746   VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
747   VTKKWRCHelper_InitializeCompositeMultiTrilin();
748   VTKKWRCHelper_InitializeCompositeMultiShadeTrilin();
749   VTKKWRCHelper_InitializeCompositeMultiGOTrilin();
750 
751   for ( k = 0; k < numSteps; k++ )
752   {
753     if ( k )
754     {
755       mapper->FixedPointIncrement( pos, dir );
756     }
757 
758     VTKKWRCHelper_CroppingCheckTrilin( pos );
759 
760     mapper->ShiftVectorDown( pos, spos );
761     if ( spos[0] != oldSPos[0] ||
762          spos[1] != oldSPos[1] ||
763          spos[2] != oldSPos[2] )
764     {
765       oldSPos[0] = spos[0];
766       oldSPos[1] = spos[1];
767       oldSPos[2] = spos[2];
768 
769       dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
770       VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
771 
772       dptr++;
773       VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
774 
775       if ( components > 2 )
776       {
777         dptr++;
778         VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
779         if ( components > 3 )
780         {
781           dptr++;
782           VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
783         }
784       }
785 
786       magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
787       magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
788       VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 );
789 
790       magPtrABCD++;
791       magPtrEFGH++;
792       VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 );
793 
794       if ( components > 2 )
795       {
796         magPtrABCD++;
797         magPtrEFGH++;
798         VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 );
799         if ( components > 3 )
800         {
801           magPtrABCD++;
802           magPtrEFGH++;
803           VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 );
804         }
805       }
806 
807       dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
808       dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
809       VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 0 );
810 
811       dirPtrABCD++;
812       dirPtrEFGH++;
813       VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 1 );
814 
815       if ( components > 2 )
816       {
817         dirPtrABCD++;
818         dirPtrEFGH++;
819         VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 2 );
820         if ( components > 3 )
821         {
822           dirPtrABCD++;
823           dirPtrEFGH++;
824           VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 3 );
825         }
826       }
827     }
828 
829     VTKKWRCHelper_ComputeWeights(pos);
830     VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
831     VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components );
832 
833     VTKKWRCHelper_LookupAndCombineIndependentColorsGOInterpolateShadeUS(
834       colorTable, scalarOpacityTable, gradientOpacityTable,
835       diffuseShadingTable, specularShadingTable,
836       val, mag, weights, components, tmp );
837 
838     VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
839   }
840 
841   VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
842   VTKKWRCHelper_IncrementAndLoopEnd();
843 }
844 
845 
GenerateImage(int threadID,int threadCount,vtkVolume * vol,vtkFixedPointVolumeRayCastMapper * mapper)846 void vtkFixedPointVolumeRayCastCompositeGOShadeHelper::GenerateImage( int threadID,
847                                                  int threadCount,
848                                                  vtkVolume *vol,
849                                                  vtkFixedPointVolumeRayCastMapper *mapper )
850 {
851   void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
852   int scalarType = mapper->GetCurrentScalars()->GetDataType();
853 
854   // Nearest Neighbor interpolate
855   if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
856   {
857     // One component data
858     if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
859     {
860       // Scale == 1.0 and shift == 0.0 - simple case (faster)
861       if ( mapper->GetTableScale()[0] == 1.0 &&
862            mapper->GetTableShift()[0] == 0.0 )
863       {
864         switch ( scalarType )
865         {
866           vtkTemplateMacro(
867             vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleNN(
868               static_cast<VTK_TT *>(data),
869               threadID, threadCount, mapper, vol) );
870         }
871       }
872       else
873       {
874         switch ( scalarType )
875         {
876           vtkTemplateMacro(
877             vtkFixedPointCompositeGOShadeHelperGenerateImageOneNN(
878               static_cast<VTK_TT *>(data),
879               threadID, threadCount, mapper, vol) );
880         }
881       }
882     }
883     // More that one independent components
884     else if ( vol->GetProperty()->GetIndependentComponents() )
885     {
886       switch ( scalarType )
887       {
888         vtkTemplateMacro(
889           vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentNN(
890             static_cast<VTK_TT *>(data),
891             threadID, threadCount, mapper, vol) );
892       }
893     }
894     // Dependent (color) components
895     else
896     {
897       // Two components - the first specifies color (through a lookup table)
898       // and the second specified opacity (through a lookup table)
899       if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
900       {
901         switch ( scalarType )
902         {
903           vtkTemplateMacro(
904             vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentNN(
905               static_cast<VTK_TT *>(data),
906               threadID, threadCount, mapper, vol) );
907         }
908       }
909       // Four components - they must be unsigned char, the first three directly
910       // specify color and the fourth specifies opacity (through a lookup
911       // table)
912       else
913       {
914         if ( scalarType == VTK_UNSIGNED_CHAR )
915         {
916           vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentNN(
917             static_cast<unsigned char *>(data), threadID, threadCount, mapper,
918             vol );
919         }
920         else
921         {
922           vtkErrorMacro("Four component dependent data must be unsigned char");
923         }
924       }
925     }
926   }
927   // Trilinear Interpolation
928   else
929   {
930     // One component
931     if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
932     {
933       // Scale == 1.0 and shift == 0.0 - simple case (faster)
934       if ( mapper->GetTableScale()[0] == 1.0 &&
935            mapper->GetTableShift()[0] == 0.0 )
936       {
937         switch ( scalarType )
938         {
939           vtkTemplateMacro(
940             vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleTrilin(
941               static_cast<VTK_TT *>(data),
942               threadID, threadCount, mapper, vol) );
943         }
944       }
945       // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
946       else
947       {
948         switch ( scalarType )
949         {
950           vtkTemplateMacro(
951             vtkFixedPointCompositeGOShadeHelperGenerateImageOneTrilin(
952               static_cast<VTK_TT *>(data),
953               threadID, threadCount, mapper, vol) );
954         }
955       }
956     }
957     // Independent components (more than one)
958     else if ( vol->GetProperty()->GetIndependentComponents() )
959     {
960       switch ( scalarType )
961       {
962         vtkTemplateMacro(
963           vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentTrilin(
964             static_cast<VTK_TT *>(data),
965             threadID, threadCount, mapper, vol) );
966       }
967     }
968     // Dependent components
969     else
970     {
971       // Two components - the first specifies color (through a lookup table)
972       // and the second specified opacity (through a lookup table)
973       if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
974       {
975         switch ( scalarType )
976         {
977           vtkTemplateMacro(
978             vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentTrilin(
979               static_cast<VTK_TT *>(data),
980               threadID, threadCount, mapper, vol) );
981         }
982       }
983       // Four components - they must be unsigned char, the first three directly
984       // specify color and the fourth specifies opacity (through a lookup
985       // table)
986       else
987       {
988         if ( scalarType == VTK_UNSIGNED_CHAR )
989         {
990           vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentTrilin(
991             static_cast<unsigned char *>(data), threadID, threadCount, mapper,
992             vol );
993         }
994         else
995         {
996           vtkErrorMacro("Four component dependent data must be unsigned char");
997         }
998       }
999     }
1000   }
1001 }
1002 
1003 // Print method for vtkFixedPointVolumeRayCastCompositeGOShadeHelper
PrintSelf(ostream & os,vtkIndent indent)1004 void vtkFixedPointVolumeRayCastCompositeGOShadeHelper::PrintSelf(ostream& os, vtkIndent indent)
1005 {
1006   this->Superclass::PrintSelf(os,indent);
1007 }
1008 
1009