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