vtkFixedPointVolumeRayCastCompositeGOHelper.cxx 32.9 KB
Newer Older
1 2 3 4 5 6
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFixedPointVolumeRayCastCompositeGOHelper.cxx
  Language:  C++

7
  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
8 9 10
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

11 12
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 14 15 16 17 18 19 20 21 22 23 24
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkFixedPointVolumeRayCastCompositeGOHelper.h"

#include "vtkImageData.h"
#include "vtkCommand.h"
#include "vtkFixedPointVolumeRayCastMapper.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindow.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
25
#include "vtkFixedPointRayCastImage.h"
26
#include "vtkDataArray.h"
27

28
#include <cmath>
29 30 31 32

vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeGOHelper);

// Construct a new vtkFixedPointVolumeRayCastCompositeGOHelper with default values
33
vtkFixedPointVolumeRayCastCompositeGOHelper::vtkFixedPointVolumeRayCastCompositeGOHelper() = default;
34 35

// Destruct a vtkFixedPointVolumeRayCastCompositeGOHelper - clean up any memory used
36
vtkFixedPointVolumeRayCastCompositeGOHelper::~vtkFixedPointVolumeRayCastCompositeGOHelper() = default;
37 38 39


// This method is used when the interpolation type is nearest neighbor and
40 41 42
// the data has one component and scale == 1.0 and shift == 0.0. In the inner
// loop we get the data value as an unsigned short, and use this index to
// lookup a color and opacity for this sample. We then composite this into
43 44 45 46
// the color computed so far along the ray, and check if we can terminate at
// this point (if the accumulated opacity is higher than some threshold).
// Finally we move on to the next sample along the ray.
template <class T>
47
void vtkFixedPointCompositeGOHelperGenerateImageOneSimpleNN( T *data,
48 49 50 51 52 53 54 55 56
                                                   int threadID,
                                                   int threadCount,
                                                   vtkFixedPointVolumeRayCastMapper *mapper,
                                                   vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGONN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeGONN();
  VTKKWRCHelper_SpaceLeapSetup();
57

58
  for ( k = 0; k < numSteps; k++ )
59
  {
60
    if ( k )
61
    {
62
      VTKKWRCHelper_MoveToNextSampleGONN();
63
    }
64

65 66 67 68 69 70
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckNN( pos );

    unsigned short val = static_cast<unsigned short>(((*dptr)));
    unsigned char  mag = *magPtr;

71
    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
72
                                   gradientOpacityTable[0], val, mag, tmp );
73

74
    if ( tmp[3] )
75
    {
76 77
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
    }
78
  }
79 80

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
81 82 83 84 85 86 87 88 89 90 91
  VTKKWRCHelper_IncrementAndLoopEnd();
}

// This method is used when the interpolation type is nearest neighbor and
// the data has one component. In the inner loop we get the data value as
// an unsigned short using the scale/shift, and use this index to lookup
// a color and opacity for this sample. We then composite this into the
// color computed so far along the ray, and check if we can terminate at
// this point (if the accumulated opacity is higher than some threshold).
// Finally we move on to the next sample along the ray.
template <class T>
92
void vtkFixedPointCompositeGOHelperGenerateImageOneNN( T *data,
93 94 95 96 97 98 99 100 101
                                             int threadID,
                                             int threadCount,
                                             vtkFixedPointVolumeRayCastMapper *mapper,
                                             vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGONN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeGONN();
  VTKKWRCHelper_SpaceLeapSetup();
102

103
  for ( k = 0; k < numSteps; k++ )
104
  {
105
    if ( k )
106
    {
107
      VTKKWRCHelper_MoveToNextSampleGONN();
108
    }
109

110 111 112 113 114 115
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckNN( pos );

    unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
    unsigned char  mag = *magPtr;

116
    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
117 118 119
                                   gradientOpacityTable[0], val, mag, tmp );

    if ( tmp[3] )
120
    {
121 122
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
    }
123
  }
