Spreadsheet: Display geometry volume component grids

This shows a geometry's volume grids in the spreadsheet.
Three columns are displayed:
 - Name: The text name of each grid
 - Data type: Float, Vector, etc.
 - Class: Fog volume, Level Set, or unkown

In the future, values of the voxels themselves could be displayed,
but that is a much more complex problem, with important performance
implications, etc.

Differential Revision: https://developer.blender.org/D13049
This commit is contained in:
Hans Goudey 2021-11-03 13:45:51 -05:00
parent 4e5537d841
commit ccead2ed9c
Notes: blender-bot 2023-02-14 07:39:44 +01:00
Referenced by commit 978ef093db, Cleanup: fix compiler warnings
Referenced by issue #92950, spreadsheet showing 0 instances when there are instances:
10 changed files with 188 additions and 23 deletions

View File

@ -67,4 +67,14 @@ set(SRC
set(LIB
)
if(WITH_OPENVDB)
list(APPEND INC_SYS
${OPENVDB_INCLUDE_DIRS}
)
list(APPEND LIB
${OPENVDB_LIBRARIES}
)
add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
endif()
blender_add_lib(bf_editor_space_spreadsheet "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -58,6 +58,7 @@ class CellValue {
std::optional<ObjectCellValue> value_object;
std::optional<CollectionCellValue> value_collection;
std::optional<GeometrySetCellValue> value_geometry_set;
std::optional<std::string> value_string;
};
} // namespace blender::ed::spreadsheet

View File

@ -20,6 +20,7 @@
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h"
#include "BKE_volume.h"
#include "DNA_ID.h"
#include "DNA_mesh_types.h"
@ -33,6 +34,11 @@
#include "NOD_geometry_nodes_eval_log.hh"
#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "FN_field_cpp_type.hh"
#include "bmesh.h"
@ -112,6 +118,9 @@ std::unique_ptr<ColumnValues> ExtraColumns::get_column_values(
r_cell_value.value_color = *(
const ColorGeometry4f *)value;
break;
case SPREADSHEET_VALUE_TYPE_STRING:
r_cell_value.value_string = *(const std::string *)value;
break;
case SPREADSHEET_VALUE_TYPE_INSTANCES:
break;
}
@ -487,6 +496,89 @@ int InstancesDataSource::tot_rows() const
return component_->instances_amount();
}
void VolumeDataSource::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
if (component_->is_empty()) {
return;
}
for (const char *name : {"Grid Name", "Data Type", "Class"}) {
SpreadsheetColumnID column_id{(char *)name};
fn(column_id, false);
}
}
std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
const SpreadsheetColumnID &column_id) const
{
const Volume *volume = component_->get_for_read();
if (volume == nullptr) {
return {};
}
#ifdef WITH_OPENVDB
const int size = this->tot_rows();
if (STREQ(column_id.name, "Grid Name")) {
return column_values_from_function(
SPREADSHEET_VALUE_TYPE_STRING,
IFACE_("Grid Name"),
size,
[volume](int index, CellValue &r_cell_value) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
r_cell_value.value_string = BKE_volume_grid_name(volume_grid);
},
6.0f);
}
if (STREQ(column_id.name, "Data Type")) {
return column_values_from_function(
SPREADSHEET_VALUE_TYPE_STRING,
IFACE_("Type"),
size,
[volume](int index, CellValue &r_cell_value) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
const VolumeGridType type = BKE_volume_grid_type(volume_grid);
const char *name = nullptr;
RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name);
r_cell_value.value_string = IFACE_(name);
},
5.0f);
}
if (STREQ(column_id.name, "Class")) {
return column_values_from_function(
SPREADSHEET_VALUE_TYPE_STRING,
IFACE_("Class"),
size,
[volume](int index, CellValue &r_cell_value) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
openvdb::GridClass grid_class = grid->getGridClass();
if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
r_cell_value.value_string = IFACE_("Fog Volume");
}
else if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
r_cell_value.value_string = IFACE_("Level Set");
}
else {
r_cell_value.value_string = IFACE_("Unkown");
}
},
5.0f);
}
#endif
return {};
}
int VolumeDataSource::tot_rows() const
{
const Volume *volume = component_->get_for_read();
if (volume == nullptr) {
return 0;
}
return BKE_volume_num_grids(volume);
}
GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet,
Object *object_eval,
const GeometryComponentType used_component_type)
@ -682,6 +774,9 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object
if (component_type == GEO_COMPONENT_TYPE_INSTANCES) {
return std::make_unique<InstancesDataSource>(geometry_set, std::move(extra_columns));
}
if (component_type == GEO_COMPONENT_TYPE_VOLUME) {
return std::make_unique<VolumeDataSource>(geometry_set);
}
return std::make_unique<GeometryDataSource>(
object_eval, geometry_set, component_type, domain, std::move(extra_columns));
}

View File

@ -116,6 +116,26 @@ class InstancesDataSource : public DataSource {
int tot_rows() const override;
};
class VolumeDataSource : public DataSource {
const GeometrySet geometry_set_;
const VolumeComponent *component_;
public:
VolumeDataSource(GeometrySet geometry_set)
: geometry_set_(std::move(geometry_set)),
component_(geometry_set_.get_component_for_read<VolumeComponent>())
{
}
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;
};
std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval);
} // namespace blender::ed::spreadsheet

View File

@ -20,6 +20,7 @@
#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
#include "BKE_volume.h"
#include "BLF_api.h"
@ -48,7 +49,7 @@ static int is_component_row_selected(struct uiBut *but, const void *arg)
const bool is_domain_selected = (AttributeDomain)sspreadsheet->attribute_domain == domain;
bool is_selected = is_component_selected && is_domain_selected;
if (component == GEO_COMPONENT_TYPE_INSTANCES) {
if (ELEM(component, GEO_COMPONENT_TYPE_VOLUME, GEO_COMPONENT_TYPE_INSTANCES)) {
is_selected = is_component_selected;
}
@ -141,6 +142,14 @@ static int element_count_from_instances(const GeometrySet &geometry_set)
return 0;
}
static int element_count_from_volume(const GeometrySet &geometry_set)
{
if (const Volume *volume = geometry_set.get_volume_for_read()) {
return BKE_volume_num_grids(volume);
}
return 0;
}
static int element_count_from_component_domain(const GeometrySet &geometry_set,
GeometryComponentType component,
AttributeDomain domain)
@ -191,6 +200,10 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
BLI_str_format_attribute_domain_size(
element_count, element_count_from_instances(draw_context.current_geometry_set));
}
if (component == GEO_COMPONENT_TYPE_VOLUME) {
BLI_str_format_attribute_domain_size(
element_count, element_count_from_volume(draw_context.current_geometry_set));
}
else {
BLI_str_format_attribute_domain_size(
element_count,
@ -237,7 +250,7 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
void DatasetRegionDrawer::draw_component_row(const DatasetComponentLayoutInfo &component_info)
{
if (component_info.type == GEO_COMPONENT_TYPE_INSTANCES) {
if (ELEM(component_info.type, GEO_COMPONENT_TYPE_VOLUME, GEO_COMPONENT_TYPE_INSTANCES)) {
draw_dataset_row(
0, component_info.type, std::nullopt, component_info.icon, component_info.label, true);
}

View File

@ -74,6 +74,12 @@ constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = {
ATTR_INFO(ATTR_DOMAIN_POINT, N_("Point"), ICON_PARTICLE_POINT),
},
},
{
GEO_COMPONENT_TYPE_VOLUME,
N_("Volume Grids"),
ICON_VOLUME_DATA,
{},
},
{
GEO_COMPONENT_TYPE_INSTANCES,
N_("Instances"),

View File

@ -228,6 +228,23 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
0,
nullptr);
}
else if (cell_value.value_string.has_value()) {
uiDefIconTextBut(params.block,
UI_BTYPE_LABEL,
0,
ICON_NONE,
cell_value.value_string->c_str(),
params.xmin,
params.ymin,
params.width,
params.height,
nullptr,
0,
0,
0,
0,
nullptr);
}
}
void draw_float_vector(const CellDrawParams &params, const Span<float> values) const

View File

@ -2006,6 +2006,7 @@ typedef enum eSpreadsheetColumnValueType {
SPREADSHEET_VALUE_TYPE_FLOAT3 = 4,
SPREADSHEET_VALUE_TYPE_COLOR = 5,
SPREADSHEET_VALUE_TYPE_INSTANCES = 6,
SPREADSHEET_VALUE_TYPE_STRING = 7,
} eSpreadsheetColumnValueType;
/**

View File

@ -211,6 +211,8 @@ DEF_ENUM(rna_enum_attribute_domain_items)
DEF_ENUM(rna_enum_attribute_domain_without_corner_items)
DEF_ENUM(rna_enum_attribute_domain_with_auto_items)
DEF_ENUM(rna_enum_volume_grid_data_type_items)
DEF_ENUM(rna_enum_collection_color_items)
DEF_ENUM(rna_enum_strip_color_items)

View File

@ -33,6 +33,26 @@
#include "BLI_math_base.h"
const EnumPropertyItem rna_enum_volume_grid_data_type_items[] = {
{VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"},
{VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"},
{VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"},
{VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"},
{VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"},
{VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"},
{VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"},
{VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"},
{VOLUME_GRID_VECTOR_DOUBLE, "VECTOR_DOUBLE", 0, "Double Vector", "3D double vector"},
{VOLUME_GRID_VECTOR_INT, "VECTOR_INT", 0, "Integer Vector", "3D integer vector"},
{VOLUME_GRID_POINTS,
"POINTS",
0,
"Points (Unsupported)",
"Points grid, currently unsupported by volume objects"},
{VOLUME_GRID_UNKNOWN, "UNKNOWN", 0, "Unknown", "Unsupported data type"},
{0, NULL, 0, NULL, NULL},
};
#ifdef RNA_RUNTIME
# include "DEG_depsgraph.h"
@ -244,30 +264,10 @@ static void rna_def_volume_grid(BlenderRNA *brna)
prop, "rna_VolumeGrid_name_get", "rna_VolumeGrid_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Volume grid name");
static const EnumPropertyItem data_type_items[] = {
{VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"},
{VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"},
{VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"},
{VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"},
{VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"},
{VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"},
{VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"},
{VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"},
{VOLUME_GRID_VECTOR_DOUBLE, "VECTOR_DOUBLE", 0, "Double Vector", "3D double vector"},
{VOLUME_GRID_VECTOR_INT, "VECTOR_INT", 0, "Integer Vector", "3D integer vector"},
{VOLUME_GRID_POINTS,
"POINTS",
0,
"Points (Unsupported)",
"Points grid, currently unsupported by volume objects"},
{VOLUME_GRID_UNKNOWN, "UNKNOWN", 0, "Unknown", "Unsupported data type"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_VolumeGrid_data_type_get", NULL, NULL);
RNA_def_property_enum_items(prop, data_type_items);
RNA_def_property_enum_items(prop, rna_enum_volume_grid_data_type_items);
RNA_def_property_ui_text(prop, "Data Type", "Data type of voxel values");
prop = RNA_def_property(srna, "channels", PROP_INT, PROP_UNSIGNED);