22#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
24 u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
25 u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
26 u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
27 u[3] = (1.0f / 6.0f) * t * t * t; \
42 if constexpr (std::is_same_v<OutT, float4>) {
57 const float f = 1.0f / 255.0f;
63 return r * (1.0f / 255.0f);
83 return r * (1.0f / 65535.0f);
88 const float f = 1.0f / 65535.0f;
95 read(
const TexT *
data,
const int x,
int y,
const int width,
const int height)
121 return read(
data[
x +
y * width +
z * width * height]);
137 return read(
data[
x +
y * width +
z * width * height]);
155 OutT
read(
const TexT *,
int,
int,
int,
int,
int,
int))
157 OutT r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) *
158 read(
data, ix, iy, iz, width, height, depth);
159 r += (1.0f - tz) * (1.0f - ty) * tx *
read(
data, nix, iy, iz, width, height, depth);
160 r += (1.0f - tz) * ty * (1.0f - tx) *
read(
data, ix, niy, iz, width, height, depth);
161 r += (1.0f - tz) * ty * tx *
read(
data, nix, niy, iz, width, height, depth);
163 r += tz * (1.0f - ty) * (1.0f - tx) *
read(
data, ix, iy, niz, width, height, depth);
164 r += tz * (1.0f - ty) * tx *
read(
data, nix, iy, niz, width, height, depth);
165 r += tz * ty * (1.0f - tx) *
read(
data, ix, niy, niz, width, height, depth);
166 r += tz * ty * tx *
read(
data, nix, niy, niz, width, height, depth);
182 OutT
read(
const TexT *,
int,
int,
int,
int,
int,
int))
184 float u[4],
v[4],
w[4];
189#define DATA(x, y, z) (read(data, xc[x], yc[y], zc[z], width, height, depth))
190#define COL_TERM(col, row) \
191 (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
192 u[3] * DATA(3, col, row)))
193#define ROW_TERM(row) \
194 (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
218 return clamp(
x, 0, width - 1);
223 const int m =
abs(
x + (
x < 0)) % (2 * width);
225 return 2 * width - m - 1;
234 const int width =
info.width;
235 const int height =
info.height;
237 frac(
x * (
float)width, &ix);
238 frac(
y * (
float)height, &iy);
239 switch (
info.extension) {
241 ix = wrap_periodic(ix, width);
242 iy = wrap_periodic(iy, height);
246 if (ix < 0 || ix >= width || iy < 0 || iy >= height) {
251 ix = wrap_clamp(ix, width);
252 iy = wrap_clamp(iy, height);
255 ix = wrap_mirror(ix, width);
256 iy = wrap_mirror(iy, height);
263 const TexT *
data = (
const TexT *)
info.data;
264 return read(
data, ix, iy, width, height);
269 const int width =
info.width;
270 const int height =
info.height;
275 const float tx =
frac(
x * (
float)width - 0.5f, &ix);
276 const float ty =
frac(
y * (
float)height - 0.5f, &iy);
277 const TexT *
data = (
const TexT *)
info.data;
279 switch (
info.extension) {
281 ix = wrap_periodic(ix, width);
282 nix = wrap_periodic(ix + 1, width);
284 iy = wrap_periodic(iy, height);
285 niy = wrap_periodic(iy + 1, height);
289 if (ix < -1 || ix >= width || iy < -1 || iy >= height) {
294 return (1.0f - ty) * (1.0f - tx) * read_clip(
data, ix, iy, width, height) +
295 (1.0f - ty) * tx * read_clip(
data, nix, iy, width, height) +
296 ty * (1.0f - tx) * read_clip(
data, ix, niy, width, height) +
297 ty * tx * read_clip(
data, nix, niy, width, height);
299 nix = wrap_clamp(ix + 1, width);
300 ix = wrap_clamp(ix, width);
301 niy = wrap_clamp(iy + 1, height);
302 iy = wrap_clamp(iy, height);
305 nix = wrap_mirror(ix + 1, width);
306 ix = wrap_mirror(ix, width);
307 niy = wrap_mirror(iy + 1, height);
308 iy = wrap_mirror(iy, height);
315 return (1.0f - ty) * (1.0f - tx) *
read(
data, ix, iy, width, height) +
316 (1.0f - ty) * tx *
read(
data, nix, iy, width, height) +
317 ty * (1.0f - tx) *
read(
data, ix, niy, width, height) +
318 ty * tx *
read(
data, nix, niy, width, height);
323 const int width =
info.width;
324 const int height =
info.height;
328 const float tx =
frac(
x * (
float)width - 0.5f, &ix);
329 const float ty =
frac(
y * (
float)height - 0.5f, &iy);
335 switch (
info.extension) {
337 ix = wrap_periodic(ix, width);
338 pix = wrap_periodic(ix - 1, width);
339 nix = wrap_periodic(ix + 1, width);
340 nnix = wrap_periodic(ix + 2, width);
342 iy = wrap_periodic(iy, height);
343 piy = wrap_periodic(iy - 1, height);
344 niy = wrap_periodic(iy + 1, height);
345 nniy = wrap_periodic(iy + 2, height);
349 if (ix < -2 || ix > width || iy < -2 || iy > height) {
362 pix = wrap_clamp(ix - 1, width);
363 nix = wrap_clamp(ix + 1, width);
364 nnix = wrap_clamp(ix + 2, width);
365 ix = wrap_clamp(ix, width);
367 piy = wrap_clamp(iy - 1, height);
368 niy = wrap_clamp(iy + 1, height);
369 nniy = wrap_clamp(iy + 2, height);
370 iy = wrap_clamp(iy, height);
373 pix = wrap_mirror(ix - 1, width);
374 nix = wrap_mirror(ix + 1, width);
375 nnix = wrap_mirror(ix + 2, width);
376 ix = wrap_mirror(ix, width);
378 piy = wrap_mirror(iy - 1, height);
379 niy = wrap_mirror(iy + 1, height);
380 nniy = wrap_mirror(iy + 2, height);
381 iy = wrap_mirror(iy, height);
388 const TexT *
data = (
const TexT *)
info.data;
389 const int xc[4] = {pix, ix, nix, nnix};
390 const int yc[4] = {piy, iy, niy, nniy};
396#define DATA(x, y) (read_clip(data, xc[x], yc[y], width, height))
399 (u[0] * DATA(0, col) + u[1] * DATA(1, col) + u[2] * DATA(2, col) + u[3] * DATA(3, col)))
412 switch (
info.interpolation) {
414 return interp_closest(
info,
x,
y);
416 return interp_linear(
info,
x,
y);
418 return interp_cubic(
info,
x,
y);
429 const int width =
info.width;
430 const int height =
info.height;
431 const int depth =
info.depth;
434 frac(
x * (
float)width, &ix);
435 frac(
y * (
float)height, &iy);
436 frac(
z * (
float)depth, &iz);
438 switch (
info.extension) {
440 ix = wrap_periodic(ix, width);
441 iy = wrap_periodic(iy, height);
442 iz = wrap_periodic(iz, depth);
446 if (ix < 0 || ix >= width || iy < 0 || iy >= height || iz < 0 || iz >= depth) {
451 ix = wrap_clamp(ix, width);
452 iy = wrap_clamp(iy, height);
453 iz = wrap_clamp(iz, depth);
456 ix = wrap_mirror(ix, width);
457 iy = wrap_mirror(iy, height);
458 iz = wrap_mirror(iz, depth);
465 const TexT *
data = (
const TexT *)
info.data;
466 return read(
data, ix, iy, iz, width, height, depth);
474 const int width =
info.width;
475 const int height =
info.height;
476 const int depth =
info.depth;
481 float tx =
frac(
x * (
float)width - 0.5f, &ix);
482 float ty =
frac(
y * (
float)height - 0.5f, &iy);
483 float tz =
frac(
z * (
float)depth - 0.5f, &iz);
485 switch (
info.extension) {
487 ix = wrap_periodic(ix, width);
488 nix = wrap_periodic(ix + 1, width);
490 iy = wrap_periodic(iy, height);
491 niy = wrap_periodic(iy + 1, height);
493 iz = wrap_periodic(iz, depth);
494 niz = wrap_periodic(iz + 1, depth);
498 if (ix < -1 || ix >= width || iy < -1 || iy >= height || iz < -1 || iz >= depth) {
507 if (ix >= 0 && nix < width && iy >= 0 && niy < height && iz >= 0 && niz < depth) {
513 return trilinear_lookup((
const TexT *)
info.data,
528 nix = wrap_clamp(ix + 1, width);
529 ix = wrap_clamp(ix, width);
531 niy = wrap_clamp(iy + 1, height);
532 iy = wrap_clamp(iy, height);
534 niz = wrap_clamp(iz + 1, depth);
535 iz = wrap_clamp(iz, depth);
538 nix = wrap_mirror(ix + 1, width);
539 ix = wrap_mirror(ix, width);
541 niy = wrap_mirror(iy + 1, height);
542 iy = wrap_mirror(iy, height);
544 niz = wrap_mirror(iz + 1, depth);
545 iz = wrap_mirror(iz, depth);
552 return trilinear_lookup((
const TexT *)
info.data,
576#if defined(__GNUC__) || defined(__clang__)
584 int width =
info.width;
585 int height =
info.height;
586 int depth =
info.depth;
590 const float tx =
frac(
x * (
float)width - 0.5f, &ix);
591 const float ty =
frac(
y * (
float)height - 0.5f, &iy);
592 const float tz =
frac(
z * (
float)depth - 0.5f, &iz);
596 int nnix, nniy, nniz;
598 switch (
info.extension) {
600 ix = wrap_periodic(ix, width);
601 pix = wrap_periodic(ix - 1, width);
602 nix = wrap_periodic(ix + 1, width);
603 nnix = wrap_periodic(ix + 2, width);
605 iy = wrap_periodic(iy, height);
606 niy = wrap_periodic(iy + 1, height);
607 piy = wrap_periodic(iy - 1, height);
608 nniy = wrap_periodic(iy + 2, height);
610 iz = wrap_periodic(iz, depth);
611 piz = wrap_periodic(iz - 1, depth);
612 niz = wrap_periodic(iz + 1, depth);
613 nniz = wrap_periodic(iz + 2, depth);
617 if (ix < -2 || ix > width || iy < -2 || iy > height || iz < -2 || iz > depth) {
634 if (pix >= 0 && nnix < width && piy >= 0 && nniy < height && piz >= 0 && nniz < depth) {
640 const int xc[4] = {pix, ix, nix, nnix};
641 const int yc[4] = {piy, iy, niy, nniy};
642 const int zc[4] = {piz, iz, niz, nniz};
643 return tricubic_lookup(
644 (
const TexT *)
info.data, tx, ty, tz, xc, yc, zc, width, height, depth, read_clip);
647 pix = wrap_clamp(ix - 1, width);
648 nix = wrap_clamp(ix + 1, width);
649 nnix = wrap_clamp(ix + 2, width);
650 ix = wrap_clamp(ix, width);
652 piy = wrap_clamp(iy - 1, height);
653 niy = wrap_clamp(iy + 1, height);
654 nniy = wrap_clamp(iy + 2, height);
655 iy = wrap_clamp(iy, height);
657 piz = wrap_clamp(iz - 1, depth);
658 niz = wrap_clamp(iz + 1, depth);
659 nniz = wrap_clamp(iz + 2, depth);
660 iz = wrap_clamp(iz, depth);
663 pix = wrap_mirror(ix - 1, width);
664 nix = wrap_mirror(ix + 1, width);
665 nnix = wrap_mirror(ix + 2, width);
666 ix = wrap_mirror(ix, width);
668 piy = wrap_mirror(iy - 1, height);
669 niy = wrap_mirror(iy + 1, height);
670 nniy = wrap_mirror(iy + 2, height);
671 iy = wrap_mirror(iy, height);
673 piz = wrap_mirror(iz - 1, depth);
674 niz = wrap_mirror(iz + 1, depth);
675 nniz = wrap_mirror(iz + 2, depth);
676 iz = wrap_mirror(iz, depth);
682 const int xc[4] = {pix, ix, nix, nnix};
683 const int yc[4] = {piy, iy, niy, nniy};
684 const int zc[4] = {piz, iz, niz, nniz};
685 const TexT *
data = (
const TexT *)
info.data;
686 return tricubic_lookup(
data, tx, ty, tz, xc, yc, zc, width, height, depth,
read);
694 return interp_3d_closest(
info,
x,
y,
z);
696 return interp_3d_linear(
info,
x,
y,
z);
698 return interp_3d_cubic(
info,
x,
y,
z);
704template<
typename TexT,
typename OutT>
struct NanoVDBInterpolator {
716 template<
typename Acc>
718 interp_3d_closest(
const Acc &acc,
const float x,
float y,
const float z)
721 return read(acc.getValue(coord));
724 template<
typename Acc>
726 interp_3d_linear(
const Acc &acc,
const float x,
float y,
const float z)
729 const float tx =
frac(
x - 0.5f, &ix);
730 const float ty =
frac(
y - 0.5f, &iy);
731 const float tz =
frac(
z - 0.5f, &iz);
751 template<
typename Acc>
752# if defined(__GNUC__) || defined(__clang__)
758 interp_3d_cubic(
const Acc &acc,
const float x,
float y,
const float z)
763 int nnix, nniy, nniz;
766 const float tx =
frac(
x - 0.5f, &ix);
767 const float ty =
frac(
y - 0.5f, &iy);
768 const float tz =
frac(
z - 0.5f, &iz);
780 const int xc[4] = {pix, ix, nix, nnix};
781 const int yc[4] = {piy, iy, niy, nniy};
782 const int zc[4] = {piz, iz, niz, nniz};
783 float u[4],
v[4],
w[4];
788# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
789# define COL_TERM(col, row) \
790 (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
791 u[3] * DATA(3, col, row)))
792# define ROW_TERM(row) \
793 (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
817 return interp_3d_closest(acc,
x,
y,
z);
821 return interp_3d_linear(acc,
x,
y,
z);
825 return interp_3d_cubic(acc,
x,
y,
z);
832#undef SET_CUBIC_SPLINE_WEIGHTS
842 switch (
info.data_type) {
885 if (
info.use_transform_3d) {
888 switch (
info.data_type) {
915 const float f = NanoVDBInterpolator<float, float>::interp_3d(
info,
P.x,
P.y,
P.z,
interp);
919 return NanoVDBInterpolator<packed_float3, float4>::interp_3d(
info,
P.x,
P.y,
P.z,
interp);
921 const float f = NanoVDBInterpolator<nanovdb::FpN, float>::interp_3d(
926 const float f = NanoVDBInterpolator<nanovdb::Fp16, float>::interp_3d(
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
#define SET_CUBIC_SPLINE_WEIGHTS(u, t)
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(const float x, ccl_private int *ix)
ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, const int id, float3 P, InterpolationType interp)
ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, const int id, const float x, float y)
#define kernel_assert(cond)
#define kernel_data_fetch(name, index)
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define ccl_always_inline
#define assert(assertion)
constexpr T clamp(T, U, U) RET
ccl_device_inline float4 half4_to_float4_image(const half4 h)
ccl_device_inline float half_to_float_image(half h)
ccl_device_inline int float_to_int(const float f)
ccl_device_inline float interp(const float a, const float b, const float t)
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
static ccl_always_inline OutT interp(const TextureInfo &info, const float x, float y)
static ccl_never_inline OutT interp_3d_cubic(const TextureInfo &info, const float x, float y, const float z)
static ccl_always_inline float read(const uint16_t r)
static ccl_always_inline int wrap_mirror(const int x, const int width)
static ccl_always_inline OutT tricubic_lookup(const TexT *data, const float tx, const float ty, const float tz, const int xc[4], const int yc[4], const int zc[4], const int width, const int height, const int depth, OutT read(const TexT *, int, int, int, int, int, int))
static ccl_always_inline OutT read(const TexT *data, const int x, int y, const int width, const int height)
static ccl_always_inline OutT read_clip(const TexT *data, const int x, int y, const int z, int width, const int height, const int depth)
static ccl_always_inline OutT interp_3d(const TextureInfo &info, const float x, float y, const float z, InterpolationType interp)
static ccl_always_inline float4 read(const uchar4 r)
static ccl_always_inline OutT interp_3d_linear(const TextureInfo &info, const float x, const float y, const float z)
static ccl_always_inline OutT trilinear_lookup(const TexT *data, const float tx, const float ty, const float tz, const int ix, const int iy, const int iz, const int nix, const int niy, const int niz, const int width, const int height, const int depth, OutT read(const TexT *, int, int, int, int, int, int))
static ccl_always_inline OutT zero()
static ccl_always_inline float read(const uchar r)
static ccl_always_inline OutT interp_linear(const TextureInfo &info, const float x, float y)
static ccl_always_inline OutT interp_cubic(const TextureInfo &info, const float x, float y)
static ccl_always_inline OutT interp_closest(const TextureInfo &info, const float x, float y)
static ccl_always_inline int wrap_periodic(int x, const int width)
static ccl_always_inline OutT interp_3d_closest(const TextureInfo &info, const float x, const float y, const float z)
static ccl_always_inline float4 read(const float4 r)
static ccl_always_inline float4 read(ushort4 r)
static ccl_always_inline OutT read_clip(const TexT *data, const int x, int y, const int width, const int height)
static ccl_always_inline float4 read(half4 r)
static ccl_always_inline int wrap_clamp(const int x, const int width)
static ccl_always_inline float read(const float r)
static ccl_always_inline float read(half r)
static ccl_always_inline OutT read(const TexT *data, const int x, int y, const int z, int width, const int height, const int depth)
@ IMAGE_DATA_TYPE_NANOVDB_FP16
@ IMAGE_DATA_TYPE_USHORT4
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
@ IMAGE_DATA_TYPE_NANOVDB_FPN