124 125

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
126 127 128 129 130 131 132 133
  VTKKWRCHelper_IncrementAndLoopEnd();
}


// This method is used when the interpolation type is nearest neighbor and
// the data has two components which are not considered independent. In the
// inner loop we compute the two unsigned short index values from the data
// values (using the scale/shift). We use the first index to lookup a color,
134 135
// and we use the second index to look up the opacity. We then composite
// the color into the color computed so far along this ray, and check to
136 137 138
// see if we can terminate here (if the opacity accumulated exceed some
// threshold). Finally we move to the next sample along the ray.
template <class T>
139
void vtkFixedPointCompositeGOHelperGenerateImageTwoDependentNN( T *data,
140 141 142 143 144 145 146 147 148
                                                      int threadID,
                                                      int threadCount,
                                                      vtkFixedPointVolumeRayCastMapper *mapper,
                                                      vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGONN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeGONN();
  VTKKWRCHelper_SpaceLeapSetup();
149

150
  for ( k = 0; k < numSteps; k++ )
151
  {
152
    if ( k )
153
    {
154
      VTKKWRCHelper_MoveToNextSampleGONN();
155
    }
156

157 158 159 160 161 162 163
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckNN( pos );

    unsigned short val[2];
    val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
    val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
    unsigned char  mag = *magPtr;
164

165 166
    tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
    if ( !tmp[3] )
167
    {
168
      continue;
169
    }
170

171 172 173 174 175 176
    tmp[0] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
    tmp[1] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
    tmp[2] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
177

178
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
179
  }
180

181
  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
182 183 184 185 186 187 188 189 190 191
  VTKKWRCHelper_IncrementAndLoopEnd();
}

// This method is used when the interpolation type is nearest neighbor and
// the data has four components which are not considered independent . This
// means that the first three components directly represent color, and this
// data must be of unsigned char type. In the inner loop we directly access
// the four data values (no scale/shift is needed). The first three are the
// color of this sample and the fourth is used to look up an opacity in the
// scalar opacity transfer function. We then composite this color into the
192 193
// color we have accumulated so far along the ray, and check if we can
// terminate here (if our accumulated opacity has exceed some threshold).
194 195
// Finally we move onto the next sample along the ray.
template <class T>
196
void vtkFixedPointCompositeGOHelperGenerateImageFourDependentNN( T *data,
197 198 199 200 201 202 203 204 205 206 207
                                                         int threadID,
                                                         int threadCount,
                                                         vtkFixedPointVolumeRayCastMapper *mapper,
                                                         vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGONN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeGONN();
  VTKKWRCHelper_SpaceLeapSetup();

  for ( k = 0; k < numSteps; k++ )
208
  {
209
    if ( k )
210
    {
211
      VTKKWRCHelper_MoveToNextSampleGONN();
212
    }
213

214 215 216 217 218 219 220
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckNN( pos );

    unsigned short val[4];
    val[0] = *(dptr  );
    val[1] = *(dptr+1);
    val[2] = *(dptr+2);
221
    val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
222

223
    unsigned char  mag = *magPtr;
224

225
    tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
226
    if ( !tmp[3] )
227
    {
228
      continue;
229
    }
230

231 232 233
    tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
    tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
    tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
234

235
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
236
  }
237 238

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
239 240 241 242 243 244 245 246 247 248
  VTKKWRCHelper_IncrementAndLoopEnd();
}

