WIP: Volume grid attribute support in geometry nodes #110044
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ static void sdf_volume_mean_filter(Volume &volume, const GeoNodeExecParams ¶
|
|||
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;
|
||||
|
|
|
@ -52,8 +52,8 @@ static void sdf_volume_offset(Volume &volume, const GeoNodeExecParams ¶ms)
|
|||
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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue