|
1 | 1 | #include "neural_sampler.h"
|
2 | 2 |
|
| 3 | +namespace vidi { |
| 4 | +enum VoxelType { |
| 5 | + VOXEL_UINT8 = vnr::VALUE_TYPE_UINT8, |
| 6 | + VOXEL_INT8 = vnr::VALUE_TYPE_INT8, |
| 7 | + VOXEL_UINT16 = vnr::VALUE_TYPE_UINT16, |
| 8 | + VOXEL_INT16 = vnr::VALUE_TYPE_INT16, |
| 9 | + VOXEL_UINT32 = vnr::VALUE_TYPE_UINT32, |
| 10 | + VOXEL_INT32 = vnr::VALUE_TYPE_INT32, |
| 11 | + VOXEL_FLOAT = vnr::VALUE_TYPE_FLOAT, |
| 12 | + VOXEL_DOUBLE = vnr::VALUE_TYPE_DOUBLE, |
| 13 | +}; |
| 14 | +} // namespace vidi |
| 15 | +#define VIDI_VOLUME_EXTERNAL_TYPE_ENUM |
| 16 | +#include <vidi_parallel_algorithm.h> |
| 17 | +#include <vidi_volume_reader.h> |
| 18 | + |
3 | 19 |
|
4 | 20 | #ifdef ENABLE_OUT_OF_CORE
|
5 | 21 |
|
@@ -149,6 +165,132 @@ isclose(float a, float b, float rel_tol = 10*float_epsilon, float abs_tol = 0.0)
|
149 | 165 | //
|
150 | 166 | // ------------------------------------------------------------------
|
151 | 167 |
|
| 168 | +namespace { |
| 169 | + |
| 170 | +// template<class T> |
| 171 | +// constexpr const T& clamp(const T& v, const T& lo, const T& hi) |
| 172 | +// { |
| 173 | +// return (v < lo) ? lo : (hi < v) ? hi : v; |
| 174 | +// } |
| 175 | + |
| 176 | +template<typename IType> |
| 177 | +std::shared_ptr<char[]> |
| 178 | +convert_volume(std::shared_ptr<char[]> idata, size_t size, float vmin, float vmax) |
| 179 | +{ |
| 180 | + std::shared_ptr<char[]> odata; |
| 181 | + odata.reset(new char[size * sizeof(float)]); |
| 182 | + |
| 183 | + tbb::parallel_for(size_t(0), size, [&](size_t idx) { |
| 184 | + auto* i = (IType*)&idata[idx * sizeof(IType)]; |
| 185 | + auto* o = (float*)&odata[idx * sizeof(float)]; |
| 186 | +#ifdef TEST_SIREN |
| 187 | + *o = clamp((static_cast<float>(*i) - (float)vmin) / ((float)vmax - (float)vmin), 0.f, 1.f) * 2.f - 1.f; |
| 188 | +#else |
| 189 | + *o = clamp((static_cast<float>(*i) - (float)vmin) / ((float)vmax - (float)vmin), 0.f, 1.f); |
| 190 | +#endif |
| 191 | + }); |
| 192 | + |
| 193 | + return odata; |
| 194 | +} |
| 195 | + |
| 196 | +template<> |
| 197 | +std::shared_ptr<char[]> |
| 198 | +convert_volume<float>(std::shared_ptr<char[]> idata, size_t size, float vmin, float vmax) |
| 199 | +{ |
| 200 | + tbb::parallel_for(size_t(0), size, [&](size_t idx) { |
| 201 | + auto* i = (float*)&idata[idx * sizeof(float)]; |
| 202 | +#ifdef TEST_SIREN |
| 203 | + *i = clamp((static_cast<float>(*i) - (float)vmin) / ((float)vmax - (float)vmin), 0.f, 1.f) * 2.f - 1.f; |
| 204 | +#else |
| 205 | + *i = clamp((static_cast<float>(*i) - (float)vmin) / ((float)vmax - (float)vmin), 0.f, 1.f); |
| 206 | +#endif |
| 207 | + }); |
| 208 | + |
| 209 | + return idata; |
| 210 | +} |
| 211 | + |
| 212 | +template<typename T> |
| 213 | +static range1f |
| 214 | +compute_scalar_fminmax(const void* _array, size_t count) |
| 215 | +{ |
| 216 | + using vidi::parallel::compute_scalar_minmax; |
| 217 | + auto r = compute_scalar_minmax<T>(_array, count, 0); |
| 218 | + return range1f((float)r.first, (float)r.second); |
| 219 | +} |
| 220 | + |
| 221 | +} // namespace |
| 222 | + |
| 223 | +void |
| 224 | +StaticSampler::load(const MultiVolume::File& desc, |
| 225 | + vec3i dims, dtype type, range1f minmax, |
| 226 | + std::shared_ptr<char[]>& buffer, |
| 227 | + range1f& value_range_unnormalized, |
| 228 | + range1f& value_range_normalized) |
| 229 | +{ |
| 230 | + const auto& offset = desc.offset; |
| 231 | + const auto& filename = desc.filename; |
| 232 | + const auto& is_big_endian = desc.bigendian; |
| 233 | + |
| 234 | + /* load data from file */ |
| 235 | + { |
| 236 | + vidi::StructuredRegularVolumeDesc desc; |
| 237 | + desc.dims.x = dims.x; |
| 238 | + desc.dims.y = dims.y; |
| 239 | + desc.dims.z = dims.z; |
| 240 | + desc.type = (vidi::VoxelType)type; |
| 241 | + desc.offset = offset; |
| 242 | + desc.is_big_endian = is_big_endian; |
| 243 | + buffer = vidi::read_volume_structured_regular(filename, desc); |
| 244 | + } |
| 245 | + |
| 246 | + /* copy data to GPU */ |
| 247 | + const size_t count = (size_t)dims.x * dims.y * dims.z; |
| 248 | + |
| 249 | + /* convert volume into floats */ |
| 250 | + range1f range; |
| 251 | + { |
| 252 | + if (minmax.is_empty()) { |
| 253 | + switch (type) { |
| 254 | + case VALUE_TYPE_UINT8: range = compute_scalar_fminmax<uint8_t>(buffer.get(), count); break; |
| 255 | + case VALUE_TYPE_INT8: range = compute_scalar_fminmax<int8_t>(buffer.get(), count); break; |
| 256 | + case VALUE_TYPE_UINT16: range = compute_scalar_fminmax<uint16_t>(buffer.get(), count); break; |
| 257 | + case VALUE_TYPE_INT16: range = compute_scalar_fminmax<int16_t>(buffer.get(), count); break; |
| 258 | + case VALUE_TYPE_UINT32: range = compute_scalar_fminmax<uint32_t>(buffer.get(), count); break; |
| 259 | + case VALUE_TYPE_INT32: range = compute_scalar_fminmax<int32_t>(buffer.get(), count); break; |
| 260 | + case VALUE_TYPE_FLOAT: range = compute_scalar_fminmax<float>(buffer.get(), count); break; |
| 261 | + case VALUE_TYPE_DOUBLE: range = compute_scalar_fminmax<double>(buffer.get(), count); break; |
| 262 | + default: throw std::runtime_error("unknown data type"); |
| 263 | + } |
| 264 | + } |
| 265 | + else { |
| 266 | + range = minmax; |
| 267 | + } |
| 268 | + |
| 269 | + switch (type) { |
| 270 | + case VALUE_TYPE_UINT8: buffer = convert_volume<uint8_t> (buffer, count, range.lower, range.upper); break; |
| 271 | + case VALUE_TYPE_INT8: buffer = convert_volume<int8_t> (buffer, count, range.lower, range.upper); break; |
| 272 | + case VALUE_TYPE_UINT16: buffer = convert_volume<uint16_t>(buffer, count, range.lower, range.upper); break; |
| 273 | + case VALUE_TYPE_INT16: buffer = convert_volume<int16_t> (buffer, count, range.lower, range.upper); break; |
| 274 | + case VALUE_TYPE_UINT32: buffer = convert_volume<uint32_t>(buffer, count, range.lower, range.upper); break; |
| 275 | + case VALUE_TYPE_INT32: buffer = convert_volume<int32_t> (buffer, count, range.lower, range.upper); break; |
| 276 | + case VALUE_TYPE_FLOAT: buffer = convert_volume<float> (buffer, count, range.lower, range.upper); break; |
| 277 | + case VALUE_TYPE_DOUBLE: buffer = convert_volume<double> (buffer, count, range.lower, range.upper); break; |
| 278 | + default: throw std::runtime_error("unknown data type"); |
| 279 | + } |
| 280 | + } |
| 281 | + value_range_unnormalized = range; |
| 282 | + value_range_normalized.lower = 0.f; |
| 283 | + value_range_normalized.upper = 1.f; |
| 284 | + // std::tie(value_range_normalized.lower, value_range_normalized.upper) = vidi::parallel::compute_scalar_minmax<float>(buffer.get(), count, 0); |
| 285 | + |
| 286 | + log() << "[vnr] unnormalized range " << value_range_unnormalized.lower << " " << value_range_unnormalized.upper << std::endl; |
| 287 | + log() << "[vnr] normalized range " << value_range_normalized.lower << " " << value_range_normalized.upper << std::endl; |
| 288 | +} |
| 289 | + |
| 290 | +// ------------------------------------------------------------------ |
| 291 | +// |
| 292 | +// ------------------------------------------------------------------ |
| 293 | + |
152 | 294 | template<typename F>
|
153 | 295 | static float
|
154 | 296 | nearest_vkl(const vec3f& p_cell_centered, const vec3i& m_dims, const F& accessor)
|
|
0 commit comments