1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "LinearTransferFunction.h"
#ifndef OSPRAY_TARGET_SYCL
#include "volume/transferFunction/LinearTransferFunction_ispc.h"
#else
namespace ispc {
void *LinearTransferFunction_get_addr();
void *LinearTransferFunction_getMaxOpacity_addr();
} // namespace ispc
#endif
namespace ospray {
LinearTransferFunction::LinearTransferFunction(api::ISPCDevice &device)
: AddStructShared(device.getDRTDevice(), device)
{
getSh()->super.valueRange = range1f(0.0f, 1.0f);
}
void LinearTransferFunction::commit()
{
TransferFunction::commit();
colorValues = getParamDataT<vec3f>("color", true);
opacityValues = getParamDataT<float>("opacity", true);
getSh()->color = *ispc(colorValues);
getSh()->opacity = *ispc(opacityValues);
precomputeMaxOpacityRanges();
}
std::string LinearTransferFunction::toString() const
{
return "ospray::LinearTransferFunction";
}
std::vector<range1i> LinearTransferFunction::getPositiveOpacityIndexRanges()
const
{
std::vector<range1i> intervals;
range1i interval;
bool rangeActive = false;
const DataT<float> &opacities = *opacityValues;
for (int i = 0; i < int(opacities.size()); i++) {
if (opacities[i] > 0.f && !rangeActive) {
rangeActive = true;
interval.lower = i;
} else if (opacities[i] <= 0.f && rangeActive) {
rangeActive = false;
interval.upper = i;
intervals.push_back(interval);
}
}
// special case for final value
if (opacities[opacities.size() - 1] > 0.f) {
if (rangeActive) {
rangeActive = false;
interval.upper = opacities.size();
intervals.push_back(interval);
} else {
throw std::runtime_error("getPositiveOpacityIndexRanges() error");
}
}
return intervals;
}
std::vector<range1f> LinearTransferFunction::getPositiveOpacityValueRanges()
const
{
std::vector<range1f> valueRanges;
// determine index ranges for positive opacities
std::vector<range1i> indexRanges = getPositiveOpacityIndexRanges();
const DataT<float> &opacities = *opacityValues;
// convert index ranges to value ranges
// note that a positive opacity value has a span of +/-1 due to the linear
// interpolation, and returned index ranges are [min, max) intervals
for (int i = 0; i < int(indexRanges.size()); i++) {
int minValueIndex = indexRanges[i].lower - 1;
int maxValueIndex = indexRanges[i].upper;
range1f range(neg_inf, inf);
if (minValueIndex >= 0) {
range.lower = valueRange.lower
+ minValueIndex * valueRange.size() / (opacities.size() - 1.f);
}
if (maxValueIndex < int(opacities.size())) {
range.upper = valueRange.lower
+ maxValueIndex * valueRange.size() / (opacities.size() - 1.f);
}
valueRanges.push_back(range);
}
return valueRanges;
}
void LinearTransferFunction::precomputeMaxOpacityRanges()
{
const DataT<float> &opacities = *opacityValues;
const int maxOpacityDim = opacities.size() - 1;
const int maxPrecomputedDim = PRECOMPUTED_OPACITY_SUBRANGE_COUNT - 1;
// compute the diagonal
for (int i = 0; i < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; i++) {
// figure out the range of array indices we are going to compare; this is a
// conservative range of feasible indices that may be used to lookup
// opacities for any data value within the value range corresponding to [i,
// i].
const int checkRangeLow =
floor(maxOpacityDim * (float)i / maxPrecomputedDim);
const int checkRangeHigh =
ceil(maxOpacityDim * (float)i / maxPrecomputedDim);
float maxOpacity = opacities[checkRangeLow];
for (int opacityIDX = checkRangeLow; opacityIDX <= checkRangeHigh;
opacityIDX++)
maxOpacity = std::max(maxOpacity, opacities[opacityIDX]);
getSh()->maxOpacityInRange[i][i] = maxOpacity;
}
// fill out each column from the diagonal up
for (int i = 0; i < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; i++) {
for (int j = i + 1; j < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; j++) {
// figure out the range of array indices we are going to compare; this is
// a conservative range of feasible indices that may be used to lookup
// opacities for any data value within the value range corresponding to
// [i, j].
const int checkRangeLow =
floor(maxOpacityDim * (float)i / maxPrecomputedDim);
const int checkRangeHigh =
ceil(maxOpacityDim * (float)j / maxPrecomputedDim);
float maxOpacity = getSh()->maxOpacityInRange[i][i];
for (int opacityIDX = checkRangeLow; opacityIDX <= checkRangeHigh;
opacityIDX++)
maxOpacity = std::max(maxOpacity, opacities[opacityIDX]);
getSh()->maxOpacityInRange[i][j] = maxOpacity;
}
}
}
} // namespace ospray
|