// This method is used when the interpolation type is nearest neighbor and
// the data has more than one component and the components are considered to
// be independent. In the inner loop we access each component value, using
// the scale/shift to turn the data value into an unsigned short index. We
// then lookup the color/opacity for each component and combine them according
// to the weighting value for each component. We composite this resulting
// color into the color already accumulated for this ray, and we check
249
// whether we can terminate here (if the accumulated opacity exceeds some
250 251
// threshold). Finally we increment to the next sample on the ray.
template <class T>
252
void vtkFixedPointCompositeGOHelperGenerateImageIndependentNN( T *data,
253 254 255 256 257
                                                     int threadID,
                                                     int threadCount,
                                                     vtkFixedPointVolumeRayCastMapper *mapper,
                                                     vtkVolume *vol)
{
258
  VTKKWRCHelper_InitializeWeights();
259 260 261
  VTKKWRCHelper_InitializationAndLoopStartGONN();
  VTKKWRCHelper_InitializeCompositeMultiNN();
  VTKKWRCHelper_InitializeCompositeGONN();
262

263
  for ( k = 0; k < numSteps; k++ )
264
  {
265
    if ( k )
266
    {
267
      VTKKWRCHelper_MoveToNextSampleGONN();
268
    }
269

270 271
    VTKKWRCHelper_CroppingCheckNN( pos );

272
    unsigned char mag[4] = { 1, 1, 1, 1 };
273
    for ( c = 0; c < components; c++ )
274
    {
275 276
      val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
      mag[c] = static_cast<unsigned short>(*(magPtr+c));
277
    }
278

279 280
    VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable,
                                                         gradientOpacityTable,
281
                                                         val, mag, weights, components, tmp );
282 283

    if ( tmp[3] )
284
    {
285 286
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
    }
287
  }
288 289

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
290 291 292
  VTKKWRCHelper_IncrementAndLoopEnd();
}

293 294
// This method is used when the interpolation type is linear and the data
// has one component and scale = 1.0 and shift = 0.0. In the inner loop we
295
// get the data value for the eight cell corners (if we have changed cells)
296 297
// as an unsigned short (the range must be right and we don't need the
// scale/shift). We compute our weights within the cell according to our
298
// fractional position within the cell, apply trilinear interpolation to
299 300 301 302
// compute the index, and use this index to lookup a color and opacity for
// this sample. We then composite this into the color computed so far along
// the ray, and check if we can terminate at this point (if the accumulated
// opacity is higher than some threshold). Finally we move on to the next
303 304
// sample along the ray.
template <class T>
305
void vtkFixedPointCompositeGOHelperGenerateImageOneSimpleTrilin( T *data,
306 307 308 309 310 311 312 313 314 315 316 317
                                                       int threadID,
                                                       int threadCount,
                                                       vtkFixedPointVolumeRayCastMapper *mapper,
                                                       vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
  VTKKWRCHelper_InitializeCompositeOneTrilin();
  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
  VTKKWRCHelper_SpaceLeapSetup();

  int needToSampleGO = 0;
  for ( k = 0; k < numSteps; k++ )
318
  {
319
    if ( k )
320
    {
321
      mapper->FixedPointIncrement( pos, dir );
322
    }
323 324

    VTKKWRCHelper_SpaceLeapCheck();
325
    VTKKWRCHelper_CroppingCheckTrilin( pos );
326

327 328 329 330
    mapper->ShiftVectorDown( pos, spos );
    if ( spos[0] != oldSPos[0] ||
         spos[1] != oldSPos[1] ||
         spos[2] != oldSPos[2] )
331
    {
332 333 334
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
335

336 337 338 339 340
      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
      VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
      needToSampleGO = 1;
341
    }
342

343 344 345 346
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalar(val);

    tmp[3] = scalarOpacityTable[0][val];
347
    if ( !tmp[3] )
348
    {
349
      continue;
350
    }
351

352
    if ( needToSampleGO )
353
    {
354 355
      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
      needToSampleGO = 0;
356
    }
357

358
    VTKKWRCHelper_InterpolateMagnitude(mag);
359 360
    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
    if ( !tmp[3] )
361
    {
362
      continue;
363
    }
364 365

    tmp[0] = static_cast<unsigned short>
366
      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
367
    tmp[1] = static_cast<unsigned short>
368
      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
369 370 371
    tmp[2] = static_cast<unsigned short>
      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));

372
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
373

374
  }
375 376

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
377 378 379
  VTKKWRCHelper_IncrementAndLoopEnd();
}

380 381
// This method is used when the interpolation type is linear and the data
// has one component and scale != 1.0 or shift != 0.0. In the inner loop we
382
// get the data value for the eight cell corners (if we have changed cells)
383 384 385 386 387 388
// as an unsigned short (we use the scale/shift to ensure the correct range).
// We compute our weights within the cell according to our fractional position
// within the cell, apply trilinear interpolation to compute the index, and use
// this index to lookup a color and opacity for this sample. We then composite
// this into the color computed so far along the ray, and check if we can
// terminate at this point (if the accumulated opacity is higher than some
389 390
// threshold). Finally we move on to the next sample along the ray.
template <class T>
391
void vtkFixedPointCompositeGOHelperGenerateImageOneTrilin( T *data,
392 393 394 395 396 397 398 399 400
                                                 int threadID,
                                                 int threadCount,
                                                 vtkFixedPointVolumeRayCastMapper *mapper,
                                                 vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
  VTKKWRCHelper_InitializeCompositeOneTrilin();
  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
401 402

  int needToSampleGO = 0;
403
  for ( k = 0; k < numSteps; k++ )
404
  {
405
    if ( k )
406
    {
407
      mapper->FixedPointIncrement( pos, dir );
408
    }
409

410 411
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckTrilin( pos );
412

413 414 415 416
    mapper->ShiftVectorDown( pos, spos );
    if ( spos[0] != oldSPos[0] ||
         spos[1] != oldSPos[1] ||
         spos[2] != oldSPos[2] )
417
    {
418 419 420
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
421 422


423 424 425 426 427
      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
      VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
      needToSampleGO = 1;
428
    }
429

430 431 432 433
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalar(val);

    tmp[3] = scalarOpacityTable[0][val];
434
    if ( !tmp[3] )
435
    {
436
      continue;
437
    }
438

439
    if ( needToSampleGO )
440
    {
441 442
      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
      needToSampleGO = 0;
443
    }
444
    VTKKWRCHelper_InterpolateMagnitude(mag);
445 446 447

    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
    if ( !tmp[3] )
448
    {
449
      continue;
450
    }
451 452

    tmp[0] = static_cast<unsigned short>
453
      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
454
    tmp[1] = static_cast<unsigned short>
455
      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
456 457
    tmp[2] = static_cast<unsigned short>
      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
458

459
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
460
  }
461 462

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
463 464 465 466
  VTKKWRCHelper_IncrementAndLoopEnd();
}


467
// This method is used when the interpolation type is linear, the data has
468
// two components and the components are not considered independent. In the
469 470 471 472 473 474 475 476 477
// inner loop we get the data value for the eight cell corners (if we have
// changed cells) for both components as an unsigned shorts (we use the
// scale/shift to ensure the correct range). We compute our weights within
// the cell according to our fractional position within the cell, and apply
// trilinear interpolation to compute the two index value. We use the first
// index to lookup a color and the second to look up an opacity for this sample.
// We then composite this into the color computed so far along the ray, and
// check if we can terminate at this point (if the accumulated opacity is
// higher than some threshold). Finally we move on to the next sample along
478 479
// the ray.
template <class T>
480
void vtkFixedPointCompositeGOHelperGenerateImageTwoDependentTrilin( T *data,
481 482 483 484 485 486 487 488 489
                                                          int threadID,
                                                          int threadCount,
                                                          vtkFixedPointVolumeRayCastMapper *mapper,
                                                          vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
490 491

  int needToSampleGO = 0;
492
  for ( k = 0; k < numSteps; k++ )
493
  {
494
    if ( k )
495
    {
496
      mapper->FixedPointIncrement( pos, dir );
497
    }
498

499 500
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckTrilin( pos );
501

502 503 504 505
    mapper->ShiftVectorDown( pos, spos );
    if ( spos[0] != oldSPos[0] ||
         spos[1] != oldSPos[1] ||
         spos[2] != oldSPos[2] )
506
    {
507 508 509
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
510

511 512
      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
513

514 515 516 517 518 519
      dptr++;
      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );

      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
      needToSampleGO = 1;
520
    }
521

522 523
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
524

525
    tmp[3] = scalarOpacityTable[0][val[1]];
526
    if ( !tmp[3] )
527
    {
528
      continue;
529
    }
530

531
    if ( needToSampleGO )
532
    {
533 534
      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
      needToSampleGO = 0;
535
    }
536

537
    VTKKWRCHelper_InterpolateMagnitude(mag);
538
    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
539
    if ( !tmp[3] )
540
    {
541
      continue;
542
    }
543

544 545 546 547 548 549
    tmp[0] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
    tmp[1] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
    tmp[2] = static_cast<unsigned short>
      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
550

551
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
552
  }
