WIP: Volume grid attribute support in geometry nodes #110044

Closed
Lukas Tönne wants to merge 130 commits from LukasTonne/blender:geometry-nodes-flip into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
40 changed files with 489 additions and 382 deletions
Showing only changes of commit 068c58b362 - Show all commits

View File

@ -167,11 +167,11 @@ class GeometryFieldInput : public fn::FieldInput {
ResourceScope &scope) const override;
virtual GVArray get_varray_for_context(const GeometryFieldContext &context,
const IndexMask &mask) const = 0;
virtual volume::GVGrid get_volume_grid_for_context(const fn::FieldContext &context,
const volume::GVGrid &mask,
ResourceScope &scope) const override;
virtual volume::GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const volume::GVGrid &mask) const = 0;
virtual GVGrid get_volume_grid_for_context(const fn::FieldContext &context,
const GVGrid &mask,
ResourceScope &scope) const override;
virtual GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const GVGrid &mask) const = 0;
virtual std::optional<eAttrDomain> preferred_domain(const GeometryComponent &component) const;
};
@ -245,8 +245,6 @@ class InstancesFieldInput : public fn::FieldInput {
class VolumeFieldInput : public fn::FieldInput {
public:
using GGrid = volume::GVGrid;
using fn::FieldInput::FieldInput;
GVArray get_varray_for_context(const fn::FieldContext & /*context*/,
const IndexMask & /*mask*/,
@ -254,11 +252,11 @@ class VolumeFieldInput : public fn::FieldInput {
{
return {};
}
virtual GGrid get_volume_grid_for_context(const fn::FieldContext &context,
const GGrid &mask,
ResourceScope &scope) const override;
virtual GGrid get_volume_grid_for_context(const VolumeGridVector &grids,
const GGrid &mask) const = 0;
virtual GVGrid get_volume_grid_for_context(const fn::FieldContext &context,
const GVGrid &mask,
ResourceScope &scope) const override;
virtual GVGrid get_volume_grid_for_context(const VolumeGridVector &grids,
const GVGrid &mask) const = 0;
};
class AttributeFieldInput : public GeometryFieldInput {
@ -320,7 +318,7 @@ class AttributeExistsFieldInput final : public bke::GeometryFieldInput {
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const final;
GGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const volume::GVGrid &mask) const final;
const GVGrid &mask) const final;
};
class IDAttributeFieldInput : public GeometryFieldInput {
@ -332,8 +330,8 @@ class IDAttributeFieldInput : public GeometryFieldInput {
GVArray get_varray_for_context(const GeometryFieldContext &context,
const IndexMask &mask) const override;
volume::GVGrid get_volume_grid_for_context(const GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const override
GVGrid get_volume_grid_for_context(const GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const override
{
return {};
}
@ -357,8 +355,8 @@ class NormalFieldInput : public GeometryFieldInput {
GVArray get_varray_for_context(const GeometryFieldContext &context,
const IndexMask &mask) const override;
volume::GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const volume::GVGrid &mask) const override;
GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const GVGrid &mask) const override;
std::string socket_inspection_name() const override;
uint64_t hash() const override;
@ -397,8 +395,8 @@ class AnonymousAttributeFieldInput : public GeometryFieldInput {
GVArray get_varray_for_context(const GeometryFieldContext &context,
const IndexMask &mask) const override;
volume::GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const volume::GVGrid &mask) const override;
GVGrid get_volume_grid_for_context(const GeometryFieldContext &context,
const GVGrid &mask) const override;
std::string socket_inspection_name() const override;
uint64_t hash() const override;

View File

@ -16,11 +16,15 @@
struct VolumeGrid;
VolumeGrid *BKE_volume_grid_add_vdb(Volume &volume,
blender::StringRef name,
blender::volume::GVMutableGrid vdb_grid);
/* Same as openvdb::GridBase::Ptr (cannot be forward-declared). */
using GridBasePtr = std::shared_ptr<openvdb::GridBase>;
using GridBaseConstPtr = std::shared_ptr<const openvdb::GridBase>;
bool BKE_volume_grid_bounds(blender::volume::GVGrid grid,
VolumeGrid &BKE_volume_grid_add_vdb(Volume &volume,
blender::StringRef name,
const GridBasePtr &vdb_grid);
bool BKE_volume_grid_bounds(const openvdb::GridBase &grid,
blender::float3 &r_min,
blender::float3 &r_max);
@ -29,15 +33,12 @@ bool BKE_volume_grid_bounds(blender::volume::GVGrid grid,
* This is useful for instances, where there is a separate transform on top of the original
* grid transform that must be applied for some operations that only take a grid argument.
*/
blender::volume::GVGrid BKE_volume_grid_shallow_transform(blender::volume::GVGrid grid,
const blender::float4x4 &transform);
GridBaseConstPtr BKE_volume_grid_shallow_transform(const openvdb::GridBase &grid,
const blender::float4x4 &transform);
blender::volume::GVGrid BKE_volume_grid_openvdb_for_metadata(const VolumeGrid *grid);
blender::volume::GVGrid BKE_volume_grid_openvdb_for_read(const Volume *volume,
const VolumeGrid *grid);
blender::volume::GVMutableGrid BKE_volume_grid_openvdb_for_write(const Volume *volume,
VolumeGrid *grid,
bool clear);
GridBasePtr BKE_volume_grid_openvdb_for_metadata(const VolumeGrid *grid);
GridBasePtr BKE_volume_grid_openvdb_for_read(const Volume *volume, const VolumeGrid *grid);
GridBasePtr BKE_volume_grid_openvdb_for_write(const Volume *volume, VolumeGrid *grid, bool clear);
void BKE_volume_grid_clear_tree(Volume &volume, VolumeGrid &volume_grid);
void BKE_volume_grid_clear_tree(openvdb::GridBase &grid);
@ -77,7 +78,8 @@ auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op)
return op.template operator()<openvdb::FloatGrid>();
}
blender::volume::GVMutableGrid BKE_volume_grid_create_with_changed_resolution(
const VolumeGridType grid_type, const openvdb::GridBase &old_grid, float resolution_factor);
GridBasePtr BKE_volume_grid_create_with_changed_resolution(const VolumeGridType grid_type,
const openvdb::GridBase &old_grid,
float resolution_factor);
#endif

View File

@ -27,7 +27,10 @@ GAttributeGridReader VolumeCustomAttributeGridProvider::try_get_grid_for_read(
{
const VolumeGridVector &grids = grid_access_.get_const_grids(owner);
const VolumeGrid *grid = grids.find_grid(attribute_id);
return {{grid ? grid->grid() : nullptr}, domain_, nullptr};
if (!grid) {
return {};
}
return {GVGrid::ForGrid(*grid->grid()), domain_, nullptr};
}
GAttributeGridWriter VolumeCustomAttributeGridProvider::try_get_grid_for_write(
@ -35,7 +38,10 @@ GAttributeGridWriter VolumeCustomAttributeGridProvider::try_get_grid_for_write(
{
VolumeGridVector &grids = grid_access_.get_grids(owner);
VolumeGrid *grid = grids.find_grid(attribute_id);
return {{grid ? grid->grid() : nullptr}, domain_, nullptr};
if (!grid) {
return {};
}
return {GVMutableGrid::ForGrid(*grid->grid()), domain_, nullptr};
}
bool VolumeCustomAttributeGridProvider::try_delete(void *owner,
@ -103,15 +109,9 @@ template<typename ToTreeType> struct ConvertGridOp<ToTreeType, openvdb::MaskTree
}
};
static openvdb::GridBase::Ptr add_generic_grid_copy(const CPPType &value_type,
const volume::GVGrid &data)
static openvdb::GridBase::Ptr add_generic_grid_copy(const CPPType &value_type, const GVGrid &data)
{
/* Template build sanitization: nested static type dispatch creates a lot of code, which can
* easily make builds run out of memory. Capturing a functor allows doing the 2nd type dispatch
* for the grid template separately, avoiding combinatorial explosion. */
std::function<openvdb::GridBase::Ptr(const openvdb::GridBase::ConstPtr &from_grid)> copy_fn =
nullptr;
openvdb::GridBase::Ptr result = nullptr;
volume::field_to_static_type(value_type, [&](auto tag) {
using ValueType = typename decltype(tag)::type;
using GridType = volume::grid_types::AttributeGrid<ValueType>;
@ -121,40 +121,31 @@ static openvdb::GridBase::Ptr add_generic_grid_copy(const CPPType &value_type,
const ValueType &background_value = *static_cast<const ValueType *>(
value_type.default_value());
copy_fn = [background_value](
const openvdb::GridBase::ConstPtr &from_grid) -> openvdb::GridBase::Ptr {
openvdb::GridBase::Ptr result = nullptr;
if (from_grid) {
volume::grid_to_static_type(from_grid, [&](auto &typed_data) {
using FromGridType = typename std::decay<decltype(typed_data)>::type;
using FromTreeType = typename FromGridType::TreeType;
using FromValueType = typename FromTreeType::ValueType;
ConvertGridOp<TreeType, FromTreeType, std::is_convertible_v<FromValueType, ValueType>>
convert;
result = convert(typed_data.tree());
});
}
else {
result = GridType::create(Converter::single_value_to_grid(background_value));
}
return result;
};
if (data) {
volume::grid_to_static_type(*data.get_internal_grid(), [&](auto &typed_data) {
using FromGridType = typename std::decay<decltype(typed_data)>::type;
using FromTreeType = typename FromGridType::TreeType;
using FromValueType = typename FromTreeType::ValueType;
ConvertGridOp<TreeType, FromTreeType, std::is_convertible_v<FromValueType, ValueType>>
convert;
result = convert(typed_data.tree());
});
}
else {
result = GridType::create(Converter::single_value_to_grid(background_value));
}
});
if (copy_fn) {
return copy_fn(data.grid_);
}
return nullptr;
return result;
}
static openvdb::GridBase::Ptr add_generic_grid_move(const CPPType & /*value_type*/,
const volume::GVMutableGrid &data)
const GVMutableGrid &data)
{
return data.grid_;
return openvdb::GridBase::Ptr(data.get_internal_grid());
}
static openvdb::GridBase::Ptr add_generic_grid_shared(const CPPType &value_type,
const volume::GVMutableGrid &data,
const GVMutableGrid &data,
const ImplicitSharingInfo *sharing_info)
{
/* XXX May eventually use this, for now just rely on shared_ptr. */
@ -167,9 +158,8 @@ static openvdb::GridBase::Ptr add_generic_grid_shared(const CPPType &value_type,
if (data) {
/* Data must be same grid type */
BLI_assert(data.grid_->isType<GridType>());
typename GridType::Ptr typed_data = openvdb::GridBase::grid<GridType>(data.grid_);
BLI_assert(typed_data != nullptr);
BLI_assert(data.get_internal_grid()->isType<GridType>());
GridType *typed_data = static_cast<GridType *>(data.get_internal_grid());
/* Create grid that shares the tree. */
result = std::make_shared<GridType>(typed_data->treePtr());
@ -202,25 +192,24 @@ static bool add_grid_from_attribute_init(const AttributeIDRef &attribute_id,
case AttributeInit::Type::Shared:
break;
case AttributeInit::Type::Grid: {
const volume::GVGrid &data =
static_cast<const blender::bke::AttributeInitGrid &>(initializer).grid;
const GVGrid &data = static_cast<const blender::bke::AttributeInitGrid &>(initializer).grid;
result = add_generic_grid_copy(value_type, data);
#ifdef DEBUG_GRID_ATTRIBUTES
std::cout << "Copied grid to attribute " << attribute_id << std::endl;
if (data.grid_) {
data.grid_->print(std::cout, 3);
if (data) {
data.get_internal_grid()->print(std::cout, 3);
}
#endif
break;
}
case AttributeInit::Type::MoveGrid: {
const volume::GVMutableGrid &data =
const GVMutableGrid &data =
static_cast<const blender::bke::AttributeInitMoveGrid &>(initializer).grid;
result = add_generic_grid_move(value_type, data);
#ifdef DEBUG_GRID_ATTRIBUTES
std::cout << "Moved grid to attribute " << attribute_id << std::endl;
if (data.grid_) {
data.grid_->print(std::cout, 3);
if (data) {
data.get_internal_grid()->print(std::cout, 3);
}
#endif
break;
@ -232,8 +221,8 @@ static bool add_grid_from_attribute_init(const AttributeIDRef &attribute_id,
value_type, init.grid, init.sharing_info);
#ifdef DEBUG_GRID_ATTRIBUTES
std::cout << "Shared grid to attribute " << attribute_id << std::endl;
if (init.grid.grid_) {
init.grid.grid_->print(std::cout, 3);
if (init.grid) {
init.grid.get_internal_grid()->print(std::cout, 3);
}
#endif
break;
@ -294,11 +283,8 @@ bool VolumeCustomAttributeGridProvider::foreach_attribute(
for (const VolumeGrid &grid : grids) {
const AttributeIDRef attribute_id{grid.name()};
const CPPType *type = volume::GVGrid{grid.grid()}.value_type();
if (type == nullptr) {
continue;
}
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type);
const CPPType &type = volume::grid_base_attribute_type(*grid.grid());
const eCustomDataType data_type = cpp_type_to_custom_data_type(type);
if (data_type == CD_NUMTYPES) {
continue;
}

View File

@ -582,7 +582,7 @@ static AttributeAccessorFunctions get_curves_accessor_functions()
};
fn.domain_grid_mask = [](const void * /*owner*/,
const eAttrDomain /*domain*/,
const int /*main_grid*/) -> volume::GVGrid { return {}; };
const int /*main_grid*/) -> GVGrid { return {}; };
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
return ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
};

View File

@ -220,7 +220,7 @@ static AttributeAccessorFunctions get_instances_accessor_functions()
};
fn.domain_grid_mask = [](const void * /*owner*/,
const eAttrDomain /*domain*/,
const int /*main_grid*/) -> volume::GVGrid { return {}; };
const int /*main_grid*/) -> GVGrid { return {}; };
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
return domain == ATTR_DOMAIN_INSTANCE;
};

View File

@ -1237,7 +1237,7 @@ static AttributeAccessorFunctions get_mesh_accessor_functions()
};
fn.domain_grid_mask = [](const void * /*owner*/,
const eAttrDomain /*domain*/,
const int /*main_grid*/) -> volume::GVGrid { return {}; };
const int /*main_grid*/) -> GVGrid { return {}; };
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
return ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
};

View File

@ -185,7 +185,7 @@ static AttributeAccessorFunctions get_pointcloud_accessor_functions()
};
fn.domain_grid_mask = [](const void * /*owner*/,
const eAttrDomain /*domain*/,
const int /*main_grid*/) -> volume::GVGrid { return {}; };
const int /*main_grid*/) -> GVGrid { return {}; };
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
return domain == ATTR_DOMAIN_POINT;
};

View File

@ -196,9 +196,9 @@ GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &conte
return {};
}
volume::GVGrid GeometryFieldInput::get_volume_grid_for_context(const fn::FieldContext &context,
const volume::GVGrid &mask,
ResourceScope & /*scope*/) const
GVGrid GeometryFieldInput::get_volume_grid_for_context(const fn::FieldContext &context,
const GVGrid &mask,
ResourceScope & /*scope*/) const
{
if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>(
&context))
@ -304,9 +304,9 @@ GVArray InstancesFieldInput::get_varray_for_context(const fn::FieldContext &cont
return {};
}
volume::GVGrid VolumeFieldInput::get_volume_grid_for_context(const fn::FieldContext &context,
const volume::GVGrid &mask,
ResourceScope & /*scope*/) const
GVGrid VolumeFieldInput::get_volume_grid_for_context(const fn::FieldContext &context,
const GVGrid &mask,
ResourceScope & /*scope*/) const
{
if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>(
&context))
@ -333,8 +333,8 @@ GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &
return {};
}
volume::GVGrid AttributeFieldInput::get_volume_grid_for_context(
const GeometryFieldContext &context, const GGrid & /*mask*/) const
GVGrid AttributeFieldInput::get_volume_grid_for_context(const GeometryFieldContext &context,
const GGrid & /*mask*/) const
{
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
if (auto attributes = context.attributes()) {
@ -351,11 +351,11 @@ GVArray AttributeExistsFieldInput::get_varray_for_context(const bke::GeometryFie
return VArray<bool>::ForSingle(exists, domain_size);
}
volume::GVGrid AttributeExistsFieldInput::get_volume_grid_for_context(
const GeometryFieldContext &context, const volume::GVGrid & /*mask*/) const
GVGrid AttributeExistsFieldInput::get_volume_grid_for_context(const GeometryFieldContext &context,
const GVGrid & /*mask*/) const
{
const bool exists = context.attributes()->contains(name_);
return volume::VMutableGrid<bool>::create(exists);
return VGrid<bool>::ForSingle(exists);
}
std::string AttributeFieldInput::socket_inspection_name() const
@ -440,8 +440,8 @@ GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryField
return *context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
}
volume::GVGrid AnonymousAttributeFieldInput::get_volume_grid_for_context(
const GeometryFieldContext &context, const volume::GVGrid & /*mask*/) const
GVGrid AnonymousAttributeFieldInput::get_volume_grid_for_context(
const GeometryFieldContext &context, const GVGrid & /*mask*/) const
{
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
return *context.attributes()->lookup_grid(*anonymous_id_, context.domain(), data_type);
@ -501,8 +501,8 @@ GVArray NormalFieldInput::get_varray_for_context(const GeometryFieldContext &con
return {};
}
volume::GVGrid NormalFieldInput::get_volume_grid_for_context(
const GeometryFieldContext & /*context*/, const volume::GVGrid & /*mask*/) const
GVGrid NormalFieldInput::get_volume_grid_for_context(const GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const
{
return {};
}
@ -632,16 +632,18 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
const auto &volume_component = static_cast<const bke::VolumeComponent &>(component);
main_grid = volume_component.get()->active_grid;
}
const volume::GVGrid domain_mask = {attributes.domain_grid_mask(domain, main_grid)};
const GVGrid domain_mask = {attributes.domain_grid_mask(domain, main_grid)};
const bke::GeometryFieldContext field_context{component, domain};
fn::VolumeFieldEvaluator evaluator{field_context, domain_mask};
evaluator.add(validator.validate_field_if_necessary(field));
evaluator.set_selection(selection);
evaluator.evaluate();
const volume::GVGrid selection = evaluator.get_evaluated_selection_as_mask();
const GVGrid selection = evaluator.get_evaluated_selection_as_mask();
dst_attribute.grid.try_copy_masked(evaluator.get_evaluated(0), selection);
const openvdb::GridBase *src_grid = evaluator.get_evaluated(0).get_internal_grid();
openvdb::GridBase *dst_grid = dst_attribute.grid.get_internal_grid();
dst_grid->setTree(src_grid->baseTree().copy());
dst_attribute.finish();
return true;
@ -697,16 +699,18 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
const auto &volume_component = static_cast<const bke::VolumeComponent &>(component);
main_grid = volume_component.get()->active_grid;
}
const volume::GVGrid domain_mask = {attributes.domain_grid_mask(domain, main_grid)};
const GVGrid domain_mask = {attributes.domain_grid_mask(domain, main_grid)};
fn::VolumeFieldEvaluator evaluator{field_context, domain_mask};
volume::GVMutableGrid grid = volume::GVMutableGrid::create(type);
openvdb::GridBase *buffer = volume::make_grid_for_attribute_type(type);
GVMutableGrid grid = GVMutableGrid::ForGrid(*buffer);
evaluator.add_with_destination(validator.validate_field_if_necessary(field), grid);
evaluator.set_selection(selection);
evaluator.evaluate();
if (attribute_matches) {
if (GAttributeGridWriter attribute = attributes.lookup_grid_for_write(attribute_id)) {
attribute.grid = grid;
attribute.grid.get_internal_grid()->setTree(buffer->baseTreePtr());
MEM_freeN(buffer);
attribute.finish();
return true;
}
@ -717,6 +721,8 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
return true;
}
MEM_freeN(buffer);
/* If the name corresponds to a builtin attribute, removing the attribute might fail if
* it's required, and adding the attribute might fail if the domain or type is incorrect. */
return false;

View File

@ -519,7 +519,7 @@ bool BKE_volume_save(const Volume *volume,
openvdb::GridCPtrVec vdb_grids;
for (VolumeGrid &grid : grids) {
vdb_grids.push_back(BKE_volume_grid_openvdb_for_read(volume, &grid).grid_);
vdb_grids.push_back(BKE_volume_grid_openvdb_for_read(volume, &grid));
}
try {
@ -553,10 +553,10 @@ bool BKE_volume_min_max(const Volume *volume, float3 &r_min, float3 &r_max)
if (BKE_volume_load(const_cast<Volume *>(volume), G.main)) {
for (const int i : IndexRange(BKE_volume_num_grids(volume))) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, i);
blender::volume::GVGrid grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
float3 grid_min;
float3 grid_max;
if (BKE_volume_grid_bounds(grid, grid_min, grid_max)) {
if (BKE_volume_grid_bounds(*grid, grid_min, grid_max)) {
DO_MIN(grid_min, r_min);
DO_MAX(grid_max, r_max);
have_minmax = true;
@ -976,9 +976,8 @@ void BKE_volume_grid_clear_tree(openvdb::GridBase &grid)
}
void BKE_volume_grid_clear_tree(Volume &volume, VolumeGrid &volume_grid)
{
blender::volume::GVMutableGrid grid = BKE_volume_grid_openvdb_for_write(
&volume, &volume_grid, false);
BKE_volume_grid_clear_tree(*grid.grid_);
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(&volume, &volume_grid, false);
BKE_volume_grid_clear_tree(*grid);
}
VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid)
@ -1084,8 +1083,7 @@ void BKE_volume_grid_transform_matrix_set(const Volume *volume,
mat_openvdb(col, row) = mat[col][row];
}
}
openvdb::GridBase::Ptr grid =
BKE_volume_grid_openvdb_for_write(volume, volume_grid, false).grid_;
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false);
grid->setTransform(std::make_shared<openvdb::math::Transform>(
std::make_shared<openvdb::math::AffineMap>(mat_openvdb)));
#else
@ -1152,17 +1150,17 @@ VolumeGrid *BKE_volume_grid_add(Volume *volume, const char *name, VolumeGridType
}
#ifdef WITH_OPENVDB
VolumeGrid *BKE_volume_grid_add_vdb(Volume &volume,
VolumeGrid &BKE_volume_grid_add_vdb(Volume &volume,
const StringRef name,
blender::volume::GVMutableGrid vdb_grid)
const GridBasePtr &vdb_grid)
{
VolumeGridVector &grids = *volume.runtime.grids;
BLI_assert(BKE_volume_grid_find_for_read(&volume, name.data()) == nullptr);
BLI_assert(BKE_volume_grid_type_openvdb(*vdb_grid.grid_) != VOLUME_GRID_UNKNOWN);
BLI_assert(BKE_volume_grid_type_openvdb(*vdb_grid) != VOLUME_GRID_UNKNOWN);
vdb_grid.grid_->setName(name);
grids.emplace_back(vdb_grid.grid_);
return &grids.back();
vdb_grid->setName(name);
grids.emplace_back(vdb_grid);
return grids.back();
}
#endif
@ -1223,15 +1221,15 @@ float BKE_volume_simplify_factor(const Depsgraph *depsgraph)
#ifdef WITH_OPENVDB
bool BKE_volume_grid_bounds(blender::volume::GVGrid grid, float3 &r_min, float3 &r_max)
bool BKE_volume_grid_bounds(const openvdb::GridBase &grid, float3 &r_min, float3 &r_max)
{
/* TODO: we can get this from grid metadata in some cases? */
openvdb::CoordBBox coordbbox;
if (!grid.grid_->baseTree().evalLeafBoundingBox(coordbbox)) {
if (!grid.baseTree().evalLeafBoundingBox(coordbbox)) {
return false;
}
openvdb::BBoxd bbox = grid.grid_->transform().indexToWorld(coordbbox);
openvdb::BBoxd bbox = grid.transform().indexToWorld(coordbbox);
r_min = float3(float(bbox.min().x()), float(bbox.min().y()), float(bbox.min().z()));
r_max = float3(float(bbox.max().x()), float(bbox.max().y()), float(bbox.max().z()));
@ -1239,31 +1237,31 @@ bool BKE_volume_grid_bounds(blender::volume::GVGrid grid, float3 &r_min, float3
return true;
}
blender::volume::GVGrid BKE_volume_grid_shallow_transform(blender::volume::GVGrid grid,
const blender::float4x4 &transform)
openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase &grid,
const blender::float4x4 &transform)
{
openvdb::math::Transform::Ptr grid_transform = grid.grid_->transform().copy();
openvdb::math::Transform::Ptr grid_transform = grid.transform().copy();
grid_transform->postMult(openvdb::Mat4d((float *)transform.ptr()));
/* Create a transformed grid. The underlying tree is shared. */
return blender::volume::GVGrid{grid.grid_->copyGridReplacingTransform(grid_transform)};
return grid.copyGridReplacingTransform(grid_transform);
}
blender::volume::GVGrid BKE_volume_grid_openvdb_for_metadata(const VolumeGrid *grid)
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_metadata(const VolumeGrid *grid)
{
return blender::volume::GVGrid{grid->grid()};
return grid->grid();
}
blender::volume::GVGrid BKE_volume_grid_openvdb_for_read(const Volume *volume,
const VolumeGrid *grid)
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_read(const Volume *volume,
const VolumeGrid *grid)
{
BKE_volume_grid_load(volume, grid);
return blender::volume::GVGrid{grid->grid()};
return grid->grid();
}
blender::volume::GVMutableGrid BKE_volume_grid_openvdb_for_write(const Volume *volume,
VolumeGrid *grid,
const bool clear)
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const Volume *volume,
VolumeGrid *grid,
const bool clear)
{
const char *volume_name = volume->id.name + 2;
if (clear) {
@ -1274,7 +1272,7 @@ blender::volume::GVMutableGrid BKE_volume_grid_openvdb_for_write(const Volume *v
grid->duplicate_reference(volume_name, grids.filepath);
}
return blender::volume::GVMutableGrid{grid->grid()};
return grid->grid();
}
/* Changing the resolution of a grid. */
@ -1305,14 +1303,14 @@ struct CreateGridWithChangedResolutionOp {
const openvdb::GridBase &grid;
const float resolution_factor;
template<typename GridType> blender::volume::GVMutableGrid operator()()
template<typename GridType> openvdb::GridBase::Ptr operator()()
{
return {create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
resolution_factor)};
return create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
resolution_factor);
}
};
blender::volume::GVMutableGrid BKE_volume_grid_create_with_changed_resolution(
openvdb::GridBase::Ptr BKE_volume_grid_create_with_changed_resolution(
const VolumeGridType grid_type,
const openvdb::GridBase &old_grid,
const float resolution_factor)

View File

@ -53,8 +53,7 @@ openvdb::GridBase::Ptr VolumeFileCache::Entry::simplified_grid(const int simplif
simple_grid = simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
const float resolution_factor = 1.0f / (1 << simplify_level);
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid);
return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor)
.grid_;
return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor);
});
});
return simple_grid;
@ -378,7 +377,7 @@ static AttributeAccessorFunctions get_volume_accessor_functions()
return grids.domain_size(domain);
};
fn.domain_grid_mask =
[](const void *owner, const eAttrDomain /*domain*/, const int main_grid) -> volume::GVGrid {
[](const void *owner, const eAttrDomain /*domain*/, const int main_grid) -> GVGrid {
if (owner == nullptr || main_grid < 0) {
return {nullptr};
}
@ -389,11 +388,11 @@ static AttributeAccessorFunctions get_volume_accessor_functions()
for (const VolumeGrid &grid : grids) {
int index = main_grid;
if (index-- == 0) {
return {grid.grid()};
return GVGrid::ForGrid(*grid.grid());
}
}
/* Default if main_grid is invalid. */
return {grids.front().grid()};
return GVGrid::ForGrid(*grids.front().grid());
};
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
return ELEM(domain, ATTR_DOMAIN_VOXEL);

View File

@ -97,7 +97,7 @@ bool BKE_volume_grid_dense_floats(const Volume *volume,
{
#ifdef WITH_OPENVDB
const VolumeGridType grid_type = BKE_volume_grid_type(volume_grid);
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
const openvdb::CoordBBox bbox = grid->evalActiveVoxelBoundingBox();
if (bbox.empty()) {
@ -331,7 +331,7 @@ void BKE_volume_grid_wireframe(const Volume *volume,
}
#ifdef WITH_OPENVDB
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
if (volume->display.wireframe_type == VOLUME_WIREFRAME_BOUNDS) {
/* Bounding box. */
@ -403,7 +403,7 @@ void BKE_volume_grid_selection_surface(const Volume *volume,
void *cb_userdata)
{
#ifdef WITH_OPENVDB
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
blender::Vector<openvdb::CoordBBox> boxes = get_bounding_boxes(
BKE_volume_grid_type(volume_grid), *grid, true);

View File

@ -39,7 +39,10 @@ class GVGridImpl {
// virtual void get(int64_t index, void *r_value) const;
// virtual void get_to_uninitialized(int64_t index, void *r_value) const = 0;
virtual CommonVGridInfo common_info() const;
virtual CommonVGridInfo common_info() const
{
return {};
}
// virtual void materialize(const IndexMask &mask, void *dst) const;
// virtual void materialize_to_uninitialized(const IndexMask &mask, void *dst) const;
@ -47,7 +50,10 @@ class GVGridImpl {
// virtual void materialize_compressed(const IndexMask &mask, void *dst) const;
// virtual void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const;
virtual bool try_assign_VGrid(void *vgrid) const;
virtual bool try_assign_VGrid(void * /*vgrid*/) const
{
return false;
}
};
/* A generic version of #VMutableGridImpl. */
@ -61,7 +67,10 @@ class GVMutableGridImpl : public GVGridImpl {
// virtual void set_all(const void *src);
virtual bool try_assign_VMutableGrid(void *vgrid) const;
virtual bool try_assign_VMutableGrid(void * /*vgrid*/) const
{
return false;
}
};
/** \} */
@ -121,7 +130,10 @@ class GVGridCommon {
operator bool() const;
template<typename T> bool try_assign_VGrid(VGrid<T> &vgrid) const;
bool may_have_ownership() const;
bool may_have_ownership() const
{
return impl_->common_info().may_have_ownership;
}
// void materialize(void *dst) const;
// void materialize(const IndexMask &mask, void *dst) const;
@ -188,7 +200,9 @@ class GVGrid : public GVGridCommon {
GVGrid(const GVGridImpl *impl);
GVGrid(std::shared_ptr<const GVGridImpl> impl);
#ifdef WITH_OPENVDB
GVGrid(vgrid_tag::grid /* tag */, const GridType &grid);
#endif
GVGrid(vgrid_tag::single_ref /* tag */, const CPPType &type, const void *value);
GVGrid(vgrid_tag::single /* tag */, const CPPType &type, const void *value);
@ -200,8 +214,10 @@ class GVGrid : public GVGridCommon {
static GVGrid ForSingle(const CPPType &type, const void *value);
static GVGrid ForSingleRef(const CPPType &type, const void *value);
static GVGrid ForSingleDefault(const CPPType &type);
#ifdef WITH_OPENVDB
static GVGrid ForGrid(const GridType &grid);
static GVGrid ForEmpty(const CPPType &type);
#endif
GVGrid &operator=(const GVGrid &other);
GVGrid &operator=(GVGrid &&other) noexcept;
@ -231,7 +247,9 @@ class GVMutableGrid : public GVGridCommon {
template<typename ImplT, typename... Args> static GVMutableGrid For(Args &&...args);
#ifdef WITH_OPENVDB
static GVMutableGrid ForGrid(GridType &grid);
#endif
operator GVGrid() const &;
operator GVGrid() &&noexcept;
@ -239,7 +257,9 @@ class GVMutableGrid : public GVGridCommon {
GVMutableGrid &operator=(const GVMutableGrid &other);
GVMutableGrid &operator=(GVMutableGrid &&other) noexcept;
#ifdef WITH_OPENVDB
GridType *get_internal_grid() const;
#endif
template<typename T> bool try_assign_VMutableGrid(VMutableGrid<T> &vgrid) const;
@ -378,26 +398,25 @@ template<typename T> class VMutableGridImpl_For_GVMutableGrid : public VMutableG
/** \name #GVGridImpl_For_GSpan.
* \{ */
#ifdef WITH_OPENVDB
class GVGridImpl_For_Grid : public GVMutableGridImpl {
public:
#ifdef WITH_OPENVDB
using GridType = openvdb::GridBase;
#endif
protected:
const GridType *grid_ = nullptr;
public:
GVGridImpl_For_Grid(const GridType &grid)
: GVMutableGridImpl(volume::grid_attribute_type(grid)), grid_(&grid)
{
}
GVGridImpl_For_Grid(const GridType &grid);
protected:
GVGridImpl_For_Grid(const CPPType &type) : GVMutableGridImpl(type) {}
public:
CommonVGridInfo common_info() const override;
CommonVGridInfo common_info() const override
{
return CommonVGridInfo{CommonVGridInfo::Type::Grid, true, grid_};
}
};
class GVGridImpl_For_Grid_final final : public GVGridImpl_For_Grid {
@ -405,10 +424,14 @@ class GVGridImpl_For_Grid_final final : public GVGridImpl_For_Grid {
using GVGridImpl_For_Grid::GVGridImpl_For_Grid;
private:
CommonVGridInfo common_info() const override;
CommonVGridInfo common_info() const override
{
return CommonVGridInfo(CommonVGridInfo::Type::Grid, false, grid_);
}
};
template<> inline constexpr bool is_trivial_extended_v<GVGridImpl_For_Grid> = true;
#endif /* WITH_OPENVDB */
/** \} */
@ -519,6 +542,7 @@ inline CommonVGridInfo GVGridCommon::common_info() const
/** \name Inline methods for #GVGrid.
* \{ */
#ifdef WITH_OPENVDB
inline GVGrid::GVGrid(vgrid_tag::grid /* tag */, const GridType &grid)
{
/* Use const-cast because the underlying virtual grid implementation is shared between const
@ -526,6 +550,7 @@ inline GVGrid::GVGrid(vgrid_tag::grid /* tag */, const GridType &grid)
GridType &mutable_grid = const_cast<GridType &>(grid);
this->emplace<GVGridImpl_For_Grid_final>(mutable_grid);
}
#endif
inline GVGrid::GVGrid(vgrid_tag::single_ref /* tag */, const CPPType &type, const void *value)
{
@ -571,13 +596,15 @@ template<typename T> inline GVGrid::GVGrid(const VGrid<T> &vgrid)
}
const CommonVGridInfo info = vgrid.common_info();
if (info.type == CommonVGridInfo::Type::Single) {
*this = GVGrid::ForSingle(CPPType::get<T>(), vgrid.size(), info.data);
*this = GVGrid::ForSingle(CPPType::get<T>(), info.data);
return;
}
/* Need to check for ownership, because otherwise the referenced data can be destructed when
* #this is destructed. */
if (info.type == CommonVGridInfo::Type::Grid && !info.may_have_ownership) {
#ifdef WITH_OPENVDB
*this = GVGrid::ForGrid(*static_cast<const GridType *>(info.data));
#endif
return;
}
if (vgrid.try_assign_GVGrid(*this)) {
@ -588,8 +615,6 @@ template<typename T> inline GVGrid::GVGrid(const VGrid<T> &vgrid)
template<typename T> inline VGrid<T> GVGrid::typed() const
{
using GridType = typename VGrid<T>::GridType;
if (!*this) {
return {};
}
@ -601,7 +626,12 @@ template<typename T> inline VGrid<T> GVGrid::typed() const
/* Need to check for ownership, because otherwise the referenced data can be destructed when
* #this is destructed. */
if (info.type == CommonVGridInfo::Type::Grid && !info.may_have_ownership) {
#ifdef WITH_OPENVDB
using GridType = typename VGrid<T>::GridType;
return VGrid<T>::ForGrid(static_cast<const GridType *>(info.data));
#else
return {};
#endif
}
VGrid<T> vgrid;
if (this->try_assign_VGrid(vgrid)) {
@ -631,7 +661,9 @@ template<typename T> inline GVMutableGrid::GVMutableGrid(const VMutableGrid<T> &
}
const CommonVGridInfo info = vgrid.common_info();
if (info.type == CommonVGridInfo::Type::Grid && !info.may_have_ownership) {
#ifdef WITH_OPENVDB
*this = GVMutableGrid::ForGrid(*static_cast<GridType *>(const_cast<void *>(info.data)));
#endif
return;
}
if (vgrid.try_assign_GVMutableGrid(*this)) {
@ -648,7 +680,11 @@ template<typename T> inline VMutableGrid<T> GVMutableGrid::typed() const
BLI_assert(this->type().is<T>());
const CommonVGridInfo info = this->common_info();
if (info.type == CommonVGridInfo::Type::Grid && !info.may_have_ownership) {
#ifdef WITH_OPENVDB
return VMutableGrid<T>::ForGrid(const_cast<GridType *>(static_cast<const T *>(info.data)));
#else
return {};
#endif
}
VMutableGrid<T> vgrid;
if (this->try_assign_VMutableGrid(vgrid)) {

View File

@ -153,17 +153,17 @@ template<typename T> class VMutableGridImpl : public VGridImpl<T> {
}
};
#ifdef WITH_OPENVDB
/**
* A virtual grid implementation that wraps a OpenVDB grid. This implementation is used by
* mutable and immutable grids to avoid code duplication.
*/
template<typename T> class VGridImpl_For_Grid : public VMutableGridImpl<T> {
protected:
#ifdef WITH_OPENVDB
using GridType = volume::grid_types::AttributeGrid<T>;
GridType *grid_ = nullptr;
#endif
public:
VGridImpl_For_Grid(GridType &grid) : grid_(&grid) {}
@ -182,9 +182,7 @@ template<typename T> class VGridImpl_For_Grid : public VMutableGridImpl<T> {
template<typename T> class VGridImpl_For_Grid_final final : public VGridImpl_For_Grid<T> {
public:
using VGridImpl_For_Grid<T>::VGridImpl_For_Grid;
#ifdef WITH_OPENVDB
using GridType = typename VGridImpl_For_Grid<T>::GridType;
#endif
VGridImpl_For_Grid_final(GridType &grid)
/* Cast const away, because the implementation for const and non const spans is shared. */
@ -198,6 +196,7 @@ template<typename T> class VGridImpl_For_Grid_final final : public VGridImpl_For
return CommonVGridInfo(CommonVGridInfo::Type::Grid, false, this->grid_);
}
};
#endif
/**
* A virtual array implementation that returns the same value for every location. This class is
@ -431,11 +430,11 @@ template<typename T> class VGridCommon {
* Returns the internally used grid of the virtual grid. This invokes undefined behavior if the
* virtual grid is not stored as a grid internally.
*/
GridType *get_internal_grid() const
const GridType *get_internal_grid() const
{
BLI_assert(this->is_span());
BLI_assert(this->is_grid());
const CommonVGridInfo info = impl_->common_info();
return static_cast<GridType *>(info.data);
return static_cast<const GridType *>(info.data);
}
#endif
@ -492,12 +491,9 @@ template<typename T> class VMutableGrid;
* construct the virtual grid first and then move it into the vector.
*/
namespace vgrid_tag {
struct grid {
};
struct single_ref {
};
struct single {
};
struct grid {};
struct single_ref {};
struct single {};
} // namespace vgrid_tag
/**
@ -527,10 +523,12 @@ template<typename T> class VGrid : public VGridCommon<T> {
VGrid(std::shared_ptr<const VGridImpl<T>> impl) : VGridCommon<T>(std::move(impl)) {}
#ifdef WITH_OPENVDB
VGrid(vgrid_tag::grid /* tag */, const GridType &grid)
{
this->template emplace<VGridImpl_For_Grid_final<T>>(const_cast<GridType &>(grid));
}
#endif
VGrid(vgrid_tag::single /* tag */, T value)
{
@ -556,6 +554,7 @@ template<typename T> class VGrid : public VGridCommon<T> {
return VGrid(vgrid_tag::single{}, std::move(value));
}
#ifdef WITH_OPENVDB
/**
* Construct a new virtual array for an existing span. This does not take ownership of the
* underlying memory.
@ -564,6 +563,7 @@ template<typename T> class VGrid : public VGridCommon<T> {
{
return VGrid(vgrid_tag::grid{}, grid);
}
#endif
/**
* Construct a new virtual that will invoke the provided function whenever an element is
@ -623,6 +623,7 @@ template<typename T> class VMutableGrid : public VGridCommon<T> {
return VGrid;
}
#ifdef WITH_OPENVDB
/**
* Construct a new virtual array for an existing span. This does not take ownership of the span.
*/
@ -630,6 +631,7 @@ template<typename T> class VMutableGrid : public VGridCommon<T> {
{
return VMutableGrid::For<VGridImpl_For_Grid_final<T>>(grid);
}
#endif
/** Convert to a #VGrid by copying. */
operator VGrid<T>() const &
@ -659,16 +661,18 @@ template<typename T> class VMutableGrid : public VGridCommon<T> {
return *this;
}
#ifdef WITH_OPENVDB
/**
* Get access to the internal grid. This invokes undefined behavior if the #is_grid returned
* false.
*/
GridType &get_internal_grid() const
{
BLI_assert(this->is_span());
BLI_assert(this->is_grid());
const CommonVGridInfo info = this->get_impl()->common_info();
return *const_cast<GridType *>(static_cast<const GridType *>(info.data));
}
#endif
/** See #GVMutableGridImpl::try_assign_GVMutableGrid. */
bool try_assign_GVMutableGrid(GVMutableGrid &vgrid) const

View File

@ -96,6 +96,10 @@ using VectorGrid = Vec3fGrid;
} // namespace openvdb
#endif
namespace blender {
class ResourceScope;
}
namespace blender::volume {
#ifdef WITH_OPENVDB
@ -199,7 +203,8 @@ struct Converter<openvdb::Vec3IGrid>
/* Specialization for MaskGrid: Leaf buffers directly expose the activation state bit fields. */
template<> struct Converter<openvdb::MaskGrid> {
using GridValueType = openvdb::ValueMask;
using LeafBufferValueType = unsigned long int;
// using LeafBufferValueType = unsigned long int;
using LeafBufferValueType = uint64_t;
using AttributeValueType = bool;
static GridValueType single_value_to_grid(const AttributeValueType & /*value*/)
@ -223,7 +228,8 @@ template<> struct Converter<openvdb::MaskGrid> {
/* Specialization for BoolGrid: Leaf buffers directly expose the activation state bit fields. */
template<> struct Converter<openvdb::BoolGrid> {
using GridValueType = bool;
using LeafBufferValueType = unsigned long int;
// using LeafBufferValueType = unsigned long int;
using LeafBufferValueType = uint64_t;
using AttributeValueType = bool;
static GridValueType single_value_to_grid(const AttributeValueType &value)
@ -277,10 +283,7 @@ using SupportedGridTypes = openvdb::TypeList<openvdb::BoolGrid,
} // namespace grid_types
const CPPType &grid_attribute_type(const openvdb::GridBase &grid);
template<typename GridType> const CPPType &grid_attribute_type(const GridType &grid);
openvdb::GridBase &make_grid_for_attribute_type(ResourceScope &scope, const CPPType &type);
openvdb::GridBase *make_grid_for_attribute_type(const CPPType &type);
#endif

View File

@ -16,6 +16,7 @@
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
# include <openvdb/tree/Tree.h>
#endif
/**
@ -66,14 +67,6 @@ template<typename Func> void grid_to_static_type(const openvdb::GridBase &grid,
grid.apply<grid_types::SupportedGridTypes>(func);
}
const CPPType &grid_attribute_type(const openvdb::GridBase &grid)
{
const CPPType *type = &CPPType::get<float>();
volume::grid_to_static_type(grid,
[&](auto &typed_grid) { type = &grid_attribute_type(typed_grid); });
return *type;
}
template<typename GridType> const CPPType &grid_attribute_type(const GridType & /*grid*/)
{
using Converter = grid_types::Converter<GridType>;
@ -82,6 +75,8 @@ template<typename GridType> const CPPType &grid_attribute_type(const GridType &
return CPPType::get<AttributeValueType>();
}
const CPPType &grid_base_attribute_type(const openvdb::GridBase &grid);
#else
#endif

View File

@ -49,16 +49,6 @@ namespace blender {
// this->get_to_uninitialized(index, r_value);
// }
CommonVGridInfo GVGridImpl::common_info() const
{
return {};
}
bool GVGridImpl::try_assign_VGrid(void * /*vgrid*/) const
{
return false;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -105,20 +95,15 @@ bool GVGridImpl::try_assign_VGrid(void * /*vgrid*/) const
// }
// }
bool GVMutableGridImpl::try_assign_VMutableGrid(void * /*vgrid*/) const
{
return false;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVGridImpl_For_GSpan
/** \name #GVGridImpl_For_Grid
* \{ */
CommonVGridInfo GVGridImpl_For_Grid::common_info() const
GVGridImpl_For_Grid::GVGridImpl_For_Grid(const GridType &grid)
: GVMutableGridImpl(volume::grid_base_attribute_type(grid)), grid_(&grid)
{
return CommonVGridInfo{CommonVGridInfo::Type::Grid, true, grid_};
}
/** \} */
@ -352,6 +337,7 @@ GVGrid GVGrid::ForSingleDefault(const CPPType &type)
return GVGrid::ForSingleRef(type, type.default_value());
}
#ifdef WITH_OPENVDB
GVGrid GVGrid::ForGrid(const GridType &grid)
{
return GVGrid(vgrid_tag::grid{}, grid);
@ -372,6 +358,7 @@ GVGrid GVGrid::ForEmpty(const CPPType &type)
return GVGrid::ForGrid(*grid);
}
#endif
GVGrid &GVGrid::operator=(const GVGrid &other)
{
@ -401,10 +388,12 @@ GVMutableGrid::GVMutableGrid(std::shared_ptr<GVMutableGridImpl> impl)
{
}
#ifdef WITH_OPENVDB
GVMutableGrid GVMutableGrid::ForGrid(GridType &grid)
{
return GVMutableGrid::For<GVGridImpl_For_Grid_final>(grid);
}
#endif
GVMutableGrid::operator GVGrid() const &
{
@ -442,20 +431,17 @@ GVMutableGridImpl *GVMutableGrid::get_implementation() const
// this->get_impl()->set_all(src);
// }
#ifdef WITH_OPENVDB
GVMutableGrid::GridType *GVMutableGrid::get_internal_grid() const
{
BLI_assert(this->is_grid());
const CommonVGridInfo info = impl_->common_info();
return static_cast<GridType *>(const_cast<void *>(info.data));
}
#endif
/** \} */
CommonVGridInfo GVGridImpl_For_Grid_final::common_info() const
{
return CommonVGridInfo(CommonVGridInfo::Type::Grid, false, grid_);
}
CommonVGridInfo GVGridImpl_For_SingleValueRef_final::common_info() const
{
return CommonVGridInfo(CommonVGridInfo::Type::Single, false, value_);

View File

@ -8,6 +8,7 @@
#include "BLI_cpp_type.hh"
#include "BLI_math_base.hh"
#include "BLI_resource_scope.hh"
#include "BLI_volume_openvdb.hh"
#ifdef WITH_OPENVDB
@ -18,6 +19,21 @@ namespace blender::volume {
#ifdef WITH_OPENVDB
openvdb::GridBase &make_grid_for_attribute_type(ResourceScope &scope, const CPPType &type)
{
openvdb::GridBase *result = nullptr;
volume::field_to_static_type(type, [&](auto tag) {
using ValueType = typename decltype(tag)::type;
using GridType = volume::grid_types::AttributeGrid<ValueType>;
using Converter = volume::grid_types::Converter<GridType>;
const ValueType &background_value = *static_cast<const ValueType *>(type.default_value());
result = &scope.construct<GridType>(Converter::single_value_to_grid(background_value));
});
BLI_assert(result != nullptr);
return *result;
}
openvdb::GridBase *make_grid_for_attribute_type(const CPPType &type)
{
openvdb::GridBase *result = nullptr;
@ -27,12 +43,20 @@ openvdb::GridBase *make_grid_for_attribute_type(const CPPType &type)
using Converter = volume::grid_types::Converter<GridType>;
const ValueType &background_value = *static_cast<const ValueType *>(type.default_value());
result = new GridType(Converter::single_value_to_grid(background_value));
result = MEM_new<GridType>(__func__, Converter::single_value_to_grid(background_value));
});
BLI_assert(result != nullptr);
return result;
}
const CPPType &grid_base_attribute_type(const openvdb::GridBase &grid)
{
const CPPType *type = &CPPType::get<float>();
volume::grid_to_static_type(grid,
[&](auto &typed_grid) { type = &grid_attribute_type(typed_grid); });
return *type;
}
// int64_t GVGrid::voxel_count() const
//{
// return grid_ ? grid_->activeVoxelCount() : 0;

View File

@ -179,8 +179,7 @@ class GFieldRef : public GFieldBase<const FieldNode *> {
namespace detail {
/* Utility class to make #is_field_v work. */
struct TypedFieldBase {
};
struct TypedFieldBase {};
} // namespace detail
/**
@ -499,7 +498,7 @@ class VolumeFieldEvaluator : NonMovable, NonCopyable {
ResourceScope scope_;
const FieldContext &context_;
const openvdb::MaskGrid &domain_mask_;
GVGrid domain_mask_;
Vector<GField> fields_to_evaluate_;
Vector<GVMutableGrid> dst_grids_;
Vector<GVGrid> evaluated_grids_;
@ -511,15 +510,8 @@ class VolumeFieldEvaluator : NonMovable, NonCopyable {
public:
/** Takes #mask by pointer because the mask has to live longer than the evaluator. */
VolumeFieldEvaluator(const FieldContext &context, const openvdb::MaskGrid &domain_mask)
: context_(context), domain_mask_(domain_mask)
{
}
VolumeFieldEvaluator(const FieldContext &context)
: context_(context), domain_mask_(scope_.construct<openvdb::MaskGrid>())
{
}
VolumeFieldEvaluator(const FieldContext &context, const GVGrid &domain_mask);
VolumeFieldEvaluator(const FieldContext &context);
~VolumeFieldEvaluator()
{
@ -544,10 +536,10 @@ class VolumeFieldEvaluator : NonMovable, NonCopyable {
* \param field: Field to add to the evaluator.
* \param dst: Mutable grid that the evaluated result for this field is written into.
*/
int add_with_destination(GField field, GVMutableGrid &dst);
int add_with_destination(GField field, const GVMutableGrid &dst);
/** Same as #add_with_destination but typed. */
template<typename T> int add_with_destination(Field<T> field, VMutableGrid<T> &dst)
template<typename T> int add_with_destination(Field<T> field, const VMutableGrid<T> &dst)
{
return this->add_with_destination(GField(std::move(field)), std::move(dst));
}

View File

@ -121,11 +121,9 @@ static Vector<GVGrid> get_volume_field_context_inputs(
GVGrid grid = context.get_volume_grid_for_input(field_input, mask, scope);
if (!grid) {
const CPPType &type = field_input.cpp_type();
const void *default_value = type.default_value();
/* Move ownership to the resource scope. */
openvdb::GridBase::Ptr buffer{volume::make_grid_for_attribute_type(type)};
buffer = scope.add_value<openvdb::GridBase::Ptr>(std::move(buffer));
grid = GVMutableGrid::ForGrid(*buffer);
openvdb::GridBase &buffer = volume::make_grid_for_attribute_type(scope, type);
grid = GVMutableGrid::ForGrid(buffer);
}
field_context_inputs.append(grid);
}
@ -186,7 +184,7 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
* depend on them. */
for (const int i : field_context_inputs.index_range()) {
const GVGrid &grid = field_context_inputs[i];
if (!grid) {
if (grid.is_single()) {
continue;
}
const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i];
@ -1063,41 +1061,110 @@ struct BoolGridToMask {
}
};
static GVMutableGrid grid_mask_from_selection(const GVGrid &full_mask,
const VGrid<bool> &selection,
ResourceScope & /*scope*/)
static GVGrid grid_mask_from_selection(const GVGrid &full_mask,
const VGrid<bool> &selection,
ResourceScope &scope)
{
if (!full_mask) {
return {};
}
/* Empty bool grid with same transform and metadata as the full mask */
VMutableGrid<bool> result = {openvdb::BoolGrid::create(*full_mask.grid_)};
volume::grid_to_static_type(full_mask.grid_, [&](auto &typed_full_mask) {
result.grid_->topologyUnion(typed_full_mask);
});
if (selection) {
BoolGridToMask op{selection.grid_->getConstAccessor()};
openvdb::tools::foreach (result.grid_->beginValueOn(), op);
const CommonVGridInfo mask_info = full_mask.common_info();
if (mask_info.type == CommonVGridInfo::Type::Grid) {
/* Empty bool grid with same transform and metadata as the full mask */
openvdb::GridBase *mask_grid = full_mask.get_internal_grid();
VMutableGrid<bool> mask_for_write = VMutableGrid<bool>::ForGrid(
scope.construct<openvdb::BoolGrid>(*mask_grid));
/* Initializes result with mask topology, only needed in some cases. */
auto apply_mask_topology = [&]() {
volume::grid_to_static_type(*mask_grid, [&](auto &typed_mask_grid) {
mask_for_write.get_internal_grid().topologyUnion(typed_mask_grid);
});
};
/* Merge mask with the selection field. */
if (selection) {
const CommonVGridInfo selection_info = selection.common_info();
switch (selection_info.type) {
case CommonVGridInfo::Type::Grid: {
apply_mask_topology();
BoolGridToMask op{selection.get_internal_grid()->getConstAccessor()};
openvdb::tools::foreach (mask_for_write.get_internal_grid().beginValueOn(), op);
break;
}
case CommonVGridInfo::Type::Single: {
const bool is_selected = selection.get_internal_single();
if (is_selected) {
apply_mask_topology();
}
}
case CommonVGridInfo::Type::Any: {
// TODO
// selection.materialize_to_grid();
}
}
}
else {
/* All selected by default. */
apply_mask_topology();
}
return VGrid<bool>(mask_for_write);
}
return result;
else {
/* Mask is infinite. */
if (selection) {
const CommonVGridInfo selection_info = selection.common_info();
switch (selection_info.type) {
case CommonVGridInfo::Type::Grid: {
return GVGrid::ForGrid(
scope.construct<openvdb::MaskGrid>(*selection.get_internal_grid()));
}
case CommonVGridInfo::Type::Single: {
const bool is_selected = selection.get_internal_single();
return GVGrid::ForSingle(CPPType::get<bool>(), &is_selected);
}
case CommonVGridInfo::Type::Any: {
// TODO No topology source, assume infinite mask.
static const bool is_selected = true;
return GVGrid::ForSingle(CPPType::get<bool>(), &is_selected);
}
}
}
else {
static const bool is_selected = true;
return GVGrid::ForSingle(CPPType::get<bool>(), &is_selected);
}
}
return {};
}
int VolumeFieldEvaluator::add_with_destination(GField field, GMutableGrid &dst)
VolumeFieldEvaluator::VolumeFieldEvaluator(const FieldContext &context, const GVGrid &domain_mask)
: context_(context), domain_mask_(domain_mask)
{
}
VolumeFieldEvaluator::VolumeFieldEvaluator(const FieldContext &context)
: context_(context), domain_mask_(GVGrid::ForGrid(scope_.construct<openvdb::MaskGrid>()))
{
}
int VolumeFieldEvaluator::add_with_destination(GField field, const GVMutableGrid &dst)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_grids_.append(&dst);
dst_grids_.append(dst);
output_pointer_infos_.append({});
return field_index;
}
int VolumeFieldEvaluator::add(GField field, GGrid *grid_ptr)
int VolumeFieldEvaluator::add(GField field, GVGrid *grid_ptr)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_grids_.append({});
output_pointer_infos_.append(
OutputPointerInfo{grid_ptr, [](void *dst, const GGrid &varray, ResourceScope & /*scope*/) {
*static_cast<GGrid *>(dst) = varray;
OutputPointerInfo{grid_ptr, [](void *dst, const GVGrid &grid, ResourceScope & /*scope*/) {
*static_cast<GVGrid *>(dst) = grid;
}});
return field_index;
}
@ -1116,9 +1183,12 @@ static GVGrid evaluate_selection(const Field<bool> &selection_field,
ResourceScope &scope)
{
if (selection_field) {
VGrid<bool> selection =
evaluate_volume_fields(scope, {selection_field}, domain_mask, context)[0].typed<bool>();
return grid_mask_from_selection(domain_mask, selection, scope);
// XXX Why does this not compile? - Lukas
// VGrid<bool> selection =
// evaluate_volume_fields(scope, {selection_field}, domain_mask, context)[0].typed<bool>();
// return grid_mask_from_selection(domain_mask, selection, scope);
UNUSED_VARS(scope, context);
return {};
}
return domain_mask;
}
@ -1146,7 +1216,10 @@ void VolumeFieldEvaluator::evaluate()
GVGrid VolumeFieldEvaluator::get_evaluated_as_mask(const int field_index)
{
VGrid<bool> grid = this->get_evaluated(field_index).typed<bool>();
// XXX Why does this not compile? - Lukas
// VGrid<bool> grid = this->get_evaluated(field_index).typed<bool>();
VGrid<bool> grid = {};
UNUSED_VARS(field_index);
return grid_mask_from_selection(domain_mask_, grid, scope_);
}

View File

@ -190,7 +190,7 @@ struct VGridReader_For_Accessor : public VGridReader<GridType> {
}
};
template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
template<typename GridType, typename MaskGridType = openvdb::MaskGrid> struct EvalPerLeafOp {
using GGrid = GVGrid;
using GMutableGrid = GVMutableGrid;
using TreeType = typename GridType::TreeType;
@ -207,7 +207,7 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
/* Each thread gets its own copy of the functor,
* so the accessor and context don't have to be thread-safe. */
mutable typename MaskGridType::ConstAccessor mask_accessor_;
mutable std::optional<typename MaskGridType::ConstAccessor> mask_accessor_;
mutable IndexMaskMemory index_mask_memory_;
mutable mf::ContextBuilder mf_context_;
@ -222,16 +222,17 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
input_readers_.reinitialize(field_context_inputs.size());
for (const int i : field_context_inputs.index_range()) {
volume::grid_to_static_type(field_context_inputs[i].grid_, [&](auto &input_grid) {
using InputGridType = typename std::decay<decltype(input_grid)>::type;
using AccessorType = typename InputGridType::ConstAccessor;
using Converter = volume::grid_types::Converter<InputGridType>;
volume::grid_to_static_type(
*field_context_inputs[i].get_internal_grid(), [&](auto &input_grid) {
using InputGridType = typename std::decay<decltype(input_grid)>::type;
using AccessorType = typename InputGridType::ConstAccessor;
using Converter = volume::grid_types::Converter<InputGridType>;
GridReaderPtr reader_ptr =
std::make_shared<VGridReader_For_Accessor<GridType, AccessorType, Converter>>(
input_grid.getConstAccessor());
input_readers_[i] = std::move(reader_ptr);
});
GridReaderPtr reader_ptr =
std::make_shared<VGridReader_For_Accessor<GridType, AccessorType, Converter>>(
input_grid.getConstAccessor());
input_readers_[i] = std::move(reader_ptr);
});
}
}
@ -242,6 +243,13 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
{
make_input_accessors(field_context_inputs);
}
EvalPerLeafOp(Span<GGrid> field_context_inputs, const mf::ProcedureExecutor &procedure_executor)
: procedure_executor_(procedure_executor)
{
make_input_accessors(field_context_inputs);
}
EvalPerLeafOp(const EvalPerLeafOp &other)
: procedure_executor_(other.procedure_executor_),
mask_accessor_(other.mask_accessor_),
@ -253,16 +261,18 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
{
LeafNode &leaf = *leaf_iter;
/* TODO direct construction from the mask could be faster,
* not sure how to do that best. */
IndexMask index_mask = IndexMask::from_predicate(
IndexMask(leaf_size),
GrainSize(leaf_size),
index_mask_memory_,
[this, leaf](const int64_t index) -> bool {
const Coord coord = leaf.offsetToGlobalCoord(index);
return mask_accessor_.isValueOn(coord);
});
IndexMask index_mask(leaf_size);
if (mask_accessor_) {
/* TODO direct construction from the mask could be faster,
* not sure how to do that best. */
index_mask = IndexMask::from_predicate(IndexMask(leaf_size),
GrainSize(leaf_size),
index_mask_memory_,
[this, leaf](const int64_t index) -> bool {
const Coord coord = leaf.offsetToGlobalCoord(index);
return mask_accessor_.value().isValueOn(coord);
});
}
mf::ParamsBuilder mf_params{procedure_executor_, &index_mask};
@ -321,27 +331,25 @@ void evaluate_procedure_on_varying_volume_fields(ResourceScope &scope,
/* Try to get an existing virtual grid that the result should be written into. */
GVMutableGrid dst_grid = get_dst_grid(out_index);
{
if (!dst_grid) {
/* Create a destination grid pointer in the resource scope. */
openvdb::GridBase *buffer = scope.construct<openvdb::GridBase>(volume::make_grid_for_attribute_type(type);
GVMutableGrid &dst_grid = scope.add_value<GVMutableGrid>(std::move(grid_base));
GVMutableGrid grid_base = GVMutableGrid::ForGrid(*buffer);
dst_grid_ptr = &dst_grid;
}
else {
/* Write the result into the existing grid. */
*dst_grid_ptr = std::move(grid_base);
r_is_output_written_to_dst[out_index] = true;
}
r_grids[out_index] = *dst_grid_ptr;
openvdb::GridBase *buffer;
if (!dst_grid || !dst_grid.is_grid()) {
/* Create a destination grid pointer in the resource scope. */
buffer = &volume::make_grid_for_attribute_type(scope, type);
r_grids[out_index] = GVMutableGrid::ForGrid(*buffer);
dst_grid = GVMutableGrid::ForGrid(*buffer);
}
else {
/* Write the result into the existing grid. */
buffer = dst_grid.get_internal_grid();
r_grids[out_index] = dst_grid;
r_is_output_written_to_dst[out_index] = true;
}
/* Execute the multifunction procedure on each leaf buffer of the mask.
* Each leaf buffer is a contiguous array that can be used as a span.
* The leaf buffers' active voxel masks are used as index masks. */
volume::grid_to_static_type(dst_grid_ptr->grid_, [&](auto &dst_grid) {
volume::grid_to_static_type(*buffer, [&](auto &dst_grid) {
using GridType = typename std::decay<decltype(dst_grid)>::type;
/* Make sure every active tile has leaf node buffers to write into.
@ -353,16 +361,32 @@ void evaluate_procedure_on_varying_volume_fields(ResourceScope &scope,
*/
dst_grid.tree().voxelizeActiveTiles();
volume::grid_to_static_type(mask.grid_, [&](auto &mask_grid) {
using MaskGridType = typename std::decay<decltype(mask_grid)>::type;
const CommonVGridInfo mask_info = mask.common_info();
switch (mask_info.type) {
case CommonVGridInfo::Type::Single:
case CommonVGridInfo::Type::Any: {
/* Ignore mask, counts as active everywhere */
EvalPerLeafOp<GridType> func(field_context_inputs, procedure_executor);
openvdb::tools::foreach (dst_grid.tree().beginLeaf(),
func,
/*threaded=*/true,
/*shareOp=*/false);
break;
}
case CommonVGridInfo::Type::Grid: {
volume::grid_to_static_type(*mask.get_internal_grid(), [&](auto &mask_grid) {
using MaskGridType = typename std::decay<decltype(mask_grid)>::type;
EvalPerLeafOp<GridType, MaskGridType> func(
field_context_inputs, procedure_executor, mask_grid);
openvdb::tools::foreach (dst_grid.tree().beginLeaf(),
func,
/*threaded=*/true,
/*shareOp=*/false);
});
EvalPerLeafOp<GridType, MaskGridType> func(
field_context_inputs, procedure_executor, mask_grid);
openvdb::tools::foreach (dst_grid.tree().beginLeaf(),
func,
/*threaded=*/true,
/*shareOp=*/false);
});
break;
}
}
});
}
}
@ -381,21 +405,12 @@ void evaluate_procedure_on_constant_volume_fields(ResourceScope & /*scope*/,
/* Provide inputs to the procedure executor. */
for (const int i : field_context_inputs.index_range()) {
volume::grid_to_static_type(field_context_inputs[i].grid_, [&](auto &input_grid) {
using InputGridType = typename std::decay<decltype(input_grid)>::type;
using ValueType = typename InputGridType::ValueType;
using Converter = volume::grid_types::Converter<InputGridType>;
using AttributeValueType = typename Converter::AttributeValueType;
/* XXX not all grid types have a background property. */
// const ValueType input_value = input_grid.background();
typename InputGridType::ConstAccessor accessor = input_grid.getAccessor();
const ValueType input_value = accessor.getValue(openvdb::Coord(0, 0, 0));
VArray<AttributeValueType> varray = VArray<AttributeValueType>::ForSingle(
Converter::single_value_to_attribute(input_value), 1);
mf_params.add_readonly_single_input(varray);
});
BLI_assert(field_context_inputs[i].is_single());
const CPPType &type = field_context_inputs[i].type();
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
field_context_inputs[i].get_internal_single_to_uninitialized(buffer);
GVArray varray = GVArray::ForSingle(field_context_inputs[i].type(), 1, buffer);
mf_params.add_readonly_single_input(varray);
}
/* Temporary buffers for output values, these are stored as background values on empty grids
@ -418,16 +433,9 @@ void evaluate_procedure_on_constant_volume_fields(ResourceScope & /*scope*/,
const CPPType &type = field.cpp_type();
const int out_index = field_indices[i];
volume::field_to_static_type(type, [&](auto type_tag) {
using T = typename decltype(type_tag)::type;
using GridType = volume::grid_types::AttributeGrid<T>;
using Converter = volume::grid_types::Converter<GridType>;
r_grids[out_index] = GVGrid::ForSingle(type, output_buffers[out_index]);
const T &value = *static_cast<T *>(output_buffers[i]);
r_grids[out_index] = GVGrid{GridType::create(Converter::single_value_to_grid(value))};
});
/* Destruct output value buffers, value is stored in grid backgrounds now. */
/* Destruct output value buffers, value is stored in #r_grids now. */
type.destruct(output_buffers[i]);
}
}

View File

@ -191,7 +191,7 @@ VolumeGrid *fog_volume_grid_add_from_mesh(Volume *volume,
{
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(
mesh, mesh_to_volume_space_transform, voxel_size, interior_band_width, density);
return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, {std::move(mesh_grid)}) : nullptr;
return mesh_grid ? &BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr;
}
VolumeGrid *sdf_volume_grid_add_from_mesh(Volume *volume,
@ -201,7 +201,7 @@ VolumeGrid *sdf_volume_grid_add_from_mesh(Volume *volume,
const float half_band_width)
{
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_sdf_volume_grid(mesh, voxel_size, half_band_width);
return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, {std::move(mesh_grid)}) : nullptr;
return mesh_grid ? &BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr;
}
} // namespace blender::geometry
#endif

View File

@ -82,7 +82,7 @@ VolumeGrid *fog_volume_grid_add_from_points(Volume *volume,
iter.modifyValue([&](float &value) { value *= density; });
});
return BKE_volume_grid_add_vdb(*volume, name, {std::move(new_grid)});
return &BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid));
}
VolumeGrid *sdf_volume_grid_add_from_points(Volume *volume,
@ -95,7 +95,7 @@ VolumeGrid *sdf_volume_grid_add_from_points(Volume *volume,
new_grid->transform().postScale(voxel_size);
new_grid->setGridClass(openvdb::GRID_LEVEL_SET);
return BKE_volume_grid_add_vdb(*volume, name, {std::move(new_grid)});
return &BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid));
}
} // namespace blender::geometry

View File

@ -609,7 +609,8 @@ static void correctivesmooth_modifier_do(ModifierData *md,
}
if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
(csmd->bind_coords == nullptr)) {
(csmd->bind_coords == nullptr))
{
BKE_modifier_set_error(ob, md, "Bind data required");
goto error;
}

View File

@ -193,7 +193,8 @@ struct DisplaceGridOp {
template<typename GridType> void operator()()
{
if constexpr (blender::
is_same_any_v<GridType, openvdb::points::PointDataGrid, openvdb::MaskGrid>) {
is_same_any_v<GridType, openvdb::points::PointDataGrid, openvdb::MaskGrid>)
{
/* We don't support displacing these grid types yet. */
return;
}
@ -289,8 +290,7 @@ static void displace_volume(ModifierData *md, const ModifierEvalContext *ctx, Vo
VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(volume, grid_index);
BLI_assert(volume_grid != nullptr);
openvdb::GridBase::Ptr grid =
BKE_volume_grid_openvdb_for_write(volume, volume_grid, false).grid_;
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false);
VolumeGridType grid_type = BKE_volume_grid_type(volume_grid);
DisplaceGridOp displace_grid_op{*grid, *vdmd, *ctx};

View File

@ -139,7 +139,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
return create_empty_mesh(input_mesh);
}
if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE &&
vmmd->voxel_size == 0.0f) {
vmmd->voxel_size == 0.0f)
{
return create_empty_mesh(input_mesh);
}
if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT &&
@ -157,8 +158,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
return create_empty_mesh(input_mesh);
}
const openvdb::GridBase::ConstPtr local_grid =
BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
const openvdb::GridBase::ConstPtr local_grid = BKE_volume_grid_openvdb_for_read(volume,
volume_grid);
openvdb::math::Transform::Ptr transform = local_grid->transform().copy();
transform->postMult(openvdb::Mat4d((float *)vmmd->object->object_to_world));

View File

@ -123,8 +123,8 @@ class EvaluateAtIndexInput final : public bke::GeometryFieldInput {
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const final;
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}

View File

@ -284,8 +284,8 @@ class AccumulateFieldInput final : public bke::GeometryFieldInput {
return attributes.adapt_domain(std::move(g_output), source_domain_, context.domain());
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
/* XXX Grids don't have a simple axis over which to accumulate. */
return {};
@ -380,8 +380,8 @@ class TotalFieldInput final : public bke::GeometryFieldInput {
return attributes.adapt_domain(std::move(g_outputs), source_domain_, context.domain());
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
/* TODO */
return {};

View File

@ -455,8 +455,8 @@ class BlurAttributeFieldInput final : public bke::GeometryFieldInput {
return GVArray::ForGArray(std::move(buffer_b));
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
/* TODO */
return {};

View File

@ -223,8 +223,7 @@ static void node_geo_exec(GeoNodeExecParams params)
continue;
}
openvdb::GridBase::ConstPtr base_grid =
BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
if (!base_grid) {
continue;
}
@ -233,8 +232,7 @@ static void node_geo_exec(GeoNodeExecParams params)
continue;
}
const openvdb::FloatGrid::ConstPtr grid = openvdb::gridConstPtrCast<openvdb::FloatGrid>(
base_grid);
const openvdb::FloatGrid::Ptr grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base_grid);
if (mode == GEO_NODE_DISTRIBUTE_POINTS_IN_VOLUME_DENSITY_RANDOM) {
point_scatter_density_random(*grid, density, seed, positions);

View File

@ -120,8 +120,8 @@ class EvaluateOnDomainInput final : public bke::GeometryFieldInput {
GVArray::ForGArray(std::move(values)), src_domain_, context.domain());
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}

View File

@ -132,8 +132,8 @@ class IndexOfNearestFieldInput final : public bke::GeometryFieldInput {
return VArray<int>::ForContainer(std::move(result));
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}
@ -207,8 +207,8 @@ class HasNeighborFieldInput final : public bke::GeometryFieldInput {
return VArray<bool>::ForContainer(std::move(result));
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}

View File

@ -84,8 +84,8 @@ class MaterialSelectionFieldInput final : public bke::GeometryFieldInput {
return mesh->attributes().adapt_domain<bool>(std::move(selection), ATTR_DOMAIN_FACE, domain);
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}

View File

@ -53,8 +53,8 @@ static void sdf_volume_mean_filter(Volume &volume, const GeoNodeExecParams &para
if (volume_grid == nullptr) {
return;
}
openvdb::GridBase::Ptr base_grid =
BKE_volume_grid_openvdb_for_write(&volume, volume_grid, false).grid_;
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write(
&volume, volume_grid, false);
if (!base_grid->isType<openvdb::FloatGrid>()) {
return;

View File

@ -52,8 +52,8 @@ static void sdf_volume_offset(Volume &volume, const GeoNodeExecParams &params)
if (volume_grid == nullptr) {
return;
}
openvdb::GridBase::Ptr base_grid =
BKE_volume_grid_openvdb_for_write(&volume, volume_grid, false).grid_;
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write(
&volume, volume_grid, false);
if (!base_grid->isType<openvdb::FloatGrid>()) {
return;

View File

@ -345,8 +345,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_default_remaining_outputs();
return;
}
openvdb::GridBase::ConstPtr base_grid =
BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*base_grid);
/* Check that the grid type is supported. */

View File

@ -77,7 +77,7 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
BKE_volume_grid_add_vdb(*volume, "distance", {std::move(grid)});
BKE_volume_grid_add_vdb(*volume, "distance", grid);
GeometrySet r_geometry_set = GeometrySet::from_volume(volume);
params.set_output("Volume", r_geometry_set);

View File

@ -46,8 +46,8 @@ class ToolSelectionFieldInput final : public bke::GeometryFieldInput {
return {};
}
}
volume::GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const volume::GVGrid & /*mask*/) const final
GVGrid get_volume_grid_for_context(const bke::GeometryFieldContext & /*context*/,
const GVGrid & /*mask*/) const final
{
return {};
}

View File

@ -171,7 +171,7 @@ static void node_geo_exec(GeoNodeExecParams params)
openvdb::math::Vec3<float>(bounds_min.x, bounds_min.y, bounds_min.z));
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
BKE_volume_grid_add_vdb(*volume, "density", {std::move(grid)});
BKE_volume_grid_add_vdb(*volume, "density", std::move(grid));
GeometrySet r_geometry_set;
r_geometry_set.replace_volume(volume);

View File

@ -180,7 +180,7 @@ static Mesh *create_mesh_from_volume(GeometrySet &geometry_set, GeoNodeExecParam
Vector<openvdb::GridBase::ConstPtr> grids;
for (const int i : IndexRange(BKE_volume_num_grids(volume))) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, i);
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid).grid_;
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
grids.append(std::move(grid));
}

View File

@ -401,7 +401,7 @@ struct OutputAttributeToStore {
eAttrDomain domain;
StringRefNull name;
GMutableSpan data;
volume::GVMutableGrid *grid_data;
openvdb::GridBase *grid_data;
};
/**
@ -480,7 +480,7 @@ static Vector<OutputAttributeToStore> compute_attributes_to_store(
continue;
}
const int domain_size = attributes.domain_size(domain);
const volume::GVGrid domain_mask = attributes.domain_grid_mask(domain, main_grid);
const GVGrid domain_mask = attributes.domain_grid_mask(domain, main_grid);
bke::GeometryFieldContext field_context{component, domain};
fn::FieldEvaluator field_evaluator{field_context, domain_size};
fn::VolumeFieldEvaluator volume_field_evaluator{field_context, domain_mask};
@ -496,8 +496,9 @@ static Vector<OutputAttributeToStore> compute_attributes_to_store(
field_evaluator.add_with_destination(std::move(field), store.data);
break;
case bke::GeometryComponent::AttributeType::Grid:
store.grid_data = MEM_new<volume::GVMutableGrid>(__func__);
volume_field_evaluator.add_with_destination(std::move(field), *store.grid_data);
store.grid_data = volume::make_grid_for_attribute_type(type);
volume_field_evaluator.add_with_destination(std::move(field),
GVMutableGrid::ForGrid(*store.grid_data));
break;
}
@ -554,8 +555,8 @@ static void store_computed_output_attributes(
break;
}
case bke::GeometryComponent::AttributeType::Grid: {
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
*store.grid_data->value_type());
GVMutableGrid grid = GVMutableGrid::ForGrid(*store.grid_data);
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(grid.type());
const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(
store.name);
@ -567,10 +568,7 @@ static void store_computed_output_attributes(
attributes.remove(store.name);
}
if (attributes.add(store.name,
store.domain,
bke::cpp_type_to_custom_data_type(*store.grid_data->value_type()),
bke::AttributeInitMoveGrid(*store.grid_data)))
if (attributes.add(store.name, store.domain, data_type, bke::AttributeInitMoveGrid(grid)))
{
continue;
}
@ -578,7 +576,7 @@ static void store_computed_output_attributes(
bke::GAttributeGridWriter attribute = attributes.lookup_or_add_grid_for_write(
store.name, store.domain, data_type);
if (attribute) {
attribute.grid = *store.grid_data;
attribute.grid = grid;
attribute.finish();
}