OpenVDB  9.0.1
CSampleFromVoxels.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 //
5 // Simple C-wrapper for voxel interpolation functions
6 //
7 
8 #ifndef __CSAMPLEFROMVOXELS__
9 #define __CSAMPLEFROMVOXELS__
10 
11 #include "../CNanoVDB.h"
12 
13 #ifdef __OPENCL_VERSION__
14 #else
15 #include <math.h>
16 #endif
17 
18 void
20 {
21 #ifdef __OPENCL_VERSION__
22  coord->mVec[0] = floor(xyz->mVec[0]+0.5);
23  coord->mVec[1] = floor(xyz->mVec[1]+0.5);
24  coord->mVec[2] = floor(xyz->mVec[2]+0.5);
25 #else
26  coord->mVec[0] = floorf(xyz->mVec[0]+0.5);
27  coord->mVec[1] = floorf(xyz->mVec[1]+0.5);
28  coord->mVec[2] = floorf(xyz->mVec[2]+0.5);
29 #endif
30 }
31 
32 void
34 {
35 #ifdef __OPENCL_VERSION__
36  float i0, i1, i2;
37  fraction->mVec[0] = fract(xyz->mVec[0], &i0);
38  coord->mVec[0] = i0;
39  fraction->mVec[1] = fract(xyz->mVec[1], &i1);
40  coord->mVec[1] = i1;
41  fraction->mVec[2] = fract(xyz->mVec[2], &i2);
42  coord->mVec[2] = i2;
43 #else
44  float i0, i1, i2;
45  i0 = floorf(xyz->mVec[0]);
46  fraction->mVec[0] = xyz->mVec[0] - i0;
47  coord->mVec[0] = i0;
48  i1 = floorf(xyz->mVec[1]);
49  fraction->mVec[1] = xyz->mVec[1] - i1;
50  coord->mVec[1] = i1;
51  i2 = floorf(xyz->mVec[2]);
52  fraction->mVec[2] = xyz->mVec[2] - i2;
53  coord->mVec[2] = i2;
54 #endif
55 }
56 
57 #define CREATE_STENCIL(VALUETYPE, SUFFIX) \
58 typedef struct \
59 { \
60  VALUETYPE mStencil[2][2][2]; \
61  cnanovdb_coord mCoord; \
62 } cnanovdb_stencil1##SUFFIX; \
63  \
64 void \
65 cnanovdb_stencil1##SUFFIX##_clear(cnanovdb_stencil1##SUFFIX *RESTRICT stencil) \
66 { \
67  /* Invalid coords. */ \
68  stencil->mCoord.mVec[0] = 0x80000000; \
69  stencil->mCoord.mVec[1] = 0x80000000; \
70  stencil->mCoord.mVec[2] = 0x80000000; \
71 } \
72  \
73 void \
74 cnanovdb_stencil1##SUFFIX##_fill(cnanovdb_stencil1##SUFFIX *RESTRICT stencil, cnanovdb_readaccessor *RESTRICT acc, cnanovdb_coord *RESTRICT coord) \
75 { \
76  stencil->mStencil[0][0][0] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
77  coord->mVec[2] += 1; \
78  stencil->mStencil[0][0][1] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
79  coord->mVec[1] += 1; \
80  stencil->mStencil[0][1][1] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
81  coord->mVec[2] -= 1; \
82  stencil->mStencil[0][1][0] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
83  \
84  coord->mVec[0] += 1; \
85  stencil->mStencil[1][1][0] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
86  coord->mVec[2] += 1; \
87  stencil->mStencil[1][1][1] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
88  coord->mVec[1] -= 1; \
89  stencil->mStencil[1][0][1] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
90  coord->mVec[2] -= 1; \
91  stencil->mStencil[1][0][0] = cnanovdb_readaccessor_getValue##SUFFIX(acc, coord); \
92  coord->mVec[0] -= 1; \
93  \
94  stencil->mCoord.mVec[0] = coord->mVec[0]; \
95  stencil->mCoord.mVec[1] = coord->mVec[1]; \
96  stencil->mCoord.mVec[2] = coord->mVec[2]; \
97 } \
98  \
99 void \
100 cnanovdb_stencil1##SUFFIX##_update(cnanovdb_stencil1##SUFFIX *RESTRICT stencil, cnanovdb_readaccessor *RESTRICT acc, cnanovdb_coord *RESTRICT coord) \
101 { \
102  uint32_t change = (coord->mVec[0] ^ stencil->mCoord.mVec[0]) | \
103  (coord->mVec[1] ^ stencil->mCoord.mVec[1]) | \
104  (coord->mVec[2] ^ stencil->mCoord.mVec[2]); \
105  if (!change) \
106  return; \
107  \
108  cnanovdb_stencil1##SUFFIX##_fill(stencil, acc, coord); \
109 } \
110 /**/
111 CREATE_STENCIL(float, F)
113 
114 
115 #define CREATE_LERPSIMPLE(VALUETYPE, SUFFIX) \
116 VALUETYPE \
117 cnanovdb_lerp##SUFFIX(VALUETYPE a, VALUETYPE b, float w) \
118 { \
119  return a + w * (b - a); \
120 } \
121 /**/
122 
125 
126 cnanovdb_Vec3F
127 cnanovdb_lerpF3(cnanovdb_Vec3F a, cnanovdb_Vec3F b, float w)
128 {
129  a.mVec[0] = cnanovdb_lerpF(a.mVec[0], b.mVec[0], w);
130  a.mVec[1] = cnanovdb_lerpF(a.mVec[1], b.mVec[1], w);
131  a.mVec[2] = cnanovdb_lerpF(a.mVec[2], b.mVec[2], w);
132  return a;
133 }
134 
135 #define CREATE_SAMPLE(VALUETYPE, SUFFIX) \
136 VALUETYPE \
137 cnanovdb_sample##SUFFIX##_nearest(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz) \
138 { \
139  cnanovdb_coord coord; \
140  cnanovdb_coord_round(&coord, xyz); \
141  return cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
142 } \
143  \
144 VALUETYPE \
145 cnanovdb_sample##SUFFIX##_trilinear(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz) \
146 { \
147  cnanovdb_coord coord; \
148  cnanovdb_Vec3F fraction; \
149  cnanovdb_coord_fract(&coord, &fraction, xyz); \
150  \
151  VALUETYPE vx, vx1, vy, vy1, vz, vz1; \
152  \
153  vz = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
154  coord.mVec[2] += 1; \
155  vz1 = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
156  vy = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
157  \
158  coord.mVec[1] += 1; \
159  \
160  vz1 = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
161  coord.mVec[2] -= 1; \
162  vz = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
163  vy1 = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
164  \
165  vx = cnanovdb_lerp##SUFFIX(vy, vy1, fraction.mVec[1]); \
166  \
167  coord.mVec[0] += 1; \
168  \
169  vz = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
170  coord.mVec[2] += 1; \
171  vz1 = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
172  vy1 = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
173  \
174  coord.mVec[1] -= 1; \
175  \
176  vz1 = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
177  coord.mVec[2] -= 1; \
178  vz = cnanovdb_readaccessor_getValue##SUFFIX(acc, &coord); \
179  vy = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
180  \
181  vx1 = cnanovdb_lerp##SUFFIX(vy, vy1, fraction.mVec[1]); \
182  \
183  return cnanovdb_lerp##SUFFIX(vx, vx1, fraction.mVec[0]); \
184 } \
185  \
186 VALUETYPE \
187 cnanovdb_sample##SUFFIX##_trilinear_stencil(cnanovdb_stencil1##SUFFIX *RESTRICT stencil, cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz) \
188 { \
189  cnanovdb_coord coord; \
190  cnanovdb_Vec3F fraction; \
191  cnanovdb_coord_fract(&coord, &fraction, xyz); \
192  \
193  cnanovdb_stencil1##SUFFIX##_update(stencil, acc, &coord); \
194  \
195  VALUETYPE vx, vx1, vy, vy1, vz, vz1; \
196  \
197  vz = stencil->mStencil[0][0][0]; \
198  vz1 = stencil->mStencil[0][0][1]; \
199  vy = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
200  \
201  vz = stencil->mStencil[0][1][0]; \
202  vz1 = stencil->mStencil[0][1][1]; \
203  vy1 = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
204  \
205  vx = cnanovdb_lerp##SUFFIX(vy, vy1, fraction.mVec[1]); \
206  \
207  vz = stencil->mStencil[1][1][0]; \
208  vz1 = stencil->mStencil[1][1][1]; \
209  vy1 = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
210  \
211  vz = stencil->mStencil[1][0][0]; \
212  vz1 = stencil->mStencil[1][0][1]; \
213  vy = cnanovdb_lerp##SUFFIX(vz, vz1, fraction.mVec[2]); \
214  \
215  vx1 = cnanovdb_lerp##SUFFIX(vy, vy1, fraction.mVec[1]); \
216  \
217  return cnanovdb_lerp##SUFFIX(vx, vx1, fraction.mVec[0]); \
218 } \
219 /**/
220 CREATE_SAMPLE(float, F)
221 CREATE_SAMPLE(cnanovdb_Vec3F, F3)
222 
223 void
224 cnanovdb_sampleF_gradient(cnanovdb_Vec3F *RESTRICT ret, cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz)
225 {
226  cnanovdb_Vec3F qxyz;
227  qxyz.mVec[0] = xyz->mVec[0];
228  qxyz.mVec[1] = xyz->mVec[1];
229  qxyz.mVec[2] = xyz->mVec[2];
230  for (int i = 0; i < 3; i++)
231  {
232  float sp, sm;
233 
234  qxyz.mVec[i] -= 0.5;
235  sm = cnanovdb_sampleF_trilinear(acc, &qxyz);
236  qxyz.mVec[i] += 1.0;
237  sp = cnanovdb_sampleF_trilinear(acc, &qxyz);
238  qxyz.mVec[i] -= 0.5;
239  ret->mVec[i] = sp - sm;
240  }
241 }
242 
243 void
244 cnanovdb_sampleF_gradient0(cnanovdb_Vec3F *RESTRICT ret, cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz)
245 {
246  cnanovdb_coord coord;
247  cnanovdb_Vec3F fraction;
248  cnanovdb_coord_fract(&coord, &fraction, xyz);
249 
250  float stencil[2][2][2];
251 
252  stencil[0][0][0] = cnanovdb_readaccessor_getValueF(acc, &coord);
253  coord.mVec[2] += 1;
254  stencil[0][0][1] = cnanovdb_readaccessor_getValueF(acc, &coord);
255  coord.mVec[1] += 1;
256  stencil[0][1][1] = cnanovdb_readaccessor_getValueF(acc, &coord);
257  coord.mVec[2] -= 1;
258  stencil[0][1][0] = cnanovdb_readaccessor_getValueF(acc, &coord);
259 
260  coord.mVec[0] += 1;
261  stencil[1][1][0] = cnanovdb_readaccessor_getValueF(acc, &coord);
262  coord.mVec[2] += 1;
263  stencil[1][1][1] = cnanovdb_readaccessor_getValueF(acc, &coord);
264  coord.mVec[1] -= 1;
265  stencil[1][0][1] = cnanovdb_readaccessor_getValueF(acc, &coord);
266  coord.mVec[2] -= 1;
267  stencil[1][0][0] = cnanovdb_readaccessor_getValueF(acc, &coord);
268 
269  float D[4];
270 
271  D[0] = stencil[0][0][1] - stencil[0][0][0];
272  D[1] = stencil[0][1][1] - stencil[0][1][0];
273  D[2] = stencil[1][0][1] - stencil[1][0][0];
274  D[3] = stencil[1][1][1] - stencil[1][1][0];
275 
276  ret->mVec[2] = cnanovdb_lerpF(
277  cnanovdb_lerpF(D[0], D[1], fraction.mVec[1]),
278  cnanovdb_lerpF(D[2], D[3], fraction.mVec[1]),
279  fraction.mVec[0] );
280 
281  float w = fraction.mVec[2];
282  D[0] = stencil[0][0][0] + D[0] * w;
283  D[1] = stencil[0][1][0] + D[1] * w;
284  D[2] = stencil[1][0][0] + D[2] * w;
285  D[3] = stencil[1][1][0] + D[3] * w;
286 
287  ret->mVec[0] = cnanovdb_lerpF(D[2], D[3], fraction.mVec[1])
288  - cnanovdb_lerpF(D[0], D[1], fraction.mVec[1]);
289 
290  ret->mVec[1] = cnanovdb_lerpF(D[1] - D[0], D[3] - D[2], fraction.mVec[0]);
291 }
292 
293 void
295 {
296  cnanovdb_coord coord;
297  cnanovdb_Vec3F fraction;
298  cnanovdb_coord_fract(&coord, &fraction, xyz);
299 
300  cnanovdb_stencil1F_update(stencil, acc, &coord);
301 
302  float D[4];
303 
304  D[0] = stencil->mStencil[0][0][1] - stencil->mStencil[0][0][0];
305  D[1] = stencil->mStencil[0][1][1] - stencil->mStencil[0][1][0];
306  D[2] = stencil->mStencil[1][0][1] - stencil->mStencil[1][0][0];
307  D[3] = stencil->mStencil[1][1][1] - stencil->mStencil[1][1][0];
308 
309  ret->mVec[2] = cnanovdb_lerpF(
310  cnanovdb_lerpF(D[0], D[1], fraction.mVec[1]),
311  cnanovdb_lerpF(D[2], D[3], fraction.mVec[1]),
312  fraction.mVec[0] );
313 
314  float w = fraction.mVec[2];
315  D[0] = stencil->mStencil[0][0][0] + D[0] * w;
316  D[1] = stencil->mStencil[0][1][0] + D[1] * w;
317  D[2] = stencil->mStencil[1][0][0] + D[2] * w;
318  D[3] = stencil->mStencil[1][1][0] + D[3] * w;
319 
320  ret->mVec[0] = cnanovdb_lerpF(D[2], D[3], fraction.mVec[1])
321  - cnanovdb_lerpF(D[0], D[1], fraction.mVec[1]);
322 
323  ret->mVec[1] = cnanovdb_lerpF(D[1] - D[0], D[3] - D[2], fraction.mVec[0]);
324 }
325 
326 
327 #endif
void cnanovdb_sampleF_gradient0_stencil(cnanovdb_Vec3F *__restrict ret, cnanovdb_stencil1F *__restrict stencil, cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:294
float cnanovdb_sampleF_trilinear(cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:220
#define CREATE_SAMPLE(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:135
void cnanovdb_coord_fract(cnanovdb_coord *__restrict coord, cnanovdb_Vec3F *__restrict fraction, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:33
Definition: CNanoVDB.h:95
void cnanovdb_sampleF_gradient(cnanovdb_Vec3F *__restrict ret, cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:224
float mVec[3]
Definition: CNanoVDB.h:92
float cnanovdb_readaccessor_getValueF(cnanovdb_readaccessor *__restrict acc, const cnanovdb_coord *__restrict ijk)
Definition: CNanoVDB.h:682
#define RESTRICT
Definition: CNanoVDB.h:33
#define CREATE_LERPSIMPLE(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:115
Definition: CNanoVDB.h:285
cnanovdb_Vec3F cnanovdb_lerpF3(cnanovdb_Vec3F a, cnanovdb_Vec3F b, float w)
Definition: CSampleFromVoxels.h:127
void cnanovdb_sampleF_gradient0(cnanovdb_Vec3F *__restrict ret, cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:244
void cnanovdb_stencil1F_update(cnanovdb_stencil1F *__restrict stencil, cnanovdb_readaccessor *__restrict acc, cnanovdb_coord *__restrict coord)
Definition: CSampleFromVoxels.h:111
float cnanovdb_lerpF(float a, float b, float w)
Definition: CSampleFromVoxels.h:123
Definition: CNanoVDB.h:90
int32_t mVec[3]
Definition: CNanoVDB.h:97
Definition: CSampleFromVoxels.h:111
void cnanovdb_coord_round(cnanovdb_coord *__restrict coord, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:19
#define CREATE_STENCIL(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:57