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.
10 changed files with 61 additions and 231 deletions
Showing only changes of commit 45e0cbb1f0 - Show all commits

View File

@ -168,6 +168,11 @@ struct ReinterpretCastConverter {
return reinterpret_cast<const GridValueType &>(value);
}
static AttributeValueType single_value_to_attribute(const GridValueType &value)
{
return reinterpret_cast<const AttributeValueType &>(value);
}
static MutableSpan<AttributeValueType> leaf_buffer_to_varray(
const MutableSpan<LeafBufferValueType> values)
{
@ -180,28 +185,34 @@ template<typename GridType>
struct Converter : public ReinterpretCastConverter<typename GridType::ValueType,
typename GridType::ValueType,
typename GridType::ValueType> {
using AttributeValueType = typename GridType::ValueType;
};
/* Vector implementation, casts Blender vectors to OpenVDB vectors and vice versa. */
template<>
struct Converter<openvdb::Vec2fGrid>
: public ReinterpretCastConverter<float2, openvdb::math::Vec2s, openvdb::math::Vec2s> {
using AttributeValueType = float2;
};
template<>
struct Converter<openvdb::Vec3fGrid>
: public ReinterpretCastConverter<float3, openvdb::math::Vec3s, openvdb::math::Vec3s> {
using AttributeValueType = float3;
};
template<>
struct Converter<openvdb::Vec3DGrid>
: public ReinterpretCastConverter<float2, openvdb::math::Vec3d, openvdb::math::Vec3d> {
: public ReinterpretCastConverter<double3, openvdb::math::Vec3d, openvdb::math::Vec3d> {
using AttributeValueType = double3;
};
template<>
struct Converter<openvdb::Vec2IGrid>
: public ReinterpretCastConverter<int2, openvdb::math::Vec2i, openvdb::math::Vec2i> {
using AttributeValueType = int2;
};
template<>
struct Converter<openvdb::Vec3IGrid>
: public ReinterpretCastConverter<int3, openvdb::math::Vec3i, openvdb::math::Vec3i> {
using AttributeValueType = int3;
};
/* Specialization for MaskGrid: Leaf buffers directly expose the activation state bit fields. */
@ -215,6 +226,12 @@ template<> struct Converter<openvdb::MaskGrid> {
return {};
}
/* MaskGrid accessor also returns a bool. */
static AttributeValueType single_value_to_attribute(const bool value)
{
return value;
}
static MutableSpan<AttributeValueType> leaf_buffer_to_varray(
const MutableSpan<LeafBufferValueType> values)
{
@ -233,6 +250,11 @@ template<> struct Converter<openvdb::BoolGrid> {
return value;
}
static AttributeValueType single_value_to_attribute(const AttributeValueType &value)
{
return value;
}
static MutableSpan<AttributeValueType> leaf_buffer_to_varray(
const MutableSpan<LeafBufferValueType> values)
{
@ -433,6 +455,7 @@ template<typename T> class Grid {
using GridPtr = typename GridType::Ptr;
using GridConstPtr = typename GridType::ConstPtr;
using ValueType = typename GridType::ValueType;
using Converter = grid_types::Converter<GridType>;
GridConstPtr grid_ = nullptr;
#endif
@ -455,6 +478,7 @@ template<typename T> class MutableGrid {
using GridPtr = typename GridType::Ptr;
using GridConstPtr = typename GridType::ConstPtr;
using ValueType = typename GridType::ValueType;
using Converter = grid_types::Converter<GridType>;
GridPtr grid_ = nullptr;
#endif

View File

@ -115,14 +115,15 @@ void grid_to_static_type(const std::shared_ptr<const openvdb::GridBase> &grid, F
template<typename T> MutableGrid<T> MutableGrid<T>::create(const T &background_value)
{
typename GridType::Ptr grid = GridType::create(background_value);
typename GridType::Ptr grid = GridType::create(
Converter::single_value_to_grid(background_value));
return MutableGrid<T>{std::move(grid)};
}
template<typename T> MutableGrid<T> MutableGrid<T>::create()
{
ValueType value = *static_cast<const ValueType *>(CPPType::get<T>().default_value_);
typename GridType::Ptr grid = GridType::create(value);
const T &value = *CPPType::get<T>().default_value_;
typename GridType::Ptr grid = GridType::create(Converter::single_value_to_grid(value));
return MutableGrid<T>{std::move(grid)};
}
@ -138,8 +139,10 @@ MutableGrid<T> MutableGrid<T>::create(const GGrid &mask,
const typename TreeType::Ptr tree = nullptr;
volume::grid_to_static_type(mask.grid_, [&](auto &typed_mask) {
tree = typename TreeType::Ptr(new TreeType(
typed_mask.grid_->tree(), inactive_value, active_value, openvdb::TopologyCopy{}));
tree = typename TreeType::Ptr(new TreeType(typed_mask.grid_->tree(),
Converter::single_value_to_grid(inactive_value),
Converter::single_value_to_grid(active_value),
openvdb::TopologyCopy{}));
});
typename GridType::Ptr grid(new GridType(tree));
return MutableGrid<T>{std::move(grid)};

View File

@ -84,7 +84,9 @@ const CPPType *GGrid::value_type() const
const CPPType *type = nullptr;
grid_to_static_type(grid_, [&](auto &grid) {
using GridType = typename std::decay<decltype(grid)>::type;
type = &CPPType::get<typename GridType::ValueType>();
using Converter = grid_types::Converter<GridType>;
type = &CPPType::get<typename Converter::AttributeValueType>();
});
return type;
}
@ -183,7 +185,9 @@ const CPPType *GMutableGrid::value_type() const
const CPPType *type = nullptr;
grid_to_static_type(grid_, [&](auto &grid) {
using GridType = typename std::decay<decltype(grid)>::type;
type = &CPPType::get<typename GridType::ValueType>();
using Converter = grid_types::Converter<GridType>;
type = &CPPType::get<typename Converter::AttributeValueType>();
});
return type;
}

View File

@ -704,9 +704,6 @@ Vector<GGrid> evaluate_volume_fields(ResourceScope &scope,
}
/* Still have to copy over the data in the destination provided by the caller. */
*dst_grid_ptr = {computed_grid.grid_->deepCopyGrid()};
if (*dst_grid_ptr) {
const openvdb::Vec3d vsize = dst_grid_ptr->grid_->transform().voxelSize();
}
r_grids[out_index] = *dst_grid_ptr;
}
}

View File

@ -26,11 +26,11 @@ namespace mf = multi_function;
/* A VArray implementation using OpenVDB grid accessors.
* The index is converted to global voxel coordinate
* by interpreting it as a leaf buffer index. */
template<typename AccessorType, typename LeafNodeType>
class VArrayImpl_For_GridLeaf final : public VArrayImpl<typename AccessorType::ValueType> {
template<typename AccessorType, typename LeafNodeType, typename Converter>
class VArrayImpl_For_GridLeaf final : public VArrayImpl<typename Converter::AttributeValueType> {
public:
using ValueType = typename AccessorType::ValueType;
using Coord = openvdb::Coord;
using AttributeValueType = typename Converter::AttributeValueType;
protected:
const AccessorType &accessor_;
@ -38,11 +38,13 @@ class VArrayImpl_For_GridLeaf final : public VArrayImpl<typename AccessorType::V
public:
VArrayImpl_For_GridLeaf(const AccessorType &accessor, const Coord &leaf_origin)
: VArrayImpl<ValueType>(LeafNodeType::size()), accessor_(accessor), leaf_origin_(leaf_origin)
: VArrayImpl<AttributeValueType>(LeafNodeType::size()),
accessor_(accessor),
leaf_origin_(leaf_origin)
{
}
VArrayImpl_For_GridLeaf(const AccessorType &accessor, const LeafNodeType &leaf)
: VArrayImpl<ValueType>(LeafNodeType::size()),
: VArrayImpl<AttributeValueType>(LeafNodeType::size()),
accessor_(accessor),
leaf_origin_(leaf.origin())
{
@ -58,21 +60,21 @@ class VArrayImpl_For_GridLeaf final : public VArrayImpl<typename AccessorType::V
return LeafNodeType::coordToOffset(coord - leaf_origin_);
}
ValueType get(const int64_t index) const override
AttributeValueType get(const int64_t index) const override
{
const Coord coord = index_to_global_coord(index);
return accessor_.getValue(coord);
return Converter::single_value_to_attribute(accessor_.getValue(coord));
}
void materialize(const IndexMask &mask, ValueType *dst) const override
void materialize(const IndexMask &mask, AttributeValueType *dst) const override
{
mask.foreach_index([this, dst](const int64_t i) {
const Coord coord = index_to_global_coord(i);
dst[i] = accessor_.getValue(coord);
dst[i] = Converter::single_value_to_attribute(accessor_.getValue(coord));
});
}
void materialize_to_uninitialized(const IndexMask &mask, ValueType *dst) const override
void materialize_to_uninitialized(const IndexMask &mask, AttributeValueType *dst) const override
{
this->materialize(mask, dst);
}
@ -169,10 +171,11 @@ template<typename GridType> struct VGridWriter {
virtual GVMutableArray make_varray_for_leaf(const LeafNodeType &leaf) const = 0;
};
template<typename GridType, typename AccessorType>
template<typename GridType, typename AccessorType, typename Converter>
struct VGridReader_For_Accessor : public VGridReader<GridType> {
using TreeType = typename GridType::TreeType;
using LeafNodeType = typename TreeType::LeafNodeType;
using AttributeValueType = typename Converter::AttributeValueType;
AccessorType accessor_;
@ -181,9 +184,8 @@ struct VGridReader_For_Accessor : public VGridReader<GridType> {
GVArray make_varray_for_leaf(const LeafNodeType &leaf) const override
{
using VArrayImplType = VArrayImpl_For_GridLeaf<AccessorType, LeafNodeType>;
using ValueType = typename AccessorType::ValueType;
return VArray<ValueType>::template For<VArrayImplType>(accessor_, leaf);
using VArrayImplType = VArrayImpl_For_GridLeaf<AccessorType, LeafNodeType, Converter>;
return VArray<AttributeValueType>::template For<VArrayImplType>(accessor_, leaf);
}
};
@ -223,9 +225,10 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
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>;
GridReaderPtr reader_ptr =
std::make_shared<VGridReader_For_Accessor<GridType, AccessorType>>(
std::make_shared<VGridReader_For_Accessor<GridType, AccessorType, Converter>>(
input_grid.getConstAccessor());
input_readers_[i] = std::move(reader_ptr);
});
@ -394,13 +397,16 @@ void evaluate_procedure_on_constant_volume_fields(ResourceScope & /*scope*/,
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<ValueType> varray = VArray<ValueType>::ForSingle(input_value, 1);
VArray<AttributeValueType> varray = VArray<AttributeValueType>::ForSingle(
Converter::single_value_to_attribute(input_value), 1);
mf_params.add_readonly_single_input(varray);
});
}

View File

@ -234,26 +234,6 @@ static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustom
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
// static void set_computed_value(bke::VolumeGeometry &volume,
// const GVArray &in_values,
// const IndexMask &selection)

View File

@ -55,15 +55,6 @@ static void search_link_ops(GatherLinkSearchOpParams &params)
#ifdef WITH_OPENVDB
static const StringRefNull get_grid_name(GField &field)
{
if (const auto *attribute_field_input = dynamic_cast<const AttributeFieldInput *>(&field.node()))
{
return attribute_field_input->attribute_name();
}
return "";
}
static const blender::CPPType *vdb_grid_type_to_cpp_type(const VolumeGridType grid_type)
{
switch (grid_type) {
@ -177,43 +168,6 @@ class SampleVolumeFunction : public mf::MultiFunction {
}
};
static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return params.extract_input<Field<float>>("Grid_Float");
case CD_PROP_FLOAT3:
return params.extract_input<Field<float3>>("Grid_Vector");
case CD_PROP_BOOL:
return params.extract_input<Field<bool>>("Grid_Bool");
case CD_PROP_INT32:
return params.extract_input<Field<int>>("Grid_Int");
default:
BLI_assert_unreachable();
}
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams /*params*/)

View File

@ -55,15 +55,6 @@ static void search_link_ops(GatherLinkSearchOpParams &params)
#ifdef WITH_OPENVDB
static const StringRefNull get_grid_name(GField &field)
{
if (const auto *attribute_field_input = dynamic_cast<const AttributeFieldInput *>(&field.node()))
{
return attribute_field_input->attribute_name();
}
return "";
}
static const blender::CPPType *vdb_grid_type_to_cpp_type(const VolumeGridType grid_type)
{
switch (grid_type) {
@ -177,43 +168,6 @@ class SampleVolumeFunction : public mf::MultiFunction {
}
};
static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return params.extract_input<Field<float>>("Grid_Float");
case CD_PROP_FLOAT3:
return params.extract_input<Field<float3>>("Grid_Vector");
case CD_PROP_BOOL:
return params.extract_input<Field<bool>>("Grid_Bool");
case CD_PROP_INT32:
return params.extract_input<Field<int>>("Grid_Int");
default:
BLI_assert_unreachable();
}
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams /*params*/)

View File

@ -49,15 +49,6 @@ static void search_link_ops(GatherLinkSearchOpParams &params)
#ifdef WITH_OPENVDB
static const StringRefNull get_grid_name(GField &field)
{
if (const auto *attribute_field_input = dynamic_cast<const AttributeFieldInput *>(&field.node()))
{
return attribute_field_input->attribute_name();
}
return "";
}
static const blender::CPPType *vdb_grid_type_to_cpp_type(const VolumeGridType grid_type)
{
switch (grid_type) {
@ -171,43 +162,6 @@ class SampleVolumeFunction : public mf::MultiFunction {
}
};
static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return params.extract_input<Field<float>>("Grid_Float");
case CD_PROP_FLOAT3:
return params.extract_input<Field<float3>>("Grid_Vector");
case CD_PROP_BOOL:
return params.extract_input<Field<bool>>("Grid_Bool");
case CD_PROP_INT32:
return params.extract_input<Field<int>>("Grid_Int");
default:
BLI_assert_unreachable();
}
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams /*params*/)

View File

@ -63,15 +63,6 @@ static void node_init(bNodeTree * /*tree*/, bNode * /*node*/) {}
#ifdef WITH_OPENVDB
static const StringRefNull get_grid_name(GField &field)
{
if (const auto *attribute_field_input = dynamic_cast<const AttributeFieldInput *>(&field.node()))
{
return attribute_field_input->attribute_name();
}
return "";
}
static const blender::CPPType *vdb_grid_type_to_cpp_type(const VolumeGridType grid_type)
{
switch (grid_type) {
@ -185,43 +176,6 @@ class SampleVolumeFunction : public mf::MultiFunction {
}
};
static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return params.extract_input<Field<float>>("Grid_Float");
case CD_PROP_FLOAT3:
return params.extract_input<Field<float3>>("Grid_Vector");
case CD_PROP_BOOL:
return params.extract_input<Field<bool>>("Grid_Bool");
case CD_PROP_INT32:
return params.extract_input<Field<int>>("Grid_Int");
default:
BLI_assert_unreachable();
}
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams /*params*/)