vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx 29.4 KB
Newer Older
1 2 3 4 5 6
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFixedPointVolumeRayCastCompositeShadeHelper.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
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkCommand.h"
19 20
#include "vtkDataArray.h"
#include "vtkFixedPointRayCastImage.h"
21
#include "vtkFixedPointVolumeRayCastMapper.h"
22
#include "vtkImageData.h"
23 24 25 26 27
#include "vtkObjectFactory.h"
#include "vtkRenderWindow.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"

Sean McBride's avatar
Sean McBride committed
28
#include <cmath>
29 30 31 32

vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeShadeHelper);

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

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

// This method is used when the interpolation type is nearest neighbor and
41 42 43
// 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
44 45 46 47
// 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>
48 49
void vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleNN(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
50 51 52 53 54 55
{
  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeShadeNN();
  VTKKWRCHelper_SpaceLeapSetup();

56
  for (k = 0; k < numSteps; k++)
57
  {
58
    if (k)
59
    {
60
      VTKKWRCHelper_MoveToNextSampleShadeNN();
61
    }
62 63

    VTKKWRCHelper_SpaceLeapCheck();
64
    VTKKWRCHelper_CroppingCheckNN(pos);
65

66 67
    unsigned short val = static_cast<unsigned short>(((*dptr)));
    VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
68
    if (tmp[3])
69
    {
70
      unsigned short normal = *dirPtr;
71 72
      VTKKWRCHelper_LookupShading(diffuseShadingTable[0], specularShadingTable[0], normal, tmp);
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
73
    }
74
  }
75

76
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
77 78 79 80 81 82 83 84 85 86 87
  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>
88 89
void vtkFixedPointCompositeShadeHelperGenerateImageOneNN(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
90 91 92 93 94
{
  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeShadeNN();
  VTKKWRCHelper_SpaceLeapSetup();
95

96
  for (k = 0; k < numSteps; k++)
97
  {
98
    if (k)
99
    {
100
      VTKKWRCHelper_MoveToNextSampleShadeNN();
101
    }
102 103

    VTKKWRCHelper_SpaceLeapCheck();
104
    VTKKWRCHelper_CroppingCheckNN(pos);
105

106 107
    unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0]) * scale[0]);
    VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
108
    if (tmp[3])
109
    {
110
      unsigned short normal = *dirPtr;
111 112
      VTKKWRCHelper_LookupShading(diffuseShadingTable[0], specularShadingTable[0], normal, tmp);
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
113
    }
114
  }
115

116
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
117 118 119 120 121 122 123
  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,
124 125
// 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
126 127 128
// 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>
129 130
void vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentNN(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
131 132 133 134 135
{
  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeShadeNN();
  VTKKWRCHelper_SpaceLeapSetup();
136

137
  for (k = 0; k < numSteps; k++)
138
  {
139
    if (k)
140
    {
141
      VTKKWRCHelper_MoveToNextSampleShadeNN();
142
    }
143

144
    VTKKWRCHelper_SpaceLeapCheck();
145
    VTKKWRCHelper_CroppingCheckNN(pos);
146

147
    unsigned short val[2];
148 149
    val[0] = static_cast<unsigned short>(((*(dptr)) + shift[0]) * scale[0]);
    val[1] = static_cast<unsigned short>(((*(dptr + 1)) + shift[1]) * scale[1]);
150

151 152
    tmp[3] = scalarOpacityTable[0][val[1]];
    if (tmp[3])
153
    {
154 155 156 157 158 159
      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));
160 161

      unsigned short normal = *dirPtr;
162 163
      VTKKWRCHelper_LookupShading(diffuseShadingTable[0], specularShadingTable[0], normal, tmp);
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
164
    }
165
  }
166

167
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
168 169 170 171 172 173 174 175 176 177
  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
178 179
// color we have accumulated so far along the ray, and check if we can
// terminate here (if our accumulated opacity has exceed some threshold).
180 181
// Finally we move onto the next sample along the ray.
template <class T>
182 183
void vtkFixedPointCompositeShadeHelperGenerateImageFourDependentNN(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
184 185 186 187 188 189
{
  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
  VTKKWRCHelper_InitializeCompositeOneNN();
  VTKKWRCHelper_InitializeCompositeShadeNN();
  VTKKWRCHelper_SpaceLeapSetup();

190
  for (k = 0; k < numSteps; k++)
191
  {
192
    if (k)
193
    {
194
      VTKKWRCHelper_MoveToNextSampleShadeNN();
195
    }
196 197

    VTKKWRCHelper_SpaceLeapCheck();
198
    VTKKWRCHelper_CroppingCheckNN(pos);
199

200
    unsigned short val[4];
201 202 203 204
    val[0] = *(dptr);
    val[1] = *(dptr + 1);
    val[2] = *(dptr + 2);
    val[3] = static_cast<unsigned short>(((*(dptr + 3)) + shift[3]) * scale[3]);
205

206
    tmp[3] = scalarOpacityTable[0][val[3]];
207
    if (tmp[3])
208
    {
209 210 211
      tmp[0] = (val[0] * tmp[3] + 0x7f) >> (8);
      tmp[1] = (val[1] * tmp[3] + 0x7f) >> (8);
      tmp[2] = (val[2] * tmp[3] + 0x7f) >> (8);
212

213 214 215
      unsigned short normal = *dirPtr;
      VTKKWRCHelper_LookupShading(diffuseShadingTable[0], specularShadingTable[0], normal, tmp);
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
216
    }
217
  }
218

219
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
220 221 222 223 224 225 226 227 228 229
  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
luz.paz's avatar
luz.paz committed
230
// whether we can terminate here (if the accumulated opacity exceeds some
231 232 233 234
// threshold). Finally we increment to the next sample on the ray.
//
// TODO: short circuit calculations when opacity is 0
template <class T>
235 236
void vtkFixedPointCompositeShadeHelperGenerateImageIndependentNN(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
237
{
238
  VTKKWRCHelper_InitializeWeights();
239 240 241
  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
  VTKKWRCHelper_InitializeCompositeMultiNN();
  VTKKWRCHelper_InitializeCompositeShadeNN();
242

243
  for (k = 0; k < numSteps; k++)
244
  {
245
    if (k)
246
    {
247
      VTKKWRCHelper_MoveToNextSampleShadeNN();
248
    }
249

250
    VTKKWRCHelper_CroppingCheckNN(pos);
251

252
    unsigned short normal[4];
253
    for (c = 0; c < components; c++)
254
    {
255 256
      val[c] = static_cast<unsigned short>(((*(dptr + c)) + shift[c]) * scale[c]);
      normal[c] = *(dirPtr + c);
257
    }
258

259 260
    VTKKWRCHelper_LookupAndCombineIndependentColorsShadeUS(colorTable, scalarOpacityTable,
      diffuseShadingTable, specularShadingTable, val, normal, weights, components, tmp);
261

262
    if (tmp[3])
263
    {
264
      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
265
    }
266
  }
267

268
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
269 270 271
  VTKKWRCHelper_IncrementAndLoopEnd();
}

272 273
// 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
274
// get the data value for the eight cell corners (if we have changed cells)
275 276
// 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
277
// fractional position within the cell, apply trilinear interpolation to
278 279 280 281
// 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
282 283
// sample along the ray.
template <class T>
284 285
void vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
286 287 288 289 290 291 292
{
  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
  VTKKWRCHelper_InitializeCompositeOneTrilin();
  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
  VTKKWRCHelper_SpaceLeapSetup();

  int needToSampleDirection = 0;
293
  for (k = 0; k < numSteps; k++)
294
  {
295
    if (k)
296
    {
297
      mapper->FixedPointIncrement(pos, dir);
298
    }
299

300
    VTKKWRCHelper_SpaceLeapCheck();
301
    VTKKWRCHelper_CroppingCheckTrilin(pos);
302

303 304
    mapper->ShiftVectorDown(pos, spos);
    if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
305
    {
306 307 308
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
309

310 311 312 313
      dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
      VTKKWRCHelper_GetCellScalarValuesSimple(dptr);
      dirPtrABCD = gradientDir[spos[2]] + spos[0] * dInc[0] + spos[1] * dInc[1];
      dirPtrEFGH = gradientDir[spos[2] + 1] + spos[0] * dInc[0] + spos[1] * dInc[1];
314
      needToSampleDirection = 1;
315
    }
316

317 318
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalar(val);
319

320 321
    VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
    if (needToSampleDirection)
322
    {
323
      VTKKWRCHelper_GetCellDirectionValues(dirPtrABCD, dirPtrEFGH);
324
      needToSampleDirection = 0;
325
    }
326

327 328
    VTKKWRCHelper_InterpolateShading(diffuseShadingTable[0], specularShadingTable[0], tmp);
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
329
  }
330

331
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
332 333 334
  VTKKWRCHelper_IncrementAndLoopEnd();
}

335 336
// 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
337
// get the data value for the eight cell corners (if we have changed cells)
338 339 340 341 342 343
// 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
344 345
// threshold). Finally we move on to the next sample along the ray.
template <class T>
346 347
void vtkFixedPointCompositeShadeHelperGenerateImageOneTrilin(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
348 349 350 351 352
{
  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
  VTKKWRCHelper_InitializeCompositeOneTrilin();
  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
353

354
  int needToSampleDirection = 0;
355
  for (k = 0; k < numSteps; k++)
356
  {
357
    if (k)
358
    {
359
      mapper->FixedPointIncrement(pos, dir);
360
    }
361

362
    VTKKWRCHelper_SpaceLeapCheck();
363
    VTKKWRCHelper_CroppingCheckTrilin(pos);
364

365 366
    mapper->ShiftVectorDown(pos, spos);
    if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
367
    {
368 369 370
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
371

372 373 374 375
      dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
      VTKKWRCHelper_GetCellScalarValues(dptr, scale[0], shift[0]);
      dirPtrABCD = gradientDir[spos[2]] + spos[0] * dInc[0] + spos[1] * dInc[1];
      dirPtrEFGH = gradientDir[spos[2] + 1] + spos[0] * dInc[0] + spos[1] * dInc[1];
376
      needToSampleDirection = 1;
377
    }
378

379 380
    VTKKWRCHelper_ComputeWeights(pos);
    VTKKWRCHelper_InterpolateScalar(val);
381

382 383
    VTKKWRCHelper_LookupColorUS(colorTable[0], scalarOpacityTable[0], val, tmp);
    if (needToSampleDirection)
384
    {
385
      VTKKWRCHelper_GetCellDirectionValues(dirPtrABCD, dirPtrEFGH);
386
      needToSampleDirection = 0;
387
    }
388 389
    VTKKWRCHelper_InterpolateShading(diffuseShadingTable[0], specularShadingTable[0], tmp);
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
390
  }
391

392
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
393 394 395
  VTKKWRCHelper_IncrementAndLoopEnd();
}

396
// This method is used when the interpolation type is linear, the data has
397
// two components and the components are not considered independent. In the
398 399 400 401 402 403 404 405 406
// 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
407 408
// the ray.
template <class T>
409 410
void vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
411 412 413 414 415
{
  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
416

417
  int needToSampleDirection = 0;
418
  for (k = 0; k < numSteps; k++)
419
  {
420
    if (k)
421
    {
422
      mapper->FixedPointIncrement(pos, dir);
423
    }
424 425

    VTKKWRCHelper_SpaceLeapCheck();
426
    VTKKWRCHelper_CroppingCheckTrilin(pos);
427

428 429
    mapper->ShiftVectorDown(pos, spos);
    if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
430
    {
431 432 433
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
434

435 436
      dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
      VTKKWRCHelper_GetCellComponentScalarValues(dptr, 0, scale[0], shift[0]);
437

438
      dptr++;
439
      VTKKWRCHelper_GetCellComponentScalarValues(dptr, 1, scale[1], shift[1]);
440

441 442
      dirPtrABCD = gradientDir[spos[2]] + spos[0] * dInc[0] + spos[1] * dInc[1];
      dirPtrEFGH = gradientDir[spos[2] + 1] + spos[0] * dInc[0] + spos[1] * dInc[1];
443
      needToSampleDirection = 1;
444
    }
445

446
    VTKKWRCHelper_ComputeWeights(pos);
447
    VTKKWRCHelper_InterpolateScalarComponent(val, c, 2);
448

449
    tmp[3] = scalarOpacityTable[0][val[1]];
450
    if (!tmp[3])
451
    {
452
      continue;
453
    }
454

455
    if (needToSampleDirection)
456
    {
457
      VTKKWRCHelper_GetCellDirectionValues(dirPtrABCD, dirPtrEFGH);
458
      needToSampleDirection = 0;
459
    }
460

461 462 463 464 465 466
    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));
467

468 469
    VTKKWRCHelper_InterpolateShading(diffuseShadingTable[0], specularShadingTable[0], tmp);
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
470
  }
471

472
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
473 474 475
  VTKKWRCHelper_IncrementAndLoopEnd();
}

476
// This method is used when the interpolation type is linear, the data has
477
// four components and the components are not considered independent. In the
478
// inner loop we get the data value for the eight cell corners (if we have
479 480
// 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
481 482 483
// 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
484
// use the first three directly as the color of the sample, and the fourth is
485 486 487
// 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
488 489
// move on to the next sample along the ray.
template <class T>
490 491
void vtkFixedPointCompositeShadeHelperGenerateImageFourDependentTrilin(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
492 493 494 495 496
{
  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
  VTKKWRCHelper_SpaceLeapSetup();
497

498
  int needToSampleDirection = 0;
499
  for (k = 0; k < numSteps; k++)
500
  {
501
    if (k)
502
    {
503
      mapper->FixedPointIncrement(pos, dir);
504
    }
505 506

    VTKKWRCHelper_SpaceLeapCheck();
507
    VTKKWRCHelper_CroppingCheckTrilin(pos);
508

509 510
    mapper->ShiftVectorDown(pos, spos);
    if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
511
    {
512 513 514
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
515

516 517
      dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
      VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 0);
518

519
      dptr++;
520
      VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 1);
521

522
      dptr++;
523
      VTKKWRCHelper_GetCellComponentRawScalarValues(dptr, 2);
524

525
      dptr++;
526
      VTKKWRCHelper_GetCellComponentScalarValues(dptr, 3, scale[3], shift[3]);
527

528 529
      dirPtrABCD = gradientDir[spos[2]] + spos[0] * dInc[0] + spos[1] * dInc[1];
      dirPtrEFGH = gradientDir[spos[2] + 1] + spos[0] * dInc[0] + spos[1] * dInc[1];
530
      needToSampleDirection = 1;
531
    }
532

533
    VTKKWRCHelper_ComputeWeights(pos);
534
    VTKKWRCHelper_InterpolateScalarComponent(val, c, 4);
535

536
    tmp[3] = scalarOpacityTable[0][val[3]];
537
    if (!tmp[3])
538
    {
539
      continue;
540
    }
541

542
    if (needToSampleDirection)
543
    {
544
      VTKKWRCHelper_GetCellDirectionValues(dirPtrABCD, dirPtrEFGH);
545
      needToSampleDirection = 0;
546
    }
547

548 549 550
    tmp[0] = (val[0] * tmp[3] + 0x7f) >> 8;
    tmp[1] = (val[1] * tmp[3] + 0x7f) >> 8;
    tmp[2] = (val[2] * tmp[3] + 0x7f) >> 8;
551

552 553
    VTKKWRCHelper_InterpolateShading(diffuseShadingTable[0], specularShadingTable[0], tmp);
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
554
  }
555

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

560 561 562
// 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
563
// changed cells) for all components as an unsigned shorts (we have to use the
564 565 566 567 568 569 570
// 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
571 572
// move on to the next sample along the ray.
template <class T>
573 574
void vtkFixedPointCompositeShadeHelperGenerateImageIndependentTrilin(
  T* data, int threadID, int threadCount, vtkFixedPointVolumeRayCastMapper* mapper, vtkVolume* vol)
575
{
576
  VTKKWRCHelper_InitializeWeights();
577 578 579 580
  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
  VTKKWRCHelper_InitializeCompositeMultiTrilin();
  VTKKWRCHelper_InitializeCompositeMultiShadeTrilin();

581
  for (k = 0; k < numSteps; k++)
582
  {
583
    if (k)
584
    {
585
      mapper->FixedPointIncrement(pos, dir);
586
    }
587

588
    VTKKWRCHelper_CroppingCheckTrilin(pos);
589

590 591
    mapper->ShiftVectorDown(pos, spos);
    if (spos[0] != oldSPos[0] || spos[1] != oldSPos[1] || spos[2] != oldSPos[2])
592
    {
593 594 595
      oldSPos[0] = spos[0];
      oldSPos[1] = spos[1];
      oldSPos[2] = spos[2];
596

597 598
      dptr = data + spos[0] * inc[0] + spos[1] * inc[1] + spos[2] * inc[2];
      VTKKWRCHelper_GetCellComponentScalarValues(dptr, 0, scale[0], shift[0]);
599

600
      dptr++;
601
      VTKKWRCHelper_GetCellComponentScalarValues(dptr, 1, scale[1], shift[1]);
602

603
      if (components > 2)
604
      {
605
        dptr++;
606 607
        VTKKWRCHelper_GetCellComponentScalarValues(dptr, 2, scale[2], shift[2]);
        if (components > 3)
608
        {
609
          dptr++;
610
          VTKKWRCHelper_GetCellComponentScalarValues(dptr, 3, scale[3], shift[3]);
611
        }
612
      }
613

614 615 616
      dirPtrABCD = gradientDir[spos[2]] + spos[0] * dInc[0] + spos[1] * dInc[1];
      dirPtrEFGH = gradientDir[spos[2] + 1] + spos[0] * dInc[0] + spos[1] * dInc[1];
      VTKKWRCHelper_GetCellComponentDirectionValues(dirPtrABCD, dirPtrEFGH, 0);
617 618 619

      dirPtrABCD++;
      dirPtrEFGH++;
620
      VTKKWRCHelper_GetCellComponentDirectionValues(dirPtrABCD, dirPtrEFGH, 1);
621

622
      if (components > 2)
623
      {
624 625
        dirPtrABCD++;
        dirPtrEFGH++;
626 627
        VTKKWRCHelper_GetCellComponentDirectionValues(dirPtrABCD, dirPtrEFGH, 2);
        if (components > 3)
628
        {
629 630
          dirPtrABCD++;
          dirPtrEFGH++;
631
          VTKKWRCHelper_GetCellComponentDirectionValues(dirPtrABCD, dirPtrEFGH, 3);
632 633
        }
      }
634
    }
635

636
    VTKKWRCHelper_ComputeWeights(pos);
637
    VTKKWRCHelper_InterpolateScalarComponent(val, c, components);
638

639 640
    VTKKWRCHelper_LookupAndCombineIndependentColorsInterpolateShadeUS(colorTable,
      scalarOpacityTable, diffuseShadingTable, specularShadingTable, val, weights, components, tmp);
641

642
    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination(color, tmp, remainingOpacity);
643
  }
644

645
  VTKKWRCHelper_SetPixelColor(imagePtr, color, remainingOpacity);
646 647 648
  VTKKWRCHelper_IncrementAndLoopEnd();
}

649
void vtkFixedPointVolumeRayCastCompositeShadeHelper::GenerateImage(
650
  int threadID, int threadCount, vtkVolume* vol, vtkFixedPointVolumeRayCastMapper* mapper)
651
{
652
  void* data = mapper->GetCurrentScalars()->GetVoidPointer(0);
653
  int scalarType = mapper->GetCurrentScalars()->GetDataType();
654 655

  // Nearest Neighbor interpolate
656
  if (mapper->ShouldUseNearestNeighborInterpolation(vol))
657
  {
658
    // One component data
659
    if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 1)
660
    {
661
      // Scale == 1.0 and shift == 0.0 - simple case (faster)
662
      if (mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0)
663
      {
664
        switch (scalarType)
665
        {
666 667
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleNN(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
668
        }
669
      }
670
      else
671
      {
672
        switch (scalarType)
673
        {
674 675
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageOneNN(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
676 677
        }
      }
678
    }
679
    // More that one independent components
680
    else if (vol->GetProperty()->GetIndependentComponents())
681
    {
682
      switch (scalarType)
683
      {
684 685
        vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageIndependentNN(
          static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
686
      }
687
    }
688 689
    // Dependent (color) components
    else
690
    {
691 692
      // Two components - the first specifies color (through a lookup table)
      // and the second specified opacity (through a lookup table)
693
      if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 2)
694
      {
695
        switch (scalarType)
696
        {
697 698
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentNN(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
699
        }
700
      }
701
      // Four components - they must be unsigned char, the first three directly
702 703
      // specify color and the fourth specifies opacity (through a lookup
      // table)
704
      else
705
      {
706
        if (scalarType == VTK_UNSIGNED_CHAR)
707
        {
708
          vtkFixedPointCompositeShadeHelperGenerateImageFourDependentNN(
709
            static_cast<unsigned char*>(data), threadID, threadCount, mapper, vol);
710
        }
711
        else
712
        {
713 714 715 716
          vtkErrorMacro("Four component dependent data must be unsigned char");
        }
      }
    }
717
  }
718 719
  // Trilinear Interpolation
  else
720
  {
721
    // One component
722
    if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 1)
723
    {
724
      // Scale == 1.0 and shift == 0.0 - simple case (faster)
725
      if (mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0)
726
      {
727
        switch (scalarType)
728
        {
729 730
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
731
        }
732
      }
733 734
      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
      else
735
      {
736
        switch (scalarType)
737
        {
738 739
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageOneTrilin(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
740 741
        }
      }
742
    }
luz.paz's avatar
luz.paz committed
743
    // Independent components (more than one)
744
    else if (vol->GetProperty()->GetIndependentComponents())
745
    {
746
      switch (scalarType)
747
      {
748 749
        vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageIndependentTrilin(
          static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
750
      }
751
    }
752 753
    // Dependent components
    else
754
    {
755 756
      // Two components - the first specifies color (through a lookup table)
      // and the second specified opacity (through a lookup table)
757
      if (mapper->GetCurrentScalars()->GetNumberOfComponents() == 2)
758
      {
759
        switch (scalarType)
760
        {
761 762
          vtkTemplateMacro(vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin(
            static_cast<VTK_TT*>(data), threadID, threadCount, mapper, vol));
763
        }
764
      }
765
      // Four components - they must be unsigned char, the first three directly
766 767
      // specify color and the fourth specifies opacity (through a lookup
      // table)
768
      else
769
      {
770
        if (scalarType == VTK_UNSIGNED_CHAR)