OpenVDB: nanovdb/util/CSampleFromVoxels.h Source File

OpenVDB 9.0.0

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
18void
19cnanovdb_coord_round(cnanovdb_coord *RESTRICT coord, const cnanovdb_Vec3F *RESTRICT xyz)
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
32void
33cnanovdb_coord_fract(cnanovdb_coord *RESTRICT coord, cnanovdb_Vec3F *RESTRICT fraction, const cnanovdb_Vec3F *RESTRICT xyz)
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) \
58typedef struct \
59{ \
60 VALUETYPE mStencil[2][2][2]; \
61 cnanovdb_coord mCoord; \
62} cnanovdb_stencil1##SUFFIX; \
63 \
64void \
65cnanovdb_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 \
73void \
74cnanovdb_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 \
99void \
100cnanovdb_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)
112 CREATE_STENCIL(cnanovdb_Vec3F, F3)
113
114
115#define CREATE_LERPSIMPLE(VALUETYPE, SUFFIX) \
116VALUETYPE \
117cnanovdb_lerp##SUFFIX(VALUETYPE a, VALUETYPE b, float w) \
118{ \
119 return a + w * (b - a); \
120} \
121/**/
122
123 CREATE_LERPSIMPLE(float, F)
124 CREATE_LERPSIMPLE(double, D)
125
126 cnanovdb_Vec3F
127cnanovdb_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) \
136VALUETYPE \
137cnanovdb_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 \
144VALUETYPE \
145cnanovdb_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 \
186VALUETYPE \
187cnanovdb_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
223void
224cnanovdb_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
243void
244cnanovdb_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
293void
294cnanovdb_sampleF_gradient0_stencil(cnanovdb_Vec3F *RESTRICT ret, cnanovdb_stencil1F *RESTRICT stencil, cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_Vec3F *RESTRICT xyz)
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
cnanovdb_readaccessor_getValueF
float cnanovdb_readaccessor_getValueF(cnanovdb_readaccessor *__restrict acc, const cnanovdb_coord *__restrict ijk)
Definition: CNanoVDB.h:682
RESTRICT
#define RESTRICT
Definition: CNanoVDB.h:33
cnanovdb_stencil1F_update
void cnanovdb_stencil1F_update(cnanovdb_stencil1F *__restrict stencil, cnanovdb_readaccessor *__restrict acc, cnanovdb_coord *__restrict coord)
Definition: CSampleFromVoxels.h:111
cnanovdb_sampleF_gradient
void cnanovdb_sampleF_gradient(cnanovdb_Vec3F *__restrict ret, cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:224
cnanovdb_coord_fract
void cnanovdb_coord_fract(cnanovdb_coord *__restrict coord, cnanovdb_Vec3F *__restrict fraction, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:33
CREATE_SAMPLE
#define CREATE_SAMPLE(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:135
cnanovdb_sampleF_gradient0
void cnanovdb_sampleF_gradient0(cnanovdb_Vec3F *__restrict ret, cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:244
cnanovdb_coord_round
void cnanovdb_coord_round(cnanovdb_coord *__restrict coord, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:19
cnanovdb_sampleF_gradient0_stencil
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
CREATE_LERPSIMPLE
#define CREATE_LERPSIMPLE(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:115
cnanovdb_lerpF3
cnanovdb_Vec3F cnanovdb_lerpF3(cnanovdb_Vec3F a, cnanovdb_Vec3F b, float w)
Definition: CSampleFromVoxels.h:127
cnanovdb_sampleF_trilinear
float cnanovdb_sampleF_trilinear(cnanovdb_readaccessor *__restrict acc, const cnanovdb_Vec3F *__restrict xyz)
Definition: CSampleFromVoxels.h:220
cnanovdb_lerpF
float cnanovdb_lerpF(float a, float b, float w)
Definition: CSampleFromVoxels.h:123
CREATE_STENCIL
#define CREATE_STENCIL(VALUETYPE, SUFFIX)
Definition: CSampleFromVoxels.h:57
cnanovdb_Vec3F
Definition: CNanoVDB.h:91
cnanovdb_Vec3F::mVec
float mVec[3]
Definition: CNanoVDB.h:92
cnanovdb_coord
Definition: CNanoVDB.h:96
cnanovdb_coord::mVec
int32_t mVec[3]
Definition: CNanoVDB.h:97
cnanovdb_readaccessor
Definition: CNanoVDB.h:286
cnanovdb_stencil1F
Definition: CSampleFromVoxels.h:111