57 #define VOLUME_FRAME_NONE INT_MAX
69 # include <unordered_set>
71 # include <openvdb/openvdb.h>
72 # include <openvdb/points/PointDataGrid.h>
73 # include <openvdb/tools/GridTransformer.h>
96 static struct VolumeFileCache {
100 : filepath(filepath), grid_name(grid->getName()), grid(grid)
105 : filepath(other.filepath),
106 grid_name(other.grid_name),
108 is_loaded(other.is_loaded)
116 if (simplify_level == 0 || !is_loaded) {
126 simple_grid = simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
127 const float resolution_factor = 1.0f / (1 << simplify_level);
128 const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid);
129 return BKE_volume_grid_create_with_changed_resolution(
130 grid_type, *grid, resolution_factor);
137 std::string filepath;
138 std::string grid_name;
147 mutable bool is_loaded =
false;
149 std::string error_msg;
151 int num_metadata_users = 0;
152 int num_tree_users = 0;
160 std::hash<std::string> string_hasher;
162 string_hasher(entry.grid_name));
169 return a.filepath ==
b.filepath &&
a.grid_name ==
b.grid_name;
179 Entry *add_metadata_user(
const Entry &template_entry)
182 EntrySet::iterator it = cache.find(template_entry);
183 if (it == cache.end()) {
184 it = cache.emplace(template_entry).first;
189 entry.num_metadata_users++;
196 void copy_user(
Entry &entry,
const bool tree_user)
200 entry.num_tree_users++;
203 entry.num_metadata_users++;
207 void remove_user(
Entry &entry,
const bool tree_user)
211 entry.num_tree_users--;
214 entry.num_metadata_users--;
216 update_for_remove_user(entry);
219 void change_to_tree_user(
Entry &entry)
222 entry.num_tree_users++;
223 entry.num_metadata_users--;
224 update_for_remove_user(entry);
227 void change_to_metadata_user(
Entry &entry)
230 entry.num_metadata_users++;
231 entry.num_tree_users--;
232 update_for_remove_user(entry);
236 void update_for_remove_user(
Entry &entry)
241 if (entry.num_metadata_users + entry.num_tree_users == 0) {
244 else if (entry.num_tree_users == 0) {
247 entry.grid = entry.grid->copyGridWithNewTree();
248 entry.simplified_grids.clear();
249 entry.is_loaded = false;
255 using EntrySet = std::unordered_set<Entry, EntryHasher, EntryEqual>;
268 : entry(nullptr), simplify_level(simplify_level), is_loaded(false)
274 : entry(nullptr), local_grid(grid), is_loaded(true)
279 : entry(other.entry),
280 simplify_level(other.simplify_level),
281 local_grid(other.local_grid),
282 is_loaded(other.is_loaded)
296 void load(
const char *volume_name,
const char *filepath)
const
299 if (is_loaded || entry ==
nullptr) {
304 std::lock_guard<std::mutex>
lock(entry->mutex);
313 if (entry->is_loaded) {
319 CLOG_INFO(&
LOG, 1,
"Volume %s: load grid '%s'", volume_name, name());
321 openvdb::io::File
file(filepath);
329 const bool delay_load =
false;
330 file.setCopyMaxBytes(0);
331 file.open(delay_load);
333 entry->grid->setTree(vdb_grid->baseTreePtr());
335 catch (
const openvdb::IoError &
e) {
336 entry->error_msg =
e.what();
340 std::atomic_thread_fence(std::memory_order_release);
341 entry->is_loaded =
true;
345 void unload(
const char *volume_name)
const
348 if (!is_loaded || entry ==
nullptr) {
353 std::lock_guard<std::mutex>
lock(entry->mutex);
358 CLOG_INFO(&
LOG, 1,
"Volume %s: unload grid '%s'", volume_name, name());
365 std::atomic_thread_fence(std::memory_order_release);
369 void clear_reference(
const char *
UNUSED(volume_name))
372 local_grid = grid()->copyGridWithNewTree();
380 void duplicate_reference(
const char *volume_name,
const char *filepath)
384 load(volume_name, filepath);
386 local_grid = grid()->deepCopyGrid();
394 const char *name()
const
398 openvdb::StringMetadata::ConstPtr name_meta =
399 main_grid()->getMetadata<openvdb::StringMetadata>(openvdb::GridBase::META_GRID_NAME);
400 return (name_meta) ? name_meta->value().c_str() :
"";
403 const char *error_message()
const
405 if (is_loaded && entry && !entry->error_msg.empty()) {
406 return entry->error_msg.c_str();
412 bool grid_is_loaded()
const
420 return entry->simplified_grid(simplify_level);
425 void set_simplify_level(
const int simplify_level)
428 this->simplify_level = simplify_level;
434 return (entry) ? entry->grid : local_grid;
443 int simplify_level = 0;
453 mutable bool is_loaded;
461 struct VolumeGridVector :
public std::list<VolumeGrid> {
462 VolumeGridVector() : metadata(
new openvdb::MetaMap())
467 VolumeGridVector(
const VolumeGridVector &other)
468 :
std::list<
VolumeGrid>(other), error_msg(other.error_msg), metadata(other.metadata)
470 memcpy(filepath, other.filepath,
sizeof(filepath));
473 bool is_loaded()
const
475 return filepath[0] !=
'\0';
492 std::string error_msg;
536 const VolumeGridVector &grids_src = *(volume_src->
runtime.
grids);
537 volume_dst->
runtime.
grids = MEM_new<VolumeGridVector>(__func__, grids_src);
559 for (
int i = 0; i < volume->
totcol; i++) {
571 offsetof(
Volume, runtime.grids),
636 for (
int a = 0;
a < volume->
totcol;
a++) {
644 for (
int a = 0;
a < volume->
totcol;
a++) {
683 volume->
runtime.
grids = MEM_new<VolumeGridVector>(__func__);
707 int path_frame, path_digits;
718 if (frame_duration == 0) {
722 int frame = scene_frame - frame_start + 1;
726 if (frame < 1 || frame > frame_duration) {
732 frame =
clamp_i(frame, 1, frame_duration);
736 frame = frame % frame_duration;
738 frame += frame_duration;
741 frame = frame_duration;
746 const int pingpong_duration = frame_duration * 2 - 2;
747 frame = frame % pingpong_duration;
749 frame += pingpong_duration;
752 frame = pingpong_duration;
754 if (frame > frame_duration) {
755 frame = frame_duration * 2 - frame;
762 frame += frame_offset;
768 static void volume_filepath_get(
const Main *bmain,
const Volume *volume,
char r_filepath[
FILE_MAX])
773 int path_frame, path_digits;
809 const StringRefNull postfixes[][3] = {{
"x",
"y",
"z"}, {
".x",
".y",
".z"}, {
"_x",
"_y",
"_z"}};
813 for (
int i = 0; i < 3; i++) {
814 std::string post_fixed_name = ref_base_name + postfix[i];
828 (ref_base_name + postfix[0]).c_str(),
831 (ref_base_name + postfix[1]).c_str(),
834 (ref_base_name + postfix[2]).c_str(),
850 const VolumeGridVector &const_grids = *volume->
runtime.
grids;
858 return const_grids.error_msg.empty();
862 std::lock_guard<std::mutex>
lock(const_grids.mutex);
864 return const_grids.error_msg.empty();
869 VolumeGridVector &grids =
const_cast<VolumeGridVector &
>(const_grids);
872 const char *volume_name = volume->
id.
name + 2;
874 volume_filepath_get(bmain, volume, filepath);
876 CLOG_INFO(&
LOG, 1,
"Volume %s: load %s", volume_name, filepath);
882 grids.error_msg = filename + std::string(
" not found");
883 CLOG_INFO(&
LOG, 1,
"Volume %s: %s", volume_name, grids.error_msg.c_str());
888 openvdb::io::File
file(filepath);
889 openvdb::GridPtrVec vdb_grids;
894 const bool delay_load =
false;
895 file.setCopyMaxBytes(0);
896 file.open(delay_load);
897 vdb_grids = *(
file.readAllGridMetadata());
898 grids.metadata =
file.getMetadata();
900 catch (
const openvdb::IoError &
e) {
901 grids.error_msg =
e.what();
902 CLOG_INFO(&
LOG, 1,
"Volume %s: %s", volume_name, grids.error_msg.c_str());
914 const char *common_velocity_names[] = {
"velocity",
"vel",
"v"};
915 for (
const char *common_velocity_name : common_velocity_names) {
923 return grids.error_msg.empty();
934 if (grids.filepath[0] !=
'\0') {
935 const char *volume_name = volume->
id.
name + 2;
949 const char *filepath)
958 openvdb::GridCPtrVec vdb_grids;
961 vdb_grids.push_back(BKE_volume_grid_openvdb_for_read(volume, &grid));
965 openvdb::io::File
file(filepath);
966 file.write(vdb_grids, *grids.metadata);
969 catch (
const openvdb::IoError &
e) {
983 bool have_minmax =
false;
991 openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
994 if (BKE_volume_grid_bounds(grid, grid_min, grid_max)) {
1016 ob->
runtime.
bb = MEM_cnew<BoundBox>(__func__);
1038 if (grids.metadata) {
1039 openvdb::StringMetadata::ConstPtr creator =
1040 grids.metadata->getMetadata<openvdb::StringMetadata>(
"creator");
1042 creator = grids.metadata->getMetadata<openvdb::StringMetadata>(
"Creator");
1044 return (creator && creator->str().rfind(
"Houdini", 0) == 0);
1056 if (num_grids == 0) {
1060 for (
int i = 0; i < num_grids; i++) {
1078 grid.set_simplify_level(simplify_level);
1106 for (; md; md = md->
next) {
1148 if (volume !=
nullptr) {
1173 if (volume_eval ==
nullptr) {
1178 const bool eval_is_owned = (volume != volume_eval);
1180 object->runtime.geometry_set_eval =
new GeometrySet(std::move(geometry_set));
1191 if (!grids->is_loaded()) {
1264 const VolumeGridVector &grids = *volume->
runtime.
grids;
1266 if (grid_index-- == 0) {
1282 if (grid_index-- == 0) {
1296 if (num_grids == 0) {
1307 for (
int i = 0; i < num_grids; i++) {
1323 const char *volume_name = volume->
id.
name + 2;
1324 grid->load(volume_name, grids.filepath);
1325 const char *error_msg = grid->error_message();
1327 grids.error_msg = error_msg;
1340 const char *volume_name = volume->
id.
name + 2;
1341 grid->unload(volume_name);
1350 return grid->grid_is_loaded();
1362 return volume_grid->name();
1370 struct ClearGridOp {
1371 openvdb::GridBase &grid;
1375 static_cast<Grid &
>(grid).
clear();
1378 void BKE_volume_grid_clear_tree(openvdb::GridBase &grid)
1380 const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid);
1381 ClearGridOp op{grid};
1382 BKE_volume_grid_type_operation(grid_type, op);
1387 BKE_volume_grid_clear_tree(*grid);
1390 VolumeGridType BKE_volume_grid_type_openvdb(
const openvdb::GridBase &grid)
1392 if (grid.isType<openvdb::FloatGrid>()) {
1395 if (grid.isType<openvdb::Vec3fGrid>()) {
1398 if (grid.isType<openvdb::BoolGrid>()) {
1401 if (grid.isType<openvdb::DoubleGrid>()) {
1404 if (grid.isType<openvdb::Int32Grid>()) {
1407 if (grid.isType<openvdb::Int64Grid>()) {
1410 if (grid.isType<openvdb::Vec3IGrid>()) {
1413 if (grid.isType<openvdb::Vec3dGrid>()) {
1416 if (grid.isType<openvdb::MaskGrid>()) {
1419 if (grid.isType<openvdb::points::PointDataGrid>()) {
1430 return BKE_volume_grid_type_openvdb(*grid);
1470 for (
int row = 0; row < 4; row++) {
1471 mat[
col][row] = matrix(
col, row);
1485 for (
int row = 0; row < 4; row++) {
1486 mat_openvdb(
col, row) = mat[
col][row];
1490 grid->setTransform(std::make_shared<openvdb::math::Transform>(
1491 std::make_shared<openvdb::math::AffineMap>(mat_openvdb)));
1529 struct CreateGridOp {
1532 if constexpr (std::is_same_v<GridType, openvdb::points::PointDataGrid>) {
1554 vdb_grid->setName(name);
1555 grids.emplace_back(vdb_grid);
1556 return &grids.back();
1572 vdb_grid->setName(name);
1573 grids.emplace_back(vdb_grid);
1574 return &grids.back();
1582 for (VolumeGridVector::iterator it = grids.begin(); it != grids.end(); it++) {
1610 if (simplify == 0.0f) {
1614 return ceilf(-log2(simplify));
1635 bool BKE_volume_grid_bounds(openvdb::GridBase::ConstPtr grid,
float3 &r_min,
float3 &r_max)
1638 openvdb::CoordBBox coordbbox;
1639 if (!grid->baseTree().evalLeafBoundingBox(coordbbox)) {
1643 openvdb::BBoxd bbox = grid->transform().indexToWorld(coordbbox);
1645 r_min =
float3((
float)bbox.min().x(), (
float)bbox.min().y(), (
float)bbox.min().z());
1646 r_max =
float3((
float)bbox.max().x(), (
float)bbox.max().y(), (
float)bbox.max().z());
1651 openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase::ConstPtr grid,
1655 grid_transform->postMult(openvdb::Mat4d(((
float *)
transform.values)));
1658 return grid->copyGridReplacingTransform(grid_transform);
1661 openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_metadata(
const VolumeGrid *grid)
1663 return grid->grid();
1666 openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(
const Volume *volume,
1670 return grid->grid();
1677 const char *volume_name = volume->
id.
name + 2;
1679 grid->clear_reference(volume_name);
1683 grid->duplicate_reference(volume_name, grids.filepath);
1686 return grid->grid();
1695 template<
typename Gr
idType>
1696 static typename GridType::Ptr create_grid_with_changed_resolution(
const GridType &old_grid,
1697 const float resolution_factor)
1701 openvdb::Mat4R xform;
1703 openvdb::tools::GridTransformer transformer{xform};
1705 typename GridType::Ptr new_grid = old_grid.copyWithNewTree();
1706 transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid);
1707 new_grid->transform() = old_grid.transform();
1708 new_grid->transform().preScale(1.0f / resolution_factor);
1709 new_grid->transform().postTranslate(-new_grid->voxelSize() / 2.0f);
1713 struct CreateGridWithChangedResolutionOp {
1714 const openvdb::GridBase &grid;
1715 const float resolution_factor;
1719 return create_grid_with_changed_resolution(
static_cast<const GridType &
>(grid),
1726 const openvdb::GridBase &old_grid,
1727 const float resolution_factor)
1729 CreateGridWithChangedResolutionOp op{old_grid, resolution_factor};
1730 return BKE_volume_grid_type_operation(grid_type, op);
void BKE_animdata_free(struct ID *id, bool do_id_user)
void BKE_animdata_blend_read_data(struct BlendDataReader *reader, struct AnimData *adt)
void BKE_animdata_blend_write(struct BlendWriter *writer, struct AnimData *adt)
bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path)
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
void(* IDTypeForeachCacheFunctionCallback)(struct ID *id, const struct IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data)
@ LIB_ID_COPY_CD_REFERENCE
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void * BKE_id_new_nomain(short type, const char *name)
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
void * BKE_id_new(struct Main *bmain, short type, const char *name)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
void BKE_modifiers_clear_errors(struct Object *ob)
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3])
void BKE_object_free_derived_caches(struct Object *ob)
void BKE_object_eval_assign_data(struct Object *object, struct ID *data, bool is_owned)
struct PackedFile * BKE_packedfile_duplicate(const struct PackedFile *pf_src)
void BKE_packedfile_blend_write(struct BlendWriter *writer, struct PackedFile *pf)
void BKE_packedfile_blend_read(struct BlendDataReader *reader, struct PackedFile **pf_p)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_VECTOR_DOUBLE
struct VolumeGrid VolumeGrid
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
KDTree *BLI_kdtree_nd_() new(unsigned int maxsize)
MINLINE int clamp_i(int value, int min, int max)
void unit_m4(float m[4][4])
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL()
bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL()
void BLI_path_frame_strip(char *path, char *r_ext, size_t ext_maxlen) ATTR_NONNULL()
void BLI_split_file_part(const char *string, char *file, size_t filelen)
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
#define STRNCPY(dst, src)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
#define INIT_MINMAX(min, max)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_expand(expander, id)
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
#define BLT_I18NCONTEXT_ID_VOLUME
#define CLOG_INFO(clg_ref, level,...)
struct Depsgraph Depsgraph
bool DEG_is_active(const struct Depsgraph *depsgraph)
float DEG_get_ctime(const Depsgraph *graph)
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
struct ID * DEG_get_original_id(struct ID *id)
#define ID_BLEND_PATH(_bmain, _id)
@ LIB_TAG_COPIED_ON_WRITE
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define DNA_struct_default_get(struct_name)
Object is a sort of wrapper for general info.
@ VOLUME_SEQUENCE_PING_PONG
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
btScalar determinant() const
Return the determinant of the matrix.
static ImGlobalTileCache GLOBAL_CACHE
void replace(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
constexpr const char * data() const
const Depsgraph * depsgraph
SyclQueue void void size_t num_bytes void
void *(* MEM_dupallocN)(const void *vmemh)
static void clear(Message *msg)
VecMat::Vec3< double > Vec3d
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
void isolate_task(const Function &function)
vec_base< float, 3 > float3
Eigen::Matrix< float, 4, 4 > Mat4f
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void remove(const GeometryComponentType component_type)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
bool has(const GeometryComponentType component_type) const
void replace_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
struct ModifierData * next
void(* modifyGeometrySet)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct GeometrySet *geometry_set)
struct VolumeGridVector * grids
int default_simplify_level
struct PackedFile * packedfile
static void initialize(SubdivDisplacement *displacement)
const VolumeGrid * BKE_volume_grid_active_get_for_read(const Volume *volume)
const char * BKE_volume_grids_error_msg(const Volume *volume)
#define VOLUME_FRAME_NONE
int BKE_volume_grid_channels(const VolumeGrid *grid)
bool BKE_volume_grid_is_loaded(const VolumeGrid *grid)
bool BKE_volume_is_loaded(const Volume *volume)
void BKE_volume_batch_cache_free(Volume *volume)
bool BKE_volume_is_y_up(const Volume *volume)
static void volume_evaluate_modifiers(struct Depsgraph *depsgraph, struct Scene *scene, Object *object, GeometrySet &geometry_set)
int BKE_volume_num_grids(const Volume *volume)
const VolumeGrid * BKE_volume_grid_get_for_read(const Volume *volume, int grid_index)
const char * BKE_volume_grid_name(const VolumeGrid *volume_grid)
bool BKE_volume_save(const Volume *volume, const Main *bmain, ReportList *reports, const char *filepath)
const char * BKE_volume_grids_frame_filepath(const Volume *volume)
void BKE_volume_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
void BKE_volume_batch_cache_dirty_tag(Volume *volume, int mode)
bool BKE_volume_load(const Volume *volume, const Main *bmain)
void BKE_volume_grid_remove(Volume *volume, VolumeGrid *grid)
static void volume_update_simplify_level(Volume *volume, const Depsgraph *depsgraph)
bool BKE_volume_is_points_only(const Volume *volume)
static void volume_init_data(ID *id)
bool BKE_volume_min_max(const Volume *volume, float3 &r_min, float3 &r_max)
static int volume_sequence_frame(const Depsgraph *depsgraph, const Volume *volume)
void(* BKE_volume_batch_cache_dirty_tag_cb)(Volume *volume, int mode)
void * BKE_volume_add(Main *bmain, const char *name)
VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid)
VolumeGrid * BKE_volume_grid_get_for_write(Volume *volume, int grid_index)
bool BKE_volume_grid_determinant_valid(const double determinant)
static void volume_blend_read_expand(BlendExpander *expander, ID *id)
static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
void BKE_volume_grid_transform_matrix_set(struct VolumeGrid *volume_grid, const float mat[4][4])
Volume * BKE_volume_copy_for_eval(Volume *volume_src, bool reference)
static void volume_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
int BKE_volume_simplify_level(const Depsgraph *depsgraph)
static void volume_free_data(ID *id)
void BKE_volume_grid_transform_matrix(const VolumeGrid *volume_grid, float mat[4][4])
float BKE_volume_simplify_factor(const Depsgraph *depsgraph)
void BKE_volume_unload(Volume *volume)
void(* BKE_volume_batch_cache_free_cb)(Volume *volume)
static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address)
void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, Volume *volume)
static void volume_blend_read_data(BlendDataReader *reader, ID *id)
bool BKE_volume_set_velocity_grid_by_name(Volume *volume, const char *base_name)
static Volume * take_volume_ownership_from_geometry_set(GeometrySet &geometry_set)
bool BKE_volume_grid_load(const Volume *volume, const VolumeGrid *grid)
const VolumeGrid * BKE_volume_grid_find_for_read(const Volume *volume, const char *name)
static void volume_foreach_id(ID *id, LibraryForeachIDData *data)
Volume * BKE_volume_new_for_eval(const Volume *volume_src)
void BKE_volume_grid_unload(const Volume *volume, const VolumeGrid *grid)
static void volume_blend_read_lib(BlendLibReader *reader, ID *id)
BoundBox * BKE_volume_boundbox_get(Object *ob)
static void volume_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int UNUSED(flag))
void BKE_volume_grids_backup_restore(Volume *volume, VolumeGridVector *grids, const char *filepath)
void BKE_volume_init_grids(Volume *volume)
VolumeGrid * BKE_volume_grid_add(Volume *volume, const char *name, VolumeGridType type)