Geometry Nodes: Support grid inputs to viewer node

Display the grid in the 3D viewport (internally just create a volume
geometry so this case doesn't spread into any rendering code), and add
very basic data in the spreadsheet for the grid. I had to store the geometry
in the viewer node log as a cache so the lifetime of the temporary volume
grid was long enough.

Pull Request: https://projects.blender.org/blender/blender/pulls/146780
This commit is contained in:
Hans Goudey
2025-09-25 16:51:31 +02:00
committed by Hans Goudey
parent 689f182792
commit 5ccbfbb4bc
6 changed files with 102 additions and 19 deletions

View File

@@ -1861,7 +1861,7 @@ void object_duplilist_preview(Depsgraph *depsgraph,
if (const geo_log::ViewerNodeLog *viewer_log =
geo_log::GeoNodesLog::find_viewer_node_log_for_path(*viewer_path))
{
if (std::optional<blender::bke::GeometrySet> viewer_geometry = viewer_log->main_geometry()) {
if (const blender::bke::GeometrySet *viewer_geometry = viewer_log->main_geometry()) {
ctx.preview_base_geometry = &*viewer_geometry;
make_duplis_geometry_set_impl(&ctx,
*viewer_geometry,

View File

@@ -4,6 +4,7 @@
#include <fmt/format.h>
#include "BKE_volume_grid_fwd.hh"
#include "BLI_listbase.h"
#include "BLI_math_matrix.hh"
#include "BLI_virtual_array.hh"
@@ -564,6 +565,18 @@ void VolumeDataSource::foreach_default_column_ids(
}
}
static StringRef grid_class_name(const bke::VolumeGridData &grid_data)
{
openvdb::GridClass grid_class = grid_data.grid_class();
if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
return IFACE_("Fog Volume");
}
if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
return IFACE_("Level Set");
}
return IFACE_("Unknown");
}
std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
const SpreadsheetColumnID &column_id) const
{
@@ -594,15 +607,7 @@ std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
if (STREQ(column_id.name, "Class")) {
return std::make_unique<ColumnValues>(
IFACE_("Class"), VArray<std::string>::from_std_func(size, [volume](int64_t index) {
const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index);
openvdb::GridClass grid_class = volume_grid->grid_class();
if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
return IFACE_("Fog Volume");
}
if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
return IFACE_("Level Set");
}
return IFACE_("Unknown");
return grid_class_name(*BKE_volume_grid_get(volume, index));
}));
}
#else
@@ -621,6 +626,51 @@ int VolumeDataSource::tot_rows() const
return BKE_volume_num_grids(volume);
}
VolumeGridDataSource::VolumeGridDataSource(const bke::GVolumeGrid &grid)
: grid_(std::make_unique<bke::GVolumeGrid>(grid))
{
}
void VolumeGridDataSource::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
if (!grid_) {
return;
}
for (const char *name : {"Data Type", "Class"}) {
SpreadsheetColumnID column_id{(char *)name};
fn(column_id, false);
}
}
std::unique_ptr<ColumnValues> VolumeGridDataSource::get_column_values(
const SpreadsheetColumnID &column_id) const
{
#ifdef WITH_OPENVDB
if (STREQ(column_id.name, "Data Type")) {
const VolumeGridType type = (*grid_)->grid_type();
const char *name = nullptr;
RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name);
return std::make_unique<ColumnValues>(IFACE_("Data Type"),
VArray<std::string>::from_single(name, 1));
}
if (STREQ(column_id.name, "Class")) {
const StringRef name = grid_class_name(grid_->get());
return std::make_unique<ColumnValues>(IFACE_("Class"),
VArray<std::string>::from_single(name, 1));
}
#else
UNUSED_VARS(column_id);
#endif
return {};
}
int VolumeGridDataSource::tot_rows() const
{
return 1;
}
ListDataSource::ListDataSource(nodes::ListPtr list) : list_(std::move(list)) {}
void ListDataSource::foreach_default_column_ids(
@@ -1051,7 +1101,7 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object
return {};
}
if (display_data.is_volume_grid()) {
return {};
return std::make_unique<VolumeGridDataSource>(display_data.get<bke::GVolumeGrid>());
}
if (display_data.is_list()) {
return std::make_unique<ListDataSource>(display_data.extract<nodes::ListPtr>());

View File

@@ -10,6 +10,7 @@
#include "BKE_geometry_set.hh"
#include "BKE_instances.hh"
#include "BKE_volume_grid_fwd.hh"
#include "NOD_geometry_nodes_bundle_fwd.hh"
#include "NOD_geometry_nodes_closure_fwd.hh"
@@ -93,6 +94,22 @@ class VolumeDataSource : public DataSource {
int tot_rows() const override;
};
class VolumeGridDataSource : public DataSource {
/** Using #unique_ptr so that `BKE_volume_grid_fwd.hh` can be used. */
std::unique_ptr<bke::GVolumeGrid> grid_;
public:
VolumeGridDataSource(const bke::GVolumeGrid &grid);
void foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const override;
std::unique_ptr<ColumnValues> get_column_values(
const SpreadsheetColumnID &column_id) const override;
int tot_rows() const override;
};
class ListDataSource : public DataSource {
nodes::ListPtr list_;

View File

@@ -888,7 +888,7 @@ static bke::GeometrySet find_geometry_for_gizmo(const Object &object_eval,
if (const geo_eval_log::ViewerNodeLog *viewer_log =
nmd_orig.runtime->eval_log->find_viewer_node_log_for_path(viewer_path))
{
if (std::optional<bke::GeometrySet> viewer_geometry = viewer_log->main_geometry()) {
if (const bke::GeometrySet *viewer_geometry = viewer_log->main_geometry()) {
return *viewer_geometry;
}
}

View File

@@ -30,6 +30,7 @@
#include <chrono>
#include "BLI_cache_mutex.hh"
#include "BLI_compute_context.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_generic_pointer.hh"
@@ -239,6 +240,9 @@ class ListInfoLog : public ValueLog {
* Data logged by a viewer node when it is executed.
*/
class ViewerNodeLog {
mutable CacheMutex main_geometry_cache_mutex_;
mutable std::optional<bke::GeometrySet> main_geometry_cache_;
public:
struct Item {
int identifier;
@@ -255,7 +259,7 @@ class ViewerNodeLog {
CustomIDVectorSet<Item, ItemIdentifierGetter> items;
std::optional<bke::GeometrySet> main_geometry() const;
const bke::GeometrySet *main_geometry() const;
};
using Clock = std::chrono::steady_clock;

View File

@@ -2,6 +2,7 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_lib_id.hh"
#include "NOD_geometry_nodes_bundle.hh"
#include "NOD_geometry_nodes_closure.hh"
#include "NOD_geometry_nodes_log.hh"
@@ -381,14 +382,25 @@ void GeoTreeLogger::log_value(const bNode &node, const bNodeSocket &socket, cons
}
}
std::optional<bke::GeometrySet> ViewerNodeLog::main_geometry() const
const bke::GeometrySet *ViewerNodeLog::main_geometry() const
{
for (const Item &item : this->items) {
if (item.value.is_single() && item.value.get_single_ptr().is_type<bke::GeometrySet>()) {
return *item.value.get_single_ptr().get<bke::GeometrySet>();
main_geometry_cache_mutex_.ensure([&]() {
for (const Item &item : this->items) {
if (item.value.is_volume_grid()) {
const bke::GVolumeGrid grid = item.value.get<bke::GVolumeGrid>();
Volume *volume = BKE_id_new_nomain<Volume>(nullptr);
grid->add_user();
BKE_volume_grid_add(volume, grid.get());
main_geometry_cache_ = bke::GeometrySet::from_volume(volume);
return;
}
if (item.value.is_single() && item.value.get_single_ptr().is_type<bke::GeometrySet>()) {
main_geometry_cache_ = *item.value.get_single_ptr().get<bke::GeometrySet>();
return;
}
}
}
return std::nullopt;
});
return main_geometry_cache_ ? &*main_geometry_cache_ : nullptr;
}
static bool warning_is_propagated(const NodeWarningPropagation propagation,