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.
7 changed files with 81 additions and 60 deletions
Showing only changes of commit 8145c5ab93 - Show all commits

View File

@ -206,8 +206,7 @@ GVGrid GeometryFieldInput::get_volume_grid_for_context(const fn::FieldContext &c
return this->get_volume_grid_for_context(*geometry_context, mask);
}
if (const VolumeFieldContext *volume_context = dynamic_cast<const VolumeFieldContext *>(
&context))
{
&context)) {
return this->get_volume_grid_for_context(GeometryFieldContext{volume_context->grids()}, mask);
}
return {};
@ -253,8 +252,7 @@ GVArray CurvesFieldInput::get_varray_for_context(const fn::FieldContext &context
}
}
if (const CurvesFieldContext *curves_context = dynamic_cast<const CurvesFieldContext *>(
&context))
{
&context)) {
return this->get_varray_for_context(curves_context->curves(), curves_context->domain(), mask);
}
return {};
@ -316,8 +314,7 @@ GVGrid VolumeFieldInput::get_volume_grid_for_context(const fn::FieldContext &con
}
}
if (const VolumeFieldContext *volume_context = dynamic_cast<const VolumeFieldContext *>(
&context))
{
&context)) {
return this->get_volume_grid_for_context(volume_context->grids(), mask);
}
return {};
@ -701,7 +698,7 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
}
const GVGrid domain_mask = {attributes.domain_grid_mask(domain, main_grid)};
fn::VolumeFieldEvaluator evaluator{field_context, domain_mask};
openvdb::GridBase *buffer = volume::make_grid_for_attribute_type(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);
@ -778,8 +775,7 @@ std::optional<eAttrDomain> try_detect_field_domain(const GeometryComponent &comp
}
for (const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) {
if (const auto *geometry_field_input = dynamic_cast<const GeometryFieldInput *>(
&field_input))
{
&field_input)) {
if (!handle_domain(geometry_field_input->preferred_domain(component))) {
return std::nullopt;
}
@ -802,15 +798,13 @@ std::optional<eAttrDomain> try_detect_field_domain(const GeometryComponent &comp
}
for (const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) {
if (const auto *geometry_field_input = dynamic_cast<const GeometryFieldInput *>(
&field_input))
{
&field_input)) {
if (!handle_domain(geometry_field_input->preferred_domain(component))) {
return std::nullopt;
}
}
else if (const auto *curves_field_input = dynamic_cast<const CurvesFieldInput *>(
&field_input))
{
&field_input)) {
if (!handle_domain(curves_field_input->preferred_domain(curves->geometry.wrap()))) {
return std::nullopt;
}

View File

@ -160,8 +160,7 @@ static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Volume *volume = reinterpret_cast<Volume *>(id);
if (volume->packedfile != nullptr &&
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0)
{
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
return;
}
@ -1237,7 +1236,7 @@ bool BKE_volume_grid_bounds(const openvdb::GridBase &grid, float3 &r_min, float3
return true;
}
openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase &grid,
openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(const openvdb::GridBase &grid,
const blender::float4x4 &transform)
{
openvdb::math::Transform::Ptr grid_transform = grid.transform().copy();

View File

@ -28,10 +28,11 @@ OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
class GridBase;
template<typename TreeType> class Grid;
class MetaMap;
template<typename TreeType> class Grid;
namespace tree {
class TreeBase;
template<typename T, Index Log2Dim> class LeafNode;
template<typename ChildNodeType, Index Log2Dim> class InternalNode;
template<typename ChildNodeType> class RootNode;
@ -283,7 +284,13 @@ using SupportedGridTypes = openvdb::TypeList<openvdb::BoolGrid,
} // namespace grid_types
openvdb::GridBase &make_grid_for_attribute_type(ResourceScope &scope,
std::shared_ptr<openvdb::tree::TreeBase> make_tree_for_attribute_type(ResourceScope &scope,
const CPPType &type,
const void *value = nullptr);
std::shared_ptr<openvdb::tree::TreeBase> make_tree_for_attribute_type(const CPPType &type,
const void *value = nullptr);
openvdb::GridBase *make_grid_for_attribute_type(ResourceScope &scope,
const CPPType &type,
const void *value = nullptr);
openvdb::GridBase *make_grid_for_attribute_type(const CPPType &type, const void *value = nullptr);

View File

@ -19,15 +19,15 @@ namespace blender::volume {
#ifdef WITH_OPENVDB
openvdb::TreeBase::Ptr make_tree_for_attribute_type(const CPPType &type,
const void *value,
std::optional<ResourceScope> scope)
static std::shared_ptr<openvdb::tree::TreeBase> make_tree_for_attribute_type(ResourceScope *scope,
const CPPType &type,
const void *value)
{
if (value == nullptr) {
value = type.default_value();
}
openvdb::TreeBase::Ptr result = nullptr;
std::shared_ptr<openvdb::tree::TreeBase> result = nullptr;
volume::field_to_static_type(type, [&](auto tag) {
using ValueType = typename decltype(tag)::type;
using GridType = volume::grid_types::AttributeGrid<ValueType>;
@ -35,9 +35,10 @@ openvdb::TreeBase::Ptr make_tree_for_attribute_type(const CPPType &type,
using Converter = volume::grid_types::Converter<GridType>;
const ValueType &background_value = *static_cast<const ValueType *>(value);
TreeType::Ptr tree = TreeType::create(Converter::single_value_to_grid(background_value));
std::shared_ptr<openvdb::tree::TreeBase> tree = std::make_shared<TreeType>(
Converter::single_value_to_grid(background_value));
if (scope) {
result = scope.add_value(std::move(tree));
result = scope->add_value(std::move(tree));
}
else {
result = tree;
@ -47,9 +48,22 @@ openvdb::TreeBase::Ptr make_tree_for_attribute_type(const CPPType &type,
return result;
}
openvdb::GridBase &make_grid_for_attribute_type(const CPPType &type,
const void *value,
std::optional<ResourceScope> scope)
std::shared_ptr<openvdb::tree::TreeBase> make_tree_for_attribute_type(ResourceScope &scope,
const CPPType &type,
const void *value)
{
return make_tree_for_attribute_type(&scope, type, value);
}
std::shared_ptr<openvdb::tree::TreeBase> make_tree_for_attribute_type(const CPPType &type,
const void *value)
{
return make_tree_for_attribute_type(nullptr, type, value);
}
static openvdb::GridBase *make_grid_for_attribute_type(ResourceScope *scope,
const CPPType &type,
const void *value)
{
if (value == nullptr) {
value = type.default_value();
@ -63,14 +77,26 @@ openvdb::GridBase &make_grid_for_attribute_type(const CPPType &type,
const ValueType &background_value = *static_cast<const ValueType *>(value);
if (scope) {
result = &scope.construct<GridType>(Converter::single_value_to_grid(background_value));
result = &scope->construct<GridType>(Converter::single_value_to_grid(background_value));
}
else {
result = MEM_new<GridType>(__func__, Converter::single_value_to_grid(background_value));
}
});
BLI_assert(result != nullptr);
return *result;
return result;
}
openvdb::GridBase *make_grid_for_attribute_type(ResourceScope &scope,
const CPPType &type,
const void *value)
{
return make_grid_for_attribute_type(&scope, type, value);
}
openvdb::GridBase *make_grid_for_attribute_type(const CPPType &type, const void *value)
{
return make_grid_for_attribute_type(nullptr, type, value);
}
const CPPType &grid_base_attribute_type(const openvdb::GridBase &grid)

View File

@ -122,7 +122,7 @@ static Vector<GVGrid> get_volume_field_context_inputs(
if (!grid) {
const CPPType &type = field_input.cpp_type();
/* Move ownership to the resource scope. */
openvdb::GridBase &buffer = volume::make_grid_for_attribute_type(scope, type);
openvdb::GridBase &buffer = *volume::make_grid_for_attribute_type(scope, type);
grid = GVMutableGrid::ForGrid(buffer);
}
field_context_inputs.append(grid);
@ -698,19 +698,14 @@ Vector<GVGrid> evaluate_volume_fields(ResourceScope &scope,
computed_grid.get_internal_grid()->baseTree().copy());
}
else if (computed_grid.is_single()) {
volume::grid_to_static_type(*dst_grid.get_internal_grid(), [&](auto &typed_dst_grid) {
using DstGridType = typename std::decay<decltype(typed_dst_grid)>::type;
using DstTreeType = typename DstGridType::TreeType;
computed_grid.get_internal_single()
typename DstTreeType::Ptr dst_tree = DstTreeType::create(;
dst_grid.get_internal_grid()->setTree(dst_tree);
});
computed_grid.get_internal_grid()->baseTree().copy());
BUFFER_FOR_CPP_TYPE_VALUE(dst_grid.type(), buffer);
computed_grid.get_internal_single(buffer);
dst_grid.get_internal_grid()->setTree(
volume::make_tree_for_attribute_type(dst_grid.type(), buffer));
}
else {
/* Output grids should be grids or single values. */
BLI_assert_unreachable();
/* TODO materialize into the grid? What's the topology? */
BLI_assert_unreachable();
}
}
r_grids[out_index] = dst_grid;
@ -1104,21 +1099,21 @@ static GVGrid grid_mask_from_selection(const GVGrid &full_mask,
const CommonVGridInfo selection_info = selection.common_info();
switch (selection_info.type) {
case CommonVGridInfo::Type::Grid: {
apply_mask_topology();
apply_mask_topology();
BoolGridToMask op{selection.get_internal_grid()->getConstAccessor()};
openvdb::tools::foreach (mask_for_write.get_internal_grid().beginValueOn(), op);
break;
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();
}
const bool is_selected = selection.get_internal_single();
if (is_selected) {
apply_mask_topology();
}
}
case CommonVGridInfo::Type::Any: {
// TODO
// selection.materialize_to_grid();
// TODO
// selection.materialize_to_grid();
}
}
}
@ -1134,17 +1129,17 @@ static GVGrid grid_mask_from_selection(const GVGrid &full_mask,
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()));
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);
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);
// TODO No topology source, assume infinite mask.
static const bool is_selected = true;
return GVGrid::ForSingle(CPPType::get<bool>(), &is_selected);
}
}
}

View File

@ -334,7 +334,7 @@ void evaluate_procedure_on_varying_volume_fields(ResourceScope &scope,
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);
buffer = volume::make_grid_for_attribute_type(scope, type);
r_grids[out_index] = GVMutableGrid::ForGrid(*buffer);
dst_grid = GVMutableGrid::ForGrid(*buffer);
}

View File

@ -496,7 +496,7 @@ 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 = volume::make_grid_for_attribute_type(type);
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;