25# include <openvdb/openvdb.h>
26# include <openvdb/tools/Dense.h>
33template<
typename Gr
idType,
typename VoxelType>
34static void extract_dense_voxels(
const openvdb::GridBase &grid,
35 const openvdb::CoordBBox bbox,
40 openvdb::tools::Dense<VoxelType, openvdb::tools::LayoutXYZ> dense(bbox, r_voxels);
41 openvdb::tools::copyToDense(static_cast<const GridType &>(grid), dense);
45static void extract_dense_float_voxels(
const VolumeGridType grid_type,
46 const openvdb::GridBase &grid,
47 const openvdb::CoordBBox &bbox,
52 return extract_dense_voxels<openvdb::BoolGrid, float>(grid, bbox, r_voxels);
54 return extract_dense_voxels<openvdb::FloatGrid, float>(grid, bbox, r_voxels);
56 return extract_dense_voxels<openvdb::DoubleGrid, float>(grid, bbox, r_voxels);
58 return extract_dense_voxels<openvdb::Int32Grid, float>(grid, bbox, r_voxels);
60 return extract_dense_voxels<openvdb::Int64Grid, float>(grid, bbox, r_voxels);
62 return extract_dense_voxels<openvdb::MaskGrid, float>(grid, bbox, r_voxels);
64 return extract_dense_voxels<openvdb::Vec3fGrid, openvdb::Vec3f>(
65 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
67 return extract_dense_voxels<openvdb::Vec3dGrid, openvdb::Vec3f>(
68 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
70 return extract_dense_voxels<openvdb::Vec3IGrid, openvdb::Vec3f>(
71 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
79static void create_texture_to_object_matrix(
const openvdb::Mat4d &grid_transform,
80 const openvdb::CoordBBox &bbox,
81 float r_texture_to_object[4][4])
83 float index_to_object[4][4];
84 memcpy(index_to_object, openvdb::Mat4s(grid_transform).asPointer(),
sizeof(index_to_object));
86 float texture_to_index[4][4];
87 const openvdb::Vec3f loc = bbox.min().asVec3s();
88 const openvdb::Vec3f size = bbox.dim().asVec3s();
92 mul_m4_m4m4(r_texture_to_object, index_to_object, texture_to_index);
98 const blender::bke::VolumeGridData *volume_grid,
103 blender::bke::VolumeTreeAccessToken tree_token;
104 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
106 const openvdb::CoordBBox bbox = grid.evalActiveVoxelBoundingBox();
110 const std::array<int64_t, 6> bbox_indices = {
UNPACK3(openvdb::math::Abs(bbox.min())),
111 UNPACK3(openvdb::math::Abs(bbox.max()))};
112 const int64_t max_bbox_index = *std::max_element(bbox_indices.begin(), bbox_indices.end());
113 if (max_bbox_index > (1 << 30)) {
119 const openvdb::Vec3i resolution = bbox.dim().asVec3i();
123 const int elem_size =
sizeof(
float) * channels;
124 float *voxels =
static_cast<float *
>(
MEM_malloc_arrayN(num_voxels, elem_size, __func__));
125 if (voxels ==
nullptr) {
129 extract_dense_float_voxels(grid_type, grid, bbox, voxels);
130 create_texture_to_object_matrix(grid.transform().baseMap()->getAffineMap()->getMat4(),
134 r_dense_grid->
voxels = voxels;
145 if (dense_grid->
voxels !=
nullptr) {
155template<
typename Gr
idType>
159 using TreeType =
typename GridType::TreeType;
160 using Depth2Type =
typename TreeType::RootNodeType::ChildNodeType::ChildNodeType;
161 using NodeCIter =
typename TreeType::NodeCIter;
164 const int depth = coarse ? 2 : 3;
166 NodeCIter iter = grid.tree().cbeginNode();
167 iter.setMaxDepth(depth);
169 for (; iter; ++iter) {
170 if (iter.getDepth() != depth) {
174 openvdb::CoordBBox box;
177 const Depth2Type *node =
nullptr;
180 node->evalActiveBoundingBox(box,
false);
188 if (!iter.getBoundingBox(box)) {
194 box.max() = box.max().offsetBy(1);
202struct GetBoundingBoxesOp {
203 const openvdb::GridBase &grid;
208 return get_bounding_boxes(
static_cast<const GridType &
>(grid), coarse);
213 const openvdb::GridBase &grid,
216 GetBoundingBoxesOp op{grid, coarse};
217 return BKE_volume_grid_type_operation(grid_type, op);
221 const openvdb::math::Transform &transform,
225 for (
const int i : boxes.index_range()) {
226 openvdb::Vec3d center = transform.indexToWorld(boxes[i].getCenter());
232 const openvdb::math::Transform &transform,
236 for (
const int i : boxes.index_range()) {
237 const openvdb::CoordBBox &box = boxes[i];
240 std::array<openvdb::Coord, 8> corners;
241 box.getCornerPoints(corners.data());
243 for (
int j = 0; j < 8; j++) {
244 openvdb::Coord corner_i = corners[j];
245 openvdb::Vec3d corner_d = transform.indexToWorld(corner_i);
246 r_verts[8 * i + j] =
blender::float3(corner_d[0], corner_d[1], corner_d[2]);
252 const openvdb::math::Transform &transform,
258 const int box_edges[12][2] = {
273 int vert_offset = r_verts.
size();
274 int edge_offset = r_edges.size();
276 const int vert_amount = 8 * boxes.
size();
277 const int edge_amount = 12 * boxes.
size();
280 r_edges.resize(r_edges.size() + edge_amount);
281 boxes_to_corner_points(boxes, transform, r_verts.
as_mutable_span().take_back(vert_amount));
283 for (
int i = 0; i < boxes.
size(); i++) {
284 for (
int j = 0; j < 12; j++) {
285 r_edges[edge_offset + j] = {vert_offset + box_edges[j][0], vert_offset + box_edges[j][1]};
293 const openvdb::math::Transform &transform,
297 const int box_tris[12][3] = {
312 int vert_offset = r_verts.
size();
313 int tri_offset = r_tris.size();
315 const int vert_amount = 8 * boxes.
size();
316 const int tri_amount = 12 * boxes.
size();
319 r_tris.resize(r_tris.size() + tri_amount);
320 boxes_to_corner_points(boxes, transform, r_verts.
as_mutable_span().take_back(vert_amount));
322 for (
int i = 0; i < boxes.
size(); i++) {
323 for (
int j = 0; j < 12; j++) {
324 r_tris[tri_offset + j] = {vert_offset + box_tris[j][0],
325 vert_offset + box_tris[j][1],
326 vert_offset + box_tris[j][2]};
336 const blender::bke::VolumeGridData *volume_grid,
341 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
346 blender::bke::VolumeTreeAccessToken tree_token;
347 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
351 openvdb::CoordBBox box;
354 if (grid.baseTree().evalLeafBoundingBox(box)) {
355 boxes_to_edge_mesh({box}, grid.transform(),
verts, edges);
358 (
float(*)[3])
verts.data(),
359 (
int(*)[2])edges.data(),
365 volume_grid->grid_type(),
374 boxes_to_center_points(boxes, grid.transform(),
verts);
377 boxes_to_edge_mesh(boxes, grid.transform(),
verts, edges);
381 (
float(*)[3])
verts.data(),
382 (
int(*)[2])edges.data(),
389 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
402 for (
const std::array<int, 3> &tri : tris) {
403 offsets[tri[0]] += factor * (2 *
verts[tri[0]] -
verts[tri[1]] -
verts[tri[2]]);
404 offsets[tri[1]] += factor * (2 *
verts[tri[1]] -
verts[tri[0]] -
verts[tri[2]]);
405 offsets[tri[2]] += factor * (2 *
verts[tri[2]] -
verts[tri[0]] -
verts[tri[1]]);
406 weights[tri[0]] += 1.0;
407 weights[tri[1]] += 1.0;
408 weights[tri[2]] += 1.0;
411 for (
const int i :
verts.index_range()) {
412 if (weights[i] > 0.0f) {
413 verts[i] += offsets[i] / weights[i];
420 const blender::bke::VolumeGridData *volume_grid,
425 blender::bke::VolumeTreeAccessToken tree_token;
426 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
428 volume_grid->grid_type(), grid,
true);
432 boxes_to_cube_mesh(boxes, grid.transform(),
verts, tris);
436 const float offset_factor = 0.01f;
437 grow_triangles(
verts, tris, offset_factor);
439 cb(cb_userdata, (
float(*)[3])
verts.data(), (
int(*)[3])tris.
data(),
verts.size(), tris.
size());
442 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
451 float unit[3] = {1.0f, 1.0f, 1.0f};
454 return 1.0f /
len_v3(unit);
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_VECTOR_DOUBLE
Volume data-block rendering and viewport drawing utilities.
void(*)( void *userdata, const float(*verts)[3], const int(*edges)[2], int totvert, int totedge) BKE_volume_wireframe_cb
void(*)(void *userdata, float(*verts)[3], int(*tris)[3], int totvert, int tottris) BKE_volume_selection_surface_cb
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void size_to_mat4(float R[4][4], const float size[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ VOLUME_WIREFRAME_POINTS
@ VOLUME_WIREFRAME_BOUNDS
@ VOLUME_WIREFRAME_COARSE
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
constexpr int64_t size() const
constexpr int64_t size() const
void append(const T &value)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
draw_view in_light_buf[] float
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
int get_channels_num(VolumeGridType type)
void memory_bandwidth_bound_task(const int64_t approximate_bytes_touched, const Function &function)
VecBase< float, 3 > float3
float texture_to_object[4][4]
void BKE_volume_dense_float_grid_clear(DenseFloatVolumeGrid *dense_grid)
bool BKE_volume_grid_dense_floats(const Volume *volume, const blender::bke::VolumeGridData *volume_grid, DenseFloatVolumeGrid *r_dense_grid)
float BKE_volume_density_scale(const Volume *volume, const float matrix[4][4])
void BKE_volume_grid_selection_surface(const Volume *, const blender::bke::VolumeGridData *volume_grid, BKE_volume_selection_surface_cb cb, void *cb_userdata)
void BKE_volume_grid_wireframe(const Volume *volume, const blender::bke::VolumeGridData *volume_grid, BKE_volume_wireframe_cb cb, void *cb_userdata)