WIP: Volume grid attribute support in geometry nodes #110044
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue