34#include "RNA_prototypes.hh"
39# include <openvdb/openvdb.h>
40# include <openvdb/tools/Interpolation.h>
41# include <openvdb/tools/Morphology.h>
42# include <openvdb/tools/Prune.h>
43# include <openvdb/tools/ValueTransformer.h>
80 walk(user_data, ob, md, &
ptr, prop);
128 openvdb::Mat4s new_matrix{m.
base_ptr()};
132template<
typename Gr
idType>
struct DisplaceOp {
134 typename GridType::ConstAccessor accessor;
135 const openvdb::Mat4s index_to_texture;
138 const double strength;
139 const openvdb::Vec3d texture_mid_level;
141 void operator()(
const typename GridType::ValueOnIter &iter)
const
143 const openvdb::Coord coord = iter.getCoord();
144 const openvdb::Vec3d displace_vector = this->compute_displace_vector(coord);
147 const openvdb::Vec3d sample_coord = coord.asVec3d() - displace_vector;
148 const auto new_value = openvdb::tools::BoxSampler::sample(this->accessor, sample_coord);
149 iter.setValue(new_value);
152 openvdb::Vec3d compute_displace_vector(
const openvdb::Coord &coord)
const
154 if (this->
texture !=
nullptr) {
155 const openvdb::Vec3f texture_pos = coord.asVec3s() * this->index_to_texture;
156 const openvdb::Vec3d texture_value = this->evaluate_texture(texture_pos);
157 const openvdb::Vec3d displacement = (texture_value - this->texture_mid_level) *
161 return openvdb::Vec3d{0, 0, 0};
164 openvdb::Vec3d evaluate_texture(
const openvdb::Vec3f &
pos)
const
166 TexResult texture_result = {0};
168 return {texture_result.
trgba[0], texture_result.
trgba[1], texture_result.
trgba[2]};
172static float get_max_voxel_side_length(
const openvdb::GridBase &grid)
174 const openvdb::Vec3d voxel_size = grid.voxelSize();
175 const float max_voxel_side_length = std::max({voxel_size[0], voxel_size[1], voxel_size[2]});
176 return max_voxel_side_length;
179struct DisplaceGridOp {
181 openvdb::GridBase &base_grid;
184 const ModifierEvalContext &ctx;
188 if constexpr (blender::
189 is_same_any_v<GridType, openvdb::points::PointDataGrid, openvdb::MaskGrid>)
195 this->displace_grid<GridType>();
199 template<
typename Gr
idType>
void displace_grid()
201 GridType &grid =
static_cast<GridType &
>(base_grid);
204 typename GridType::Ptr temp_grid = grid.deepCopy();
208 const float max_voxel_side_length = get_max_voxel_side_length(grid);
210 max_voxel_side_length / 2.0f;
211 openvdb::tools::dilateActiveValues(temp_grid->tree(),
212 int(std::ceil(sample_radius)),
213 openvdb::tools::NN_FACE_EDGE,
214 openvdb::tools::EXPAND_TILES);
216 const openvdb::Mat4s index_to_texture = this->get_index_to_texture_transform();
219 DisplaceOp<GridType> displace_op{grid.getConstAccessor(),
222 vdmd.
strength / max_voxel_side_length,
227 openvdb::tools::foreach(temp_grid->beginValueOn(),
235 typename GridType::ValueType prune_tolerance{0};
236 openvdb::tools::deactivate(*temp_grid, temp_grid->background(), prune_tolerance);
237 openvdb::tools::prune(temp_grid->tree());
241 grid.merge(*temp_grid);
244 openvdb::Mat4s get_index_to_texture_transform()
const
246 const openvdb::Mat4s index_to_object{
247 base_grid.transform().baseMap()->getAffineMap()->getMat4()};
251 return index_to_object;
254 const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.
object->object_to_world());
255 return index_to_object * object_to_world;
259 return index_to_object;
261 const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.
object->object_to_world());
262 const openvdb::Mat4s world_to_texture = matrix_to_openvdb(
264 return index_to_object * object_to_world * world_to_texture;
282 for (
int grid_index = 0; grid_index < grid_amount; grid_index++) {
286 blender::bke::VolumeTreeAccessToken tree_token;
287 openvdb::GridBase &grid = volume_grid->grid_for_write(tree_token);
290 DisplaceGridOp displace_grid_op{grid, *vdmd, *ctx};
291 BKE_volume_grid_type_operation(grid_type, displace_grid_op);
305 if (input_volume !=
nullptr) {
312 N_(
"Volume Displace"),
313 "VolumeDisplaceModifierData",
315 &RNA_VolumeDisplaceModifier,
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
void(*)(void *user_data, Object *ob, ModifierData *md, const PointerRNA *ptr, PropertyRNA *texture_prop) TexWalkFunc
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_texture_get_value(struct Tex *texture, const float *tex_co, struct TexResult *texres, bool use_color_management)
bool BKE_texture_dependsOnTime(const struct Tex *texture)
int BKE_volume_num_grids(const Volume *volume)
bool BKE_volume_load(const Volume *volume, const Main *bmain)
blender::bke::VolumeGridData * BKE_volume_grid_get_for_write(Volume *volume, int grid_index)
MINLINE void copy_v3_fl(float r[3], float f)
void DEG_add_generic_id_relation(DepsNodeHandle *node_handle, ID *id, const char *description)
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
Main * DEG_get_bmain(const Depsgraph *graph)
struct VolumeDisplaceModifierData VolumeDisplaceModifierData
@ eModifierType_VolumeDisplace
@ MOD_VOLUME_DISPLACE_MAP_GLOBAL
@ MOD_VOLUME_DISPLACE_MAP_LOCAL
@ MOD_VOLUME_DISPLACE_MAP_OBJECT
Object is a sort of wrapper for general info.
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static bool depends_on_time(Scene *, ModifierData *)
static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
ModifierTypeInfo modifierType_VolumeDisplace
static bool depends_on_time(Scene *, ModifierData *md)
static void displace_volume(ModifierData *md, const ModifierEvalContext *ctx, Volume *volume)
static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
static void panel_draw(const bContext *C, Panel *panel)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
static void update_depsgraph(tGraphSliderOp *gso)
MatBase< float, 4, 4 > float4x4
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
float texture_mid_level[3]
float texture_sample_radius
struct Object * texture_map_object
const T * base_ptr() const
Volume * get_volume_for_write()
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)