553

554
  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
555 556 557 558 559
  VTKKWRCHelper_IncrementAndLoopEnd();
}



560
// This method is used when the interpolation type is linear, the data has
561
// four components and the components are not considered independent. In the
562
// inner loop we get the data value for the eight cell corners (if we have
563 564
// changed cells) for all components as an unsigned shorts (we don't have to
// use the scale/shift because only unsigned char data is supported for four
565 566 567
// component data when the components are not independent). We compute our
// weights within the cell according to our fractional position within the cell,
// and apply trilinear interpolation to compute a value for each component. We
568
// use the first three directly as the color of the sample, and the fourth is
569 570 571
// used to look up an opacity for this sample. We then composite this into the
// color computed so far along the ray, and check if we can terminate at this
// point (if the accumulated opacity is higher than some threshold). Finally we
572 573
// move on to the next sample along the ray.
template <class T>
574
void vtkFixedPointCompositeGOHelperGenerateImageFourDependentTrilin( T *data,
575 576 577 578 579 580 581 582 583
                                                             int threadID,
                                                             int threadCount,
                                                             vtkFixedPointVolumeRayCastMapper *mapper,
                                                             vtkVolume *vol)
{
  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
584

585 586
  int needToSampleGO = 0;
  for ( k = 0; k < numSteps; k++ )
587
  {
588
    if ( k )
589
    {
590
      mapper->FixedPointIncrement( pos, dir );
591
    }
592

593 594
    VTKKWRCHelper_SpaceLeapCheck();
    VTKKWRCHelper_CroppingCheckTrilin( pos );
595

596 597 598 599
    mapper->ShiftVectorDown( pos, spos );
    if ( spos[0] != oldSPos[0] ||
         spos[1] != oldSPos[1] ||
         spos[2] != oldSPos[2] )
600
    {
601 602 603
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
604

605
      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
606
      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
607

608
      dptr++;
609
      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
610

611
      dptr++;
612
      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
613

614 615
      dptr++;
      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
616

617 618 619
      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
      needToSampleGO = 1;
620
    }
621

622 623
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalarComponent( val, c, 4 );
624

625
    tmp[3] = scalarOpacityTable[0][val[3]];
626
    if ( !tmp[3] )
627
    {
628
      continue;
629
    }
630

631
    if ( needToSampleGO )
632
    {
633 634
      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
      needToSampleGO = 0;
635
    }
636

637
    VTKKWRCHelper_InterpolateMagnitude(mag);
638
    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
639
    if ( !tmp[3] )
640
    {
641
      continue;
642
    }
643

644 645 646
    tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
    tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
    tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
647 648

    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
649
  }
650 651

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
652 653 654
  VTKKWRCHelper_IncrementAndLoopEnd();
}

