Mesh to Volume: Changes in Fog Volume #107279
|
@ -47,8 +47,6 @@ VolumeGrid *fog_volume_grid_add_from_mesh(Volume *volume,
|
|||
const Mesh *mesh,
|
||||
const float4x4 &mesh_to_volume_space_transform,
|
||||
float voxel_size,
|
||||
bool fill_volume,
|
||||
float exterior_band_width,
|
||||
float interior_band_width,
|
||||
float density);
|
||||
/**
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
#include "GEO_mesh_to_volume.hh"
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
# include <algorithm>
|
||||
# include <openvdb/openvdb.h>
|
||||
# include <openvdb/tools/GridTransformer.h>
|
||||
# include <openvdb/tools/LevelSetUtil.h>
|
||||
# include <openvdb/tools/VolumeToMesh.h>
|
||||
|
||||
namespace blender::geometry {
|
||||
|
@ -88,26 +90,28 @@ float volume_compute_voxel_size(const Depsgraph *depsgraph,
|
|||
float3 bb_max;
|
||||
bounds_fn(bb_min, bb_max);
|
||||
|
||||
/* Compute the voxel size based on the desired number of voxels and the approximated bounding
|
||||
* box of the volume. */
|
||||
/* Compute the diagonal of the bounding box. This is used because
|
||||
* it will always be bigger than the widest side of the mesh. */
|
||||
const float diagonal = math::distance(math::transform_point(transform, bb_max),
|
||||
math::transform_point(transform, bb_min));
|
||||
|
||||
const float approximate_volume_side_length = diagonal + exterior_band_width * 2.0f;
|
||||
const float voxel_size = approximate_volume_side_length / res.settings.voxel_amount /
|
||||
volume_simplify;
|
||||
return voxel_size;
|
||||
|
||||
/* To get the approximate size per voxel, first subtract the exterior band from the requested
|
||||
* voxel amount, then divide the diagonal with this value if it's bigger than 1. */
|
||||
const float voxel_size =
|
||||
(diagonal / std::max(1.0f, float(res.settings.voxel_amount) - 2.0f * exterior_band_width));
|
||||
|
||||
/* Return the simplified voxel size. */
|
||||
return voxel_size / volume_simplify;
|
||||
}
|
||||
|
||||
static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid(
|
||||
const Mesh *mesh,
|
||||
const float4x4 &mesh_to_volume_space_transform,
|
||||
const float voxel_size,
|
||||
const bool fill_volume,
|
||||
const float exterior_band_width,
|
||||
const float interior_band_width,
|
||||
const float density)
|
||||
{
|
||||
if (voxel_size == 0.0f) {
|
||||
if (voxel_size < 1e-5f || interior_band_width <= 0.0f) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -117,22 +121,21 @@ static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid(
|
|||
mesh_to_index_space_transform.location() -= 0.5f;
|
||||
|
||||
OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform};
|
||||
const float interior = std::max(1.0f, interior_band_width / voxel_size);
|
||||
|
||||
/* Convert the bandwidths from object in index space. */
|
||||
const float exterior = MAX2(0.001f, exterior_band_width / voxel_size);
|
||||
const float interior = MAX2(0.001f, interior_band_width / voxel_size);
|
||||
|
||||
/* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */
|
||||
openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
|
||||
voxel_size);
|
||||
openvdb::FloatGrid::Ptr new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||
mesh_adapter, {}, exterior, fill_volume ? FLT_MAX : interior);
|
||||
mesh_adapter, *transform, 1.0f, interior);
|
||||
|
||||
/* Give each grid cell a fixed density for now. */
|
||||
openvdb::tools::foreach (
|
||||
new_grid->beginValueOn(),
|
||||
[density](const openvdb::FloatGrid::ValueOnIter &iter) { iter.setValue(density); });
|
||||
|
||||
new_grid->setGridClass(openvdb::GRID_FOG_VOLUME);
|
||||
openvdb::tools::sdfToFogVolume(*new_grid);
|
||||
|
||||
if (density != 1.0f) {
|
||||
openvdb::tools::foreach (new_grid->beginValueOn(),
|
||||
[&](const openvdb::FloatGrid::ValueOnIter &iter) {
|
||||
iter.modifyValue([&](float &value) { value *= density; });
|
||||
});
|
||||
}
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
|
@ -180,31 +183,12 @@ VolumeGrid *fog_volume_grid_add_from_mesh(Volume *volume,
|
|||
const Mesh *mesh,
|
||||
const float4x4 &mesh_to_volume_space_transform,
|
||||
const float voxel_size,
|
||||
const bool fill_volume,
|
||||
const float exterior_band_width,
|
||||
const float interior_band_width,
|
||||
const float density)
|
||||
{
|
||||
VolumeGrid *c_grid = BKE_volume_grid_add(volume, name.c_str(), VOLUME_GRID_FLOAT);
|
||||
openvdb::FloatGrid::Ptr grid = openvdb::gridPtrCast<openvdb::FloatGrid>(
|
||||
BKE_volume_grid_openvdb_for_write(volume, c_grid, false));
|
||||
|
||||
/* Generate grid from mesh */
|
||||
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(mesh,
|
||||
mesh_to_volume_space_transform,
|
||||
voxel_size,
|
||||
fill_volume,
|
||||
exterior_band_width,
|
||||
interior_band_width,
|
||||
density);
|
||||
|
||||
if (mesh_grid != nullptr) {
|
||||
/* Merge the generated grid. Should be cheap because grid has just been created. */
|
||||
grid->merge(*mesh_grid);
|
||||
/* Change transform so that the index space is correctly transformed to object space. */
|
||||
grid->transform().postScale(voxel_size);
|
||||
}
|
||||
return c_grid;
|
||||
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(
|
||||
mesh, mesh_to_volume_space_transform, voxel_size, interior_band_width, density);
|
||||
return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr;
|
||||
}
|
||||
|
||||
VolumeGrid *sdf_volume_grid_add_from_mesh(Volume *volume,
|
||||
|
|
|
@ -2333,14 +2333,7 @@ typedef struct MeshToVolumeModifierData {
|
|||
* different. */
|
||||
int voxel_amount;
|
||||
|
||||
/** If true, every cell in the enclosed volume gets a density. Otherwise, the interior_band_width
|
||||
* is used. */
|
||||
char fill_volume;
|
||||
char _pad1[3];
|
||||
|
||||
/** Band widths are in object space. */
|
||||
float interior_band_width;
|
||||
float exterior_band_width;
|
||||
|
||||
float density;
|
||||
char _pad2[4];
|
||||
|
|
|
@ -7085,19 +7085,9 @@ static void rna_def_modifier_mesh_to_volume(BlenderRNA *brna)
|
|||
RNA_def_property_range(prop, 0, INT_MAX);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_fill_volume", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "fill_volume", 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Fill Volume", "Initialize the density grid in every cell inside the enclosed volume");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "interior_band_width", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Interior Band Width", "Width of the volume inside of the mesh");
|
||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "exterior_band_width", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Exterior Band Width", "Width of the volume outside of the mesh");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Interior Band Width", "Width of the gradient inside of the mesh");
|
||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
|
|
|
@ -51,9 +51,7 @@ static void initData(ModifierData *md)
|
|||
mvmd->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT;
|
||||
mvmd->voxel_size = 0.1f;
|
||||
mvmd->voxel_amount = 32;
|
||||
mvmd->fill_volume = true;
|
||||
mvmd->interior_band_width = 0.1f;
|
||||
mvmd->exterior_band_width = 0.1f;
|
||||
mvmd->interior_band_width = 0.2f;
|
||||
mvmd->density = 1.0f;
|
||||
}
|
||||
|
||||
|
@ -89,12 +87,7 @@ static void panel_draw(const bContext * /*C*/, Panel *panel)
|
|||
|
||||
{
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, ptr, "use_fill_volume", 0, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "exterior_band_width", 0, nullptr, ICON_NONE);
|
||||
|
||||
uiLayout *subcol = uiLayoutColumn(col, false);
|
||||
uiLayoutSetActive(subcol, !mvmd->fill_volume);
|
||||
uiItemR(subcol, ptr, "interior_band_width", 0, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "interior_band_width", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
{
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
|
@ -140,13 +133,13 @@ static Volume *mesh_to_volume(ModifierData *md,
|
|||
resolution.mode = (MeshToVolumeModifierResolutionMode)mvmd->resolution_mode;
|
||||
if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
|
||||
resolution.settings.voxel_amount = mvmd->voxel_amount;
|
||||
if (resolution.settings.voxel_amount <= 0.0f) {
|
||||
if (resolution.settings.voxel_amount < 1.0f) {
|
||||
return input_volume;
|
||||
}
|
||||
}
|
||||
else if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) {
|
||||
resolution.settings.voxel_size = mvmd->voxel_size;
|
||||
if (resolution.settings.voxel_size <= 0.0f) {
|
||||
if (resolution.settings.voxel_size < 1e-5f) {
|
||||
return input_volume;
|
||||
}
|
||||
}
|
||||
|
@ -157,11 +150,8 @@ static Volume *mesh_to_volume(ModifierData *md,
|
|||
r_max = bb->vec[6];
|
||||
};
|
||||
|
||||
const float voxel_size = geometry::volume_compute_voxel_size(ctx->depsgraph,
|
||||
bounds_fn,
|
||||
resolution,
|
||||
mvmd->exterior_band_width,
|
||||
mesh_to_own_object_space_transform);
|
||||
const float voxel_size = geometry::volume_compute_voxel_size(
|
||||
ctx->depsgraph, bounds_fn, resolution, 0.0f, mesh_to_own_object_space_transform);
|
||||
|
||||
/* Create a new volume. */
|
||||
Volume *volume;
|
||||
|
@ -178,8 +168,6 @@ static Volume *mesh_to_volume(ModifierData *md,
|
|||
mesh,
|
||||
mesh_to_own_object_space_transform,
|
||||
voxel_size,
|
||||
mvmd->fill_volume,
|
||||
mvmd->exterior_band_width,
|
||||
mvmd->interior_band_width,
|
||||
mvmd->density);
|
||||
|
||||
|
|
|
@ -32,21 +32,12 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.max(FLT_MAX)
|
||||
.subtype(PROP_DISTANCE);
|
||||
b.add_input<decl::Float>(N_("Voxel Amount")).default_value(64.0f).min(0.0f).max(FLT_MAX);
|
||||
b.add_input<decl::Float>(N_("Exterior Band Width"))
|
||||
.default_value(0.1f)
|
||||
.min(0.0f)
|
||||
.max(FLT_MAX)
|
||||
.subtype(PROP_DISTANCE)
|
||||
.description(N_("Width of the volume outside of the mesh"));
|
||||
b.add_input<decl::Float>(N_("Interior Band Width"))
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.default_value(0.2f)
|
||||
.min(0.0001f)
|
||||
.max(FLT_MAX)
|
||||
.subtype(PROP_DISTANCE)
|
||||
.description(N_("Width of the volume inside of the mesh"));
|
||||
b.add_input<decl::Bool>(N_("Fill Volume"))
|
||||
.default_value(true)
|
||||
.description(N_("Initialize the density grid in every cell inside the enclosed volume"));
|
||||
.description(N_("Width of the gradient inside of the mesh"));
|
||||
b.add_output<decl::Geometry>(CTX_N_(BLT_I18NCONTEXT_ID_ID, "Volume"))
|
||||
.translation_context(BLT_I18NCONTEXT_ID_ID);
|
||||
}
|
||||
|
@ -86,9 +77,7 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶
|
|||
*(const NodeGeometryMeshToVolume *)params.node().storage;
|
||||
|
||||
const float density = params.get_input<float>("Density");
|
||||
const float exterior_band_width = params.get_input<float>("Exterior Band Width");
|
||||
const float interior_band_width = params.get_input<float>("Interior Band Width");
|
||||
const bool fill_volume = params.get_input<bool>("Fill Volume");
|
||||
|
||||
geometry::MeshToVolumeResolution resolution;
|
||||
resolution.mode = (MeshToVolumeModifierResolutionMode)storage.resolution_mode;
|
||||
|
@ -119,11 +108,8 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶
|
|||
r_max = max;
|
||||
};
|
||||
|
||||
const float voxel_size = geometry::volume_compute_voxel_size(params.depsgraph(),
|
||||
bounds_fn,
|
||||
resolution,
|
||||
exterior_band_width,
|
||||
mesh_to_volume_space_transform);
|
||||
const float voxel_size = geometry::volume_compute_voxel_size(
|
||||
params.depsgraph(), bounds_fn, resolution, 0.0f, mesh_to_volume_space_transform);
|
||||
|
||||
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
|
||||
|
||||
|
@ -133,8 +119,6 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶
|
|||
&mesh,
|
||||
mesh_to_volume_space_transform,
|
||||
voxel_size,
|
||||
fill_volume,
|
||||
exterior_band_width,
|
||||
interior_band_width,
|
||||
density);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
There's a lot going on in this statement. Do you think it could be split into two, with a descriptive variable name?