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 extract_dense_voxels<openvdb::BoolGrid, float>(grid, bbox, r_voxels);
56 extract_dense_voxels<openvdb::FloatGrid, float>(grid, bbox, r_voxels);
60 extract_dense_voxels<openvdb::DoubleGrid, float>(grid, bbox, r_voxels);
64 extract_dense_voxels<openvdb::Int32Grid, float>(grid, bbox, r_voxels);
68 extract_dense_voxels<openvdb::Int64Grid, float>(grid, bbox, r_voxels);
72 extract_dense_voxels<openvdb::MaskGrid, float>(grid, bbox, r_voxels);
76 extract_dense_voxels<openvdb::Vec3fGrid, openvdb::Vec3f>(
77 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
81 extract_dense_voxels<openvdb::Vec3dGrid, openvdb::Vec3f>(
82 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
86 extract_dense_voxels<openvdb::Vec3IGrid, openvdb::Vec3f>(
87 grid, bbox,
reinterpret_cast<openvdb::Vec3f *
>(r_voxels));
97static void create_texture_to_object_matrix(
const openvdb::Mat4d &grid_transform,
98 const openvdb::CoordBBox &bbox,
99 float r_texture_to_object[4][4])
101 float index_to_object[4][4];
102 memcpy(index_to_object, openvdb::Mat4s(grid_transform).asPointer(),
sizeof(index_to_object));
104 float texture_to_index[4][4];
105 const openvdb::Vec3f loc = bbox.min().asVec3s() - openvdb::Vec3s(0.5f);
106 const openvdb::Vec3f
size = bbox.dim().asVec3s();
110 mul_m4_m4m4(r_texture_to_object, index_to_object, texture_to_index);
116 const blender::bke::VolumeGridData *volume_grid,
121 blender::bke::VolumeTreeAccessToken tree_token;
122 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
124 const openvdb::CoordBBox bbox = grid.evalActiveVoxelBoundingBox();
128 const std::array<int64_t, 6> bbox_indices = {
UNPACK3(openvdb::math::Abs(bbox.min())),
129 UNPACK3(openvdb::math::Abs(bbox.max()))};
130 const int64_t max_bbox_index = *std::max_element(bbox_indices.begin(), bbox_indices.end());
131 if (max_bbox_index > (1 << 30)) {
137 const openvdb::Vec3i resolution = bbox.dim().asVec3i();
142 if (voxels ==
nullptr) {
146 extract_dense_float_voxels(grid_type, grid, bbox, voxels);
147 create_texture_to_object_matrix(grid.transform().baseMap()->getAffineMap()->getMat4(),
151 r_dense_grid->
voxels = voxels;
162 if (dense_grid->
voxels !=
nullptr) {
172template<
typename Gr
idType>
176 using TreeType =
typename GridType::TreeType;
177 using Depth2Type =
typename TreeType::RootNodeType::ChildNodeType::ChildNodeType;
178 using NodeCIter =
typename TreeType::NodeCIter;
181 const int depth = coarse ? 2 : 3;
183 NodeCIter iter = grid.tree().cbeginNode();
184 iter.setMaxDepth(depth);
186 for (; iter; ++iter) {
187 if (iter.getDepth() != depth) {
191 openvdb::CoordBBox box;
194 const Depth2Type *node =
nullptr;
197 node->evalActiveBoundingBox(box,
false);
205 if (!iter.getBoundingBox(box)) {
211 box.max() = box.max().offsetBy(1);
219struct GetBoundingBoxesOp {
220 const openvdb::GridBase &grid;
223 template<
typename Gr
idType> blender::Vector<openvdb::CoordBBox>
operator()()
225 return get_bounding_boxes(
static_cast<const GridType &
>(grid), coarse);
230 const openvdb::GridBase &grid,
233 GetBoundingBoxesOp op{grid, coarse};
234 return BKE_volume_grid_type_operation(grid_type, op);
238 const openvdb::math::Transform &
transform,
243 openvdb::Vec3d center =
transform.indexToWorld(boxes[
i].getCenter());
249 const openvdb::math::Transform &
transform,
254 const openvdb::CoordBBox &box = boxes[
i];
257 std::array<openvdb::Coord, 8>
corners;
258 box.getCornerPoints(
corners.data());
260 for (
int j = 0; j < 8; j++) {
261 openvdb::Coord corner_i =
corners[j];
262 openvdb::Vec3d corner_d =
transform.indexToWorld(corner_i);
263 r_verts[8 *
i + j] =
blender::float3(corner_d[0], corner_d[1], corner_d[2]);
269 const openvdb::math::Transform &
transform,
275 const int box_edges[12][2] = {
290 int vert_offset = r_verts.
size();
291 int edge_offset = r_edges.size();
293 const int vert_amount = 8 * boxes.
size();
294 const int edge_amount = 12 * boxes.
size();
297 r_edges.resize(r_edges.size() + edge_amount);
300 for (
int i = 0;
i < boxes.
size();
i++) {
301 for (
int j = 0; j < 12; j++) {
302 r_edges[edge_offset + j] = {vert_offset + box_edges[j][0], vert_offset + box_edges[j][1]};
310 const openvdb::math::Transform &
transform,
314 const int box_tris[12][3] = {
329 int vert_offset = r_verts.
size();
330 int tri_offset = r_tris.size();
332 const int vert_amount = 8 * boxes.
size();
333 const int tri_amount = 12 * boxes.
size();
336 r_tris.resize(r_tris.size() + tri_amount);
339 for (
int i = 0;
i < boxes.
size();
i++) {
340 for (
int j = 0; j < 12; j++) {
341 r_tris[tri_offset + j] = {vert_offset + box_tris[j][0],
342 vert_offset + box_tris[j][1],
343 vert_offset + box_tris[j][2]};
353 const blender::bke::VolumeGridData *volume_grid,
358 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
363 blender::bke::VolumeTreeAccessToken tree_token;
364 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
368 openvdb::CoordBBox box;
371 if (grid.baseTree().evalLeafBoundingBox(box)) {
372 boxes_to_edge_mesh({box}, grid.transform(),
verts, edges);
375 (
float (*)[3])
verts.data(),
376 (int (*)[2])edges.
data(),
382 volume_grid->grid_type(),
391 boxes_to_center_points(boxes, grid.transform(),
verts);
394 boxes_to_edge_mesh(boxes, grid.transform(),
verts, edges);
398 (
float (*)[3])
verts.data(),
399 (int (*)[2])edges.
data(),
406 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
419 for (
const std::array<int, 3> &tri : tris) {
420 offsets[tri[0]] += factor * (2 *
verts[tri[0]] -
verts[tri[1]] -
verts[tri[2]]);
421 offsets[tri[1]] += factor * (2 *
verts[tri[1]] -
verts[tri[0]] -
verts[tri[2]]);
422 offsets[tri[2]] += factor * (2 *
verts[tri[2]] -
verts[tri[0]] -
verts[tri[1]]);
423 weights[tri[0]] += 1.0;
424 weights[tri[1]] += 1.0;
425 weights[tri[2]] += 1.0;
428 for (
const int i :
verts.index_range()) {
429 if (weights[
i] > 0.0f) {
430 verts[
i] += offsets[
i] / weights[
i];
437 const blender::bke::VolumeGridData *volume_grid,
442 blender::bke::VolumeTreeAccessToken tree_token;
443 const openvdb::GridBase &grid = volume_grid->grid(tree_token);
445 volume_grid->grid_type(), grid,
true);
449 boxes_to_cube_mesh(boxes, grid.transform(),
verts, tris);
453 const float offset_factor = 0.01f;
454 grow_triangles(
verts, tris, offset_factor);
456 cb(cb_userdata, (
float (*)[3])
verts.data(), (int (*)[3])tris.
data(),
verts.size(), tris.
size());
459 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
468 float unit[3] = {1.0f, 1.0f, 1.0f};
471 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, float(*verts)[3], int(*tris)[3], int totvert, int tottris) BKE_volume_selection_surface_cb
void(*)( void *userdata, const float(*verts)[3], const int(*edges)[2], int totvert, int totedge) BKE_volume_wireframe_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.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr int64_t size() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
int get_channels_num(VolumeGridType type)
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
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)