655 656 657
// This method is used when the interpolation type is linear, the data has
// more than one component and the components are considered independent. In
// the inner loop we get the data value for the eight cell corners (if we have
658
// changed cells) for all components as an unsigned shorts (we have to use the
659 660 661 662 663 664 665
// scale/shift to ensure that we obtained unsigned short indices) We compute our
// weights within the cell according to our fractional position within the cell,
// and apply trilinear interpolation to compute a value for each component. We
// look up a color/opacity for each component and blend them according to the
// component weights. We then composite this resulting color into the
// color computed so far along the ray, and check if we can terminate at this
// point (if the accumulated opacity is higher than some threshold). Finally we
666 667
// move on to the next sample along the ray.
template <class T>
668
void vtkFixedPointCompositeGOHelperGenerateImageIndependentTrilin( T *data,
669 670 671 672 673
                                                         int threadID,
                                                         int threadCount,
                                                         vtkFixedPointVolumeRayCastMapper *mapper,
                                                         vtkVolume *vol)
{
674
  VTKKWRCHelper_InitializeWeights();
675 676 677 678 679
  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeMultiGOTrilin();

  for ( k = 0; k < numSteps; k++ )
680
  {
681
    if ( k )
682
    {
683
      mapper->FixedPointIncrement( pos, dir );
684
    }
685

686
    VTKKWRCHelper_CroppingCheckTrilin( pos );
687

688 689 690 691
    mapper->ShiftVectorDown( pos, spos );
    if ( spos[0] != oldSPos[0] ||
         spos[1] != oldSPos[1] ||
         spos[2] != oldSPos[2] )
692
    {
693 694 695
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
696

697 698
      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
699

700 701
      dptr++;
      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
702

703
      if ( components > 2 )
704
      {
705 706 707
        dptr++;
        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
        if ( components > 3 )
708
        {
709 710 711
          dptr++;
          VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
        }
712
      }
713 714


715 716
      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
717 718
      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 );

719 720
      magPtrABCD++;
      magPtrEFGH++;
721 722
      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 );

723
      if ( components > 2 )
724
      {
725 726
        magPtrABCD++;
        magPtrEFGH++;
727
        VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 );
728
        if ( components > 3 )
729
        {
730 731
          magPtrABCD++;
          magPtrEFGH++;
732
          VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 );
733 734
        }
      }
735
    }
736

737 738 739
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
    VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components );
740

741 742
    VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable,
                                                         gradientOpacityTable, val, mag,
743 744
                                                         weights, components, tmp );

745
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
746

747
  }
748 749

  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
750 751 752 753 754 755 756 757 758
  VTKKWRCHelper_IncrementAndLoopEnd();
}


void vtkFixedPointVolumeRayCastCompositeGOHelper::GenerateImage( int threadID,
                                                 int threadCount,
                                                 vtkVolume *vol,
                                                 vtkFixedPointVolumeRayCastMapper *mapper )
{
759 760
  void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
  int scalarType = mapper->GetCurrentScalars()->GetDataType();
761 762 763

  // Nearest Neighbor interpolate
  if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
764
  {
765
    // One component data
766
    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
767
    {
768 769
      // Scale == 1.0 and shift == 0.0 - simple case (faster)
      if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 )
770
      {
771
        switch ( scalarType )
772
        {
773
          vtkTemplateMacro(
774
            vtkFixedPointCompositeGOHelperGenerateImageOneSimpleNN(
775
              static_cast<VTK_TT *>(data),
776
              threadID, threadCount, mapper, vol) );
777
        }
778
      }
779
      else
780
      {
781
        switch ( scalarType )
782
        {
783
          vtkTemplateMacro(
784
            vtkFixedPointCompositeGOHelperGenerateImageOneNN(
785
              static_cast<VTK_TT *>(data),
786
              threadID, threadCount, mapper, vol) );
787 788
        }
      }
789
    }
790 791
    // More that one independent components
    else if ( vol->GetProperty()->GetIndependentComponents() )
792
    {
793
      switch ( scalarType )
794
      {
795 796
        vtkTemplateMacro(
          vtkFixedPointCompositeGOHelperGenerateImageIndependentNN(
797
            static_cast<VTK_TT *>(data),
798
            threadID, threadCount, mapper, vol) );
799
      }
800
    }
801 802
    // Dependent (color) components
    else
803
    {
804 805
      // Two components - the first specifies color (through a lookup table) and
      // the second specified opacity (through a lookup table)
806
      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
807
      {
808
        switch ( scalarType )
809
        {
810
          vtkTemplateMacro(
811
            vtkFixedPointCompositeGOHelperGenerateImageTwoDependentNN(
812
              static_cast<VTK_TT *>(data),
813
              threadID, threadCount, mapper, vol) );
814
        }
815
      }
816 817 818
      // Four components - they must be unsigned char, the first three directly
      // specify color and the fourth specifies opacity (through a lookup table)
      else
819
      {
820
        if ( scalarType == VTK_UNSIGNED_CHAR )
821
        {
822
          vtkFixedPointCompositeGOHelperGenerateImageFourDependentNN(
823 824
            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
            vol );
825
        }
826
        else
827
        {
828 829 830 831
          vtkErrorMacro("Four component dependent must be unsigned char!");
        }
      }
    }
832
  }
833 834
  // Trilinear Interpolation
  else
835
  {
836
    // One component
837
    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
838
    {
839
      // Scale == 1.0 and shift == 0.0 - simple case (faster)
840 841
      if ( mapper->GetTableScale()[0] == 1.0 &&
           mapper->GetTableShift()[0] == 0.0 )
842
      {
843
        switch ( scalarType )
844
        {
845
          vtkTemplateMacro(
846
            vtkFixedPointCompositeGOHelperGenerateImageOneSimpleTrilin(
847
              static_cast<VTK_TT *>(data),
848
              threadID, threadCount, mapper, vol) );
849
        }
850
      }
851 852
      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
      else
853
      {
854
        switch ( scalarType )
855
        {
856
          vtkTemplateMacro(
857
            vtkFixedPointCompositeGOHelperGenerateImageOneTrilin(
858
              static_cast<VTK_TT *>(data),
859
              threadID, threadCount, mapper, vol) );
860 861
        }
      }
862
    }
luz.paz's avatar
luz.paz committed
863
    // Independent components (more than one)
864
    else if ( vol->GetProperty()->GetIndependentComponents() )
865
    {
866
      switch ( scalarType )
867
      {
868
        vtkTemplateMacro(
869
          vtkFixedPointCompositeGOHelperGenerateImageIndependentTrilin(
870
            static_cast<VTK_TT *>(data),
871
            threadID, threadCount, mapper, vol) );
872
      }
873
    }
874 875
    // Dependent components
    else
876
    {
877 878
      // Two components - the first specifies color (through a lookup table)
      // and the second specified opacity (through a lookup table)
879
      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
880
      {
881
        switch ( scalarType )
882
        {
883
          vtkTemplateMacro(
884
            vtkFixedPointCompositeGOHelperGenerateImageTwoDependentTrilin(
885
              static_cast<VTK_TT *>(data),
886
              threadID, threadCount, mapper, vol) );
887
        }
888
      }
889
      // Four components - they must be unsigned char, the first three directly
890 891
      // specify color and the fourth specifies opacity (through a lookup
      // table)
892
      else
893
      {
894
        if ( scalarType == VTK_UNSIGNED_CHAR )
895
        {
896
          vtkFixedPointCompositeGOHelperGenerateImageFourDependentTrilin(
897 898
            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
            vol );
899
        }
900
        else
901
        {
902 903 904 905
          vtkErrorMacro("Four component dependent must be unsigned char!");
        }
      }
    }
906
  }
907 908 909 910 911 912 913 914
}

// Print method for vtkFixedPointVolumeRayCastCompositeGOHelper
void vtkFixedPointVolumeRayCastCompositeGOHelper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}