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