| 151 | //------------------------------------------------------------------------------ |
| 152 | |
| 153 | void vtkUnstructuredGridHomogeneousRayIntegrator::Integrate(vtkDoubleArray* intersectionLengths, |
| 154 | vtkDataArray* nearIntersections, vtkDataArray* vtkNotUsed(farIntersections), float color[4]) |
| 155 | { |
| 156 | vtkIdType numIntersections = intersectionLengths->GetNumberOfTuples(); |
| 157 | |
| 158 | if (this->Property->GetIndependentComponents()) |
| 159 | { |
| 160 | if (this->NumComponents == 1) |
| 161 | { |
| 162 | // Optimize for what I think is one of the most common uses. |
| 163 | for (vtkIdType i = 0; i < numIntersections; i++) |
| 164 | { |
| 165 | int table_index = |
| 166 | (int)(this->TableScale[0] * nearIntersections->GetComponent(i, 0) + this->TableShift[0]); |
| 167 | table_index = std::max(table_index, 0); |
| 168 | table_index = std::min(table_index, this->TransferFunctionTableSize - 1); |
| 169 | float* c = this->ColorTable[0] + 3 * table_index; |
| 170 | float tau = this->AttenuationTable[0][table_index]; |
| 171 | float alpha = 1 - (float)exp(-intersectionLengths->GetComponent(i, 0) * tau); |
| 172 | color[0] += c[0] * alpha * (1 - color[3]); |
| 173 | color[1] += c[1] * alpha * (1 - color[3]); |
| 174 | color[2] += c[2] * alpha * (1 - color[3]); |
| 175 | color[3] += alpha * (1 - color[3]); |
| 176 | } |
| 177 | } |
| 178 | else |
| 179 | { |
| 180 | // Generic case. |
| 181 | for (vtkIdType i = 0; i < numIntersections; i++) |
| 182 | { |
| 183 | float newcolor[4]; |
| 184 | int table_index = |
| 185 | (int)(this->TableScale[0] * nearIntersections->GetComponent(i, 0) + this->TableShift[0]); |
| 186 | table_index = std::max(table_index, 0); |
| 187 | table_index = std::min(table_index, this->TransferFunctionTableSize - 1); |
| 188 | float* c = this->ColorTable[0] + 3 * table_index; |
| 189 | float tau = this->AttenuationTable[0][table_index]; |
| 190 | newcolor[0] = c[0]; |
| 191 | newcolor[1] = c[1]; |
| 192 | newcolor[2] = c[2]; |
| 193 | newcolor[3] = tau; |
| 194 | for (int component = 1; component < this->NumComponents; component++) |
| 195 | { |
| 196 | table_index = |
| 197 | (int)(this->TableScale[component] * nearIntersections->GetComponent(i, component) + |
| 198 | this->TableShift[component]); |
| 199 | table_index = std::max(table_index, 0); |
| 200 | table_index = std::min(table_index, this->TransferFunctionTableSize - 1); |
| 201 | c = this->ColorTable[component] + 3 * table_index; |
| 202 | tau = this->AttenuationTable[component][table_index]; |
| 203 | // Here we handle the mixing of material properties. This never |
| 204 | // seems to be defined very clearly. I handle this by assuming |
| 205 | // that each scalar represents a cloud of particles of a certain |
| 206 | // color and a certain density. We mix the scalars in the same |
| 207 | // way as mixing these particles together. By necessity, the |
| 208 | // density becomes greater. The "opacity" parameter is really |
| 209 | // interpreted as the attenuation coefficient (which is |
| 210 | // proportional to density) and can therefore easily be greater |
nothing calls this directly
no test coverage detected