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.
8 changed files with 113 additions and 38 deletions
Showing only changes of commit ce26803d3a - Show all commits

View File

@ -232,6 +232,10 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
&custom_data, data_type, const_cast<void *>(init.data), domain_num, init.sharing_info);
return stored_data != nullptr;
}
case AttributeInit::Type::Grid:
case AttributeInit::Type::MoveGrid:
case AttributeInit::Type::SharedGrid:
return false;
}
BLI_assert_unreachable();
@ -317,6 +321,10 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
init.sharing_info);
break;
}
case AttributeInit::Type::Grid:
case AttributeInit::Type::MoveGrid:
case AttributeInit::Type::SharedGrid:
break;
}
return old_layer_num < custom_data.totlayer;
}

View File

@ -661,14 +661,14 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
}
attributes.remove(attribute_id);
if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveGrid(grid))) {
if (attributes.add(
attribute_id, domain, data_type, bke::AttributeInitMoveGrid(grid.grid_.get())))
{
return true;
}
/* 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. */
type.destruct_n(buffer, domain_size);
MEM_freeN(buffer);
return false;
}
}

View File

@ -13,17 +13,45 @@
#include "BLI_math_vector_types.hh"
#include "BLI_parameter_pack_utils.hh"
/* Note: version header included here to enable correct forward declaration of some types. No other
* OpenVDB headers should be included here, especially openvdb.h, to avoid affecting other
* compilation units. */
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
# include <openvdb/version.h>
#endif
#ifdef WITH_OPENVDB
/* Forward declaration for basic OpenVDB types. */
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
using Index = uint32_t;
class GridBase;
template<typename TreeType> class Grid;
class ValueMask;
template<typename... Types> class TypeList;
namespace tree {
template<typename T, Index Log2Dim> class LeafNode;
template<typename ChildNodeType, Index Log2Dim> class InternalNode;
template<typename ChildNodeType> class RootNode;
template<typename RootNodeType> class Tree;
/* Forward-declared version of Tree4, can't use the actual Tree4 alias because it can't be
* forward-declared. */
template<typename T, Index N1 = 5, Index N2 = 4, Index N3 = 3> struct Tree4Fwd {
using Type = openvdb::tree::Tree<openvdb::tree::RootNode<
openvdb::tree::InternalNode<openvdb::tree::InternalNode<openvdb::tree::LeafNode<T, N3>, N2>,
N1>>>;
};
} // namespace tree
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif
namespace blender {
namespace volume {
template<typename T> class Grid;
template<typename T> class MutableGrid;
} // namespace volume
/* XXX OpenVDB expects some math functions on vector types. */
template<typename T, int Size> inline VecBase<T, Size> Abs(VecBase<T, Size> v)
{
@ -41,17 +69,12 @@ template<int Size> inline VecBase<uint32_t, Size> Abs(VecBase<uint32_t, Size> v)
namespace volume {
/* -------------------------------------------------------------------- */
/** \name Tree and Grid types for Blender CPP types
* \{ */
#ifdef WITH_OPENVDB
namespace grid_types {
template<typename ValueType>
using TreeCommon = typename openvdb::tree::Tree4<ValueType, 5, 4, 3>::Type;
template<typename ValueType> using GridCommon = typename openvdb::Grid<TreeCommon<ValueType>>;
using TreeCommon = typename openvdb::tree::Tree4Fwd<ValueType, 5, 4, 3>::Type;
template<typename ValueType> using GridCommon = openvdb::Grid<TreeCommon<ValueType>>;
/* TODO add more as needed. */
/* TODO could use template magic to generate all from 1 list, but not worth it for now. */
@ -121,22 +144,18 @@ using SupportedGridTypes = openvdb::TypeList<BoolGrid,
TopologyGrid>;
} // namespace grid_types
#endif
/** \} */
template<typename T> class Grid;
template<typename T> class MutableGrid;
/* Mask defined by active voxels of the grid. */
class GridMask {
#ifdef WITH_OPENVDB
openvdb::MaskGrid::ConstPtr grid_;
static const openvdb::MaskGrid::ConstPtr empty_grid()
{
static openvdb::MaskGrid::ConstPtr grid = openvdb::MaskGrid::create();
return grid;
}
using GridPtr = std::shared_ptr<grid_types::MaskGrid>;
GridPtr grid_;
static GridPtr empty_grid();
#endif
public:
@ -159,7 +178,7 @@ class GridMask {
}
#ifdef WITH_OPENVDB
GridMask(const openvdb::MaskGrid::ConstPtr &grid) : grid_(grid) {}
GridMask(const GridPtr &grid) : grid_(grid) {}
#endif
static GridMask from_bools(const volume::GridMask &full_mask,
@ -169,7 +188,7 @@ class GridMask {
int64_t min_voxel_count() const;
#ifdef WITH_OPENVDB
const openvdb::MaskGrid::ConstPtr &grid() const
const GridPtr &grid() const
{
return grid_;
}
@ -185,7 +204,8 @@ class GridMask {
class GGrid {
public:
#ifdef WITH_OPENVDB
openvdb::GridBase::ConstPtr grid_ = nullptr;
using GridPtr = std::shared_ptr<const openvdb::GridBase>;
GridPtr grid_ = nullptr;
#endif
int64_t voxel_count() const;
@ -201,7 +221,8 @@ class GGrid {
class GMutableGrid {
public:
#ifdef WITH_OPENVDB
openvdb::GridBase::Ptr grid_ = nullptr;
using GridPtr = std::shared_ptr<openvdb::GridBase>;
GridPtr grid_ = nullptr;
#endif
operator GGrid() const
@ -356,14 +377,15 @@ template<typename Func> void field_to_static_type(const CPPType &type, Func func
}
/* Helper function to evaluate a function with a static field type. */
template<typename Func> void grid_to_static_type(const openvdb::GridBase::Ptr &grid, Func func)
template<typename Func>
void grid_to_static_type(const std::shared_ptr<openvdb::GridBase> &grid, Func func)
{
grid->apply<grid_types::SupportedGridTypes>(func);
}
/* Helper function to evaluate a function with a static field type. */
template<typename Func>
void grid_to_static_type(const openvdb::GridBase::ConstPtr &grid, Func func)
void grid_to_static_type(const std::shared_ptr<const openvdb::GridBase> &grid, Func func)
{
grid->apply<grid_types::SupportedGridTypes>(func);
}

View File

@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*/
#include "BLI_cpp_type.hh"
#include "BLI_math_base.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_parameter_pack_utils.hh"
#include "BLI_volume.hh"
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
#endif
/**
* Warning: Avoid including this inside header files.
* OpenVDB is heavily templated and exposing this can affect build times severely.
*/
namespace blender {
namespace volume {
} // namespace volume
} // namespace blender

View File

@ -377,6 +377,7 @@ set(SRC
BLI_virtual_array.hh
BLI_virtual_vector_array.hh
BLI_volume.hh
BLI_volume_openvdb.hh
BLI_voronoi_2d.h
BLI_voxel.h
BLI_winstuff.h

View File

@ -8,11 +8,20 @@
#include "BLI_cpp_type.hh"
#include "BLI_math_base.hh"
#include "BLI_volume.hh"
#include "BLI_volume_openvdb.hh"
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
#endif
namespace blender::volume {
#ifdef WITH_OPENVDB
GridMask::GridPtr GridMask::empty_grid()
{
static GridPtr grid = grid_types::MaskGrid::create();
return grid;
}
GridMask GridMask::from_bools(const volume::GridMask &full_mask,
const volume::Grid<bool> &selection)

View File

@ -121,7 +121,8 @@ static Vector<GGrid> get_volume_field_context_inputs(
if (!grid) {
const CPPType &type = field_input.cpp_type();
const void *default_value = type.default_value();
grid = GMutableGrid::create(scope, type, default_value);
grid = GMutableGrid::create(type, default_value);
scope.add_value<GGrid::GridPtr>(std::move(grid.grid_));
}
field_context_inputs.append(grid);
}
@ -573,7 +574,8 @@ Vector<GGrid> evaluate_volume_fields(ResourceScope &scope,
if (mask.is_empty()) {
for (const int i : fields_to_evaluate.index_range()) {
const CPPType &type = fields_to_evaluate[i].cpp_type();
r_grids[i] = GMutableGrid::create(scope, type);
r_grids[i] = GMutableGrid::create(type);
scope.add_value<GGrid::GridPtr>(std::move(r_grids[i].grid_));
}
return r_grids;
}
@ -613,8 +615,9 @@ Vector<GGrid> evaluate_volume_fields(ResourceScope &scope,
}
case FieldNodeType::Constant: {
const FieldConstant &field_constant = static_cast<const FieldConstant &>(field.node());
r_grids[out_index] = GMutableGrid::create(
scope, field_constant.type(), field_constant.value().get());
r_grids[out_index] = GMutableGrid::create(field_constant.type(),
field_constant.value().get());
scope.add_value<GGrid::GridPtr>(std::move(r_grids[out_index].grid_));
break;
}
case FieldNodeType::Operation: {

View File

@ -314,8 +314,8 @@ void evaluate_procedure_on_varying_volume_fields(ResourceScope &scope,
GMutableGrid dst_grid = get_dst_grid(out_index);
if (!dst_grid) {
/* Create a destination grid for the computed result. */
dst_grid = GMutableGrid::create(
scope, type, mask, type.default_value(), type.default_value());
dst_grid = GMutableGrid::create(type, mask, type.default_value(), type.default_value());
scope.add_value<GMutableGrid::GridPtr>(std::move(dst_grid.grid_));
r_grids[out_index] = dst_grid;
}
else {