35 # include <openvdb/openvdb.h>
36 # include <openvdb/tools/Dense.h>
43 template<
typename Gr
idType,
typename VoxelType>
44 static void extract_dense_voxels(
const openvdb::GridBase &grid,
45 const openvdb::CoordBBox bbox,
49 openvdb::tools::Dense<VoxelType, openvdb::tools::LayoutXYZ> dense(bbox, r_voxels);
50 openvdb::tools::copyToDense(
static_cast<const GridType &
>(grid), dense);
53 static void extract_dense_float_voxels(
const VolumeGridType grid_type,
54 const openvdb::GridBase &grid,
55 const openvdb::CoordBBox &bbox,
60 return extract_dense_voxels<openvdb::BoolGrid, float>(grid, bbox, r_voxels);
62 return extract_dense_voxels<openvdb::FloatGrid, float>(grid, bbox, r_voxels);
64 return extract_dense_voxels<openvdb::DoubleGrid, float>(grid, bbox, r_voxels);
66 return extract_dense_voxels<openvdb::Int32Grid, float>(grid, bbox, r_voxels);
68 return extract_dense_voxels<openvdb::Int64Grid, float>(grid, bbox, r_voxels);
70 return extract_dense_voxels<openvdb::MaskGrid, float>(grid, bbox, r_voxels);
72 return extract_dense_voxels<openvdb::Vec3fGrid, openvdb::Vec3f>(
75 return extract_dense_voxels<openvdb::Vec3dGrid, openvdb::Vec3f>(
78 return extract_dense_voxels<openvdb::Vec3IGrid, openvdb::Vec3f>(
88 static void create_texture_to_object_matrix(
const openvdb::Mat4d &grid_transform,
89 const openvdb::CoordBBox &bbox,
90 float r_texture_to_object[4][4])
92 float index_to_object[4][4];
93 memcpy(index_to_object, openvdb::Mat4s(grid_transform).asPointer(),
sizeof(index_to_object));
95 float texture_to_index[4][4];
101 mul_m4_m4m4(r_texture_to_object, index_to_object, texture_to_index);
112 openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
114 const openvdb::CoordBBox bbox = grid->evalActiveVoxelBoundingBox();
121 static_cast<int64_t>(resolution[1]) *
122 static_cast<int64_t>(resolution[2]);
124 const int elem_size =
sizeof(
float) * channels;
125 float *voxels =
static_cast<float *
>(
MEM_malloc_arrayN(num_voxels, elem_size, __func__));
126 if (voxels ==
nullptr) {
130 extract_dense_float_voxels(grid_type, *grid, bbox, voxels);
131 create_texture_to_object_matrix(grid->transform().baseMap()->getAffineMap()->getMat4(),
135 r_dense_grid->
voxels = voxels;
146 if (dense_grid->
voxels !=
nullptr) {
156 template<
typename Gr
idType>
160 using TreeType =
typename GridType::TreeType;
161 using Depth2Type =
typename TreeType::RootNodeType::ChildNodeType::ChildNodeType;
162 using NodeCIter =
typename TreeType::NodeCIter;
165 const int depth = coarse ? 2 : 3;
167 NodeCIter iter = grid.tree().cbeginNode();
168 iter.setMaxDepth(depth);
170 for (; iter; ++iter) {
171 if (iter.getDepth() != depth) {
175 openvdb::CoordBBox box;
178 const Depth2Type *
node =
nullptr;
181 node->evalActiveBoundingBox(box,
false);
189 if (!iter.getBoundingBox(box)) {
195 box.max() = box.max().offsetBy(1);
203 struct GetBoundingBoxesOp {
204 const openvdb::GridBase &grid;
209 return get_bounding_boxes(
static_cast<const GridType &
>(grid), coarse);
214 const openvdb::GridBase &grid,
217 GetBoundingBoxesOp op{grid, coarse};
218 return BKE_volume_grid_type_operation(grid_type, op);
238 const openvdb::CoordBBox &box = boxes[i];
241 std::array<openvdb::Coord, 8> corners;
242 box.getCornerPoints(corners.data());
244 for (
int j = 0; j < 8; j++) {
245 openvdb::Coord corner_i = corners[j];
247 r_verts[8 * i + j] =
blender::float3(corner_d[0], corner_d[1], corner_d[2]);
259 const int box_edges[12][2] = {
274 int vert_offset = r_verts.
size();
275 int edge_offset = r_edges.size();
277 const int vert_amount = 8 * boxes.
size();
278 const int edge_amount = 12 * boxes.
size();
281 r_edges.resize(r_edges.size() + edge_amount);
284 for (
int i = 0; i < boxes.
size(); i++) {
285 for (
int j = 0; j < 12; j++) {
286 r_edges[edge_offset + j] = {vert_offset + box_edges[j][0], vert_offset + box_edges[j][1]};
298 const int box_tris[12][3] = {
313 int vert_offset = r_verts.
size();
314 int tri_offset = r_tris.size();
316 const int vert_amount = 8 * boxes.
size();
317 const int tri_amount = 12 * boxes.
size();
320 r_tris.resize(r_tris.size() + tri_amount);
323 for (
int i = 0; i < boxes.
size(); i++) {
324 for (
int j = 0; j < 12; j++) {
325 r_tris[tri_offset + j] = {vert_offset + box_tris[j][0],
326 vert_offset + box_tris[j][1],
327 vert_offset + box_tris[j][2]};
342 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
347 openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
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(),
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);
401 for (
const std::array<int, 3> &tri : tris) {
402 offsets[tri[0]] += factor * (2 *
verts[tri[0]] -
verts[tri[1]] -
verts[tri[2]]);
403 offsets[tri[1]] += factor * (2 *
verts[tri[1]] -
verts[tri[0]] -
verts[tri[2]]);
404 offsets[tri[2]] += factor * (2 *
verts[tri[2]] -
verts[tri[0]] -
verts[tri[1]]);
407 for (
const int i :
verts.index_range()) {
408 verts[i] += offsets[i];
419 openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
425 boxes_to_cube_mesh(boxes, grid->transform(),
verts, tris);
429 const float offset_factor = 0.01f;
430 grow_triangles(
verts, tris, offset_factor);
432 cb(cb_userdata, (
float(*)[3])
verts.data(), (
int(*)[3])tris.
data(),
verts.size(), tris.
size());
435 cb(cb_userdata,
nullptr,
nullptr, 0, 0);
444 float unit[3] = {1.0f, 1.0f, 1.0f};
447 return 1.0f /
len_v3(unit);
typedef float(TangentPoint)[2]
VolumeGridType BKE_volume_grid_type(const struct VolumeGrid *grid)
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_VECTOR_DOUBLE
int BKE_volume_grid_channels(const struct VolumeGrid *grid)
Volume data-block rendering and viewport drawing utilities.
void(* BKE_volume_wireframe_cb)(void *userdata, float(*verts)[3], int(*edges)[2], int totvert, int totedge)
void(* BKE_volume_selection_surface_cb)(void *userdata, float(*verts)[3], int(*tris)[3], int totvert, int tottris)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_mat3_m4_v3(const float M[4][4], float r[3])
void size_to_mat4(float R[4][4], const float size[3])
MINLINE float normalize_v3(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 len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ VOLUME_WIREFRAME_POINTS
@ VOLUME_WIREFRAME_BOUNDS
@ VOLUME_WIREFRAME_COARSE
NSNotificationCenter * center
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
MutableSpan< T > as_mutable_span()
void append(const T &value)
void resize(const int64_t new_size)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void(* MEM_freeN)(void *vmemh)
VecMat::Vec3< double > Vec3d
VecMat::Vec3< int > Vec3i
float texture_to_object[4][4]
bool BKE_volume_grid_dense_floats(const Volume *volume, const VolumeGrid *volume_grid, DenseFloatVolumeGrid *r_dense_grid)
void BKE_volume_dense_float_grid_clear(DenseFloatVolumeGrid *dense_grid)
void BKE_volume_grid_wireframe(const Volume *volume, const VolumeGrid *volume_grid, BKE_volume_wireframe_cb cb, void *cb_userdata)
float BKE_volume_density_scale(const Volume *volume, const float matrix[4][4])
void BKE_volume_grid_selection_surface(const Volume *volume, const VolumeGrid *volume_grid, BKE_volume_selection_surface_cb cb, void *cb_userdata)