Merge branch 'blender-v3.3-release'

This commit is contained in:
Jacques Lucke 2022-08-29 17:01:01 +02:00
commit 1567dca657
6 changed files with 114 additions and 30 deletions

View File

@ -114,6 +114,7 @@ int BKE_volume_grid_channels(const struct VolumeGrid *grid);
* Transformation from index space to object space.
*/
void BKE_volume_grid_transform_matrix(const struct VolumeGrid *grid, float mat[4][4]);
void BKE_volume_grid_transform_matrix_set(struct VolumeGrid *volume_grid, const float mat[4][4]);
/* Volume Editing
*
@ -133,6 +134,11 @@ struct VolumeGrid *BKE_volume_grid_add(struct Volume *volume,
VolumeGridType type);
void BKE_volume_grid_remove(struct Volume *volume, struct VolumeGrid *grid);
/**
* Openvdb crashes when the determinant of the transform matrix becomes too small.
*/
bool BKE_volume_grid_determinant_valid(double determinant);
/* Simplify */
int BKE_volume_simplify_level(const struct Depsgraph *depsgraph);
float BKE_volume_simplify_factor(const struct Depsgraph *depsgraph);
@ -186,6 +192,9 @@ openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *vo
struct VolumeGrid *grid,
bool clear);
void BKE_volume_grid_clear_tree(Volume &volume, VolumeGrid &volume_grid);
void BKE_volume_grid_clear_tree(openvdb::GridBase &grid);
VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid);
template<typename OpType>

View File

@ -1361,6 +1361,26 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid)
}
#ifdef WITH_OPENVDB
struct ClearGridOp {
openvdb::GridBase &grid;
template<typename Grid> void operator()()
{
static_cast<Grid &>(grid).clear();
}
};
void BKE_volume_grid_clear_tree(openvdb::GridBase &grid)
{
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid);
ClearGridOp op{grid};
BKE_volume_grid_type_operation(grid_type, op);
}
void BKE_volume_grid_clear_tree(Volume &volume, VolumeGrid &volume_grid)
{
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(&volume, &volume_grid, false);
BKE_volume_grid_clear_tree(*grid);
}
VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid)
{
if (grid.isType<openvdb::FloatGrid>()) {
@ -1451,6 +1471,23 @@ void BKE_volume_grid_transform_matrix(const VolumeGrid *volume_grid, float mat[4
#endif
}
void BKE_volume_grid_transform_matrix_set(struct VolumeGrid *volume_grid, const float mat[4][4])
{
#ifdef WITH_OPENVDB
openvdb::math::Mat4f mat_openvdb;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
mat_openvdb(col, row) = mat[col][row];
}
}
openvdb::GridBase::Ptr grid = volume_grid->grid();
grid->setTransform(std::make_shared<openvdb::math::Transform>(
std::make_shared<openvdb::math::AffineMap>(mat_openvdb)));
#else
UNUSED_VARS(grid, mat);
#endif
}
/* Grid Tree and Voxels */
/* Volume Editing */
@ -1547,6 +1584,16 @@ void BKE_volume_grid_remove(Volume *volume, VolumeGrid *grid)
#endif
}
bool BKE_volume_grid_determinant_valid(const double determinant)
{
#ifdef WITH_OPENVDB
/* Limit taken from openvdb/math/Maps.h. */
return std::abs(determinant) >= 3.0 * openvdb::math::Tolerance<double>::value();
#else
return true;
#endif
}
int BKE_volume_simplify_level(const Depsgraph *depsgraph)
{
if (DEG_get_mode(depsgraph) != DAG_EVAL_RENDER) {

View File

@ -34,7 +34,8 @@ void transform_mesh(Mesh &mesh,
const float3 rotation,
const float3 scale);
void transform_geometry_set(GeometrySet &geometry,
void transform_geometry_set(GeoNodeExecParams &params,
GeometrySet &geometry,
const float4x4 &transform,
const Depsgraph &depsgraph);

View File

@ -80,7 +80,7 @@ static void node_geo_exec(GeoNodeExecParams params)
else {
geometry_set = bke::object_get_evaluated_geometry_set(*object);
if (transform_space_relative) {
transform_geometry_set(geometry_set, transform, *params.depsgraph());
transform_geometry_set(params, geometry_set, transform, *params.depsgraph());
}
}

View File

@ -83,44 +83,61 @@ static void transform_instances(InstancesComponent &instances, const float4x4 &t
}
}
static void transform_volume(Volume &volume, const float4x4 &transform, const Depsgraph &depsgraph)
static void transform_volume(GeoNodeExecParams &params,
Volume &volume,
const float4x4 &transform,
const Depsgraph &depsgraph)
{
#ifdef WITH_OPENVDB
/* Scaling an axis to zero is not supported for volumes. */
const float3 translation = transform.translation();
const float3 rotation = transform.to_euler();
const float3 scale = transform.scale();
const float3 limited_scale = {
(scale.x == 0.0f) ? FLT_EPSILON : scale.x,
(scale.y == 0.0f) ? FLT_EPSILON : scale.y,
(scale.z == 0.0f) ? FLT_EPSILON : scale.z,
};
const float4x4 scale_limited_transform = float4x4::from_loc_eul_scale(
translation, rotation, limited_scale);
const Main *bmain = DEG_get_bmain(&depsgraph);
BKE_volume_load(&volume, bmain);
openvdb::Mat4s vdb_matrix;
memcpy(vdb_matrix.asPointer(), &scale_limited_transform, sizeof(float[4][4]));
memcpy(vdb_matrix.asPointer(), &transform, sizeof(float[4][4]));
openvdb::Mat4d vdb_matrix_d{vdb_matrix};
bool found_too_small_scale = false;
const int grids_num = BKE_volume_num_grids(&volume);
for (const int i : IndexRange(grids_num)) {
VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(&volume, i);
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(&volume, volume_grid, false);
openvdb::math::Transform &grid_transform = grid->transform();
grid_transform.postMult(vdb_matrix_d);
float4x4 grid_matrix;
BKE_volume_grid_transform_matrix(volume_grid, grid_matrix.values);
mul_m4_m4_pre(grid_matrix.values, transform.values);
const float determinant = determinant_m4(grid_matrix.values);
if (!BKE_volume_grid_determinant_valid(determinant)) {
found_too_small_scale = true;
/* Clear the tree because it is too small. */
BKE_volume_grid_clear_tree(volume, *volume_grid);
if (determinant == 0) {
/* Reset rotation and scale. */
copy_v3_fl3(grid_matrix.values[0], 1, 0, 0);
copy_v3_fl3(grid_matrix.values[1], 0, 1, 0);
copy_v3_fl3(grid_matrix.values[2], 0, 0, 1);
}
else {
/* Keep rotation but reset scale. */
normalize_v3(grid_matrix.values[0]);
normalize_v3(grid_matrix.values[1]);
normalize_v3(grid_matrix.values[2]);
}
}
BKE_volume_grid_transform_matrix_set(volume_grid, grid_matrix.values);
}
if (found_too_small_scale) {
params.error_message_add(NodeWarningType::Warning,
TIP_("Volume scale is lower than permitted by OpenVDB"));
}
#else
UNUSED_VARS(volume, transform, depsgraph);
#endif
}
static void translate_volume(Volume &volume, const float3 translation, const Depsgraph &depsgraph)
static void translate_volume(GeoNodeExecParams &params,
Volume &volume,
const float3 translation,
const Depsgraph &depsgraph)
{
transform_volume(volume, float4x4::from_location(translation), depsgraph);
transform_volume(params, volume, float4x4::from_location(translation), depsgraph);
}
static void transform_curve_edit_hints(bke::CurvesEditHints &edit_hints, const float4x4 &transform)
@ -151,7 +168,8 @@ static void translate_curve_edit_hints(bke::CurvesEditHints &edit_hints, const f
}
}
static void translate_geometry_set(GeometrySet &geometry,
static void translate_geometry_set(GeoNodeExecParams &params,
GeometrySet &geometry,
const float3 translation,
const Depsgraph &depsgraph)
{
@ -165,7 +183,7 @@ static void translate_geometry_set(GeometrySet &geometry,
translate_pointcloud(*pointcloud, translation);
}
if (Volume *volume = geometry.get_volume_for_write()) {
translate_volume(*volume, translation, depsgraph);
translate_volume(params, *volume, translation, depsgraph);
}
if (geometry.has_instances()) {
translate_instances(geometry.get_component_for_write<InstancesComponent>(), translation);
@ -175,7 +193,8 @@ static void translate_geometry_set(GeometrySet &geometry,
}
}
void transform_geometry_set(GeometrySet &geometry,
void transform_geometry_set(GeoNodeExecParams &params,
GeometrySet &geometry,
const float4x4 &transform,
const Depsgraph &depsgraph)
{
@ -189,7 +208,7 @@ void transform_geometry_set(GeometrySet &geometry,
transform_pointcloud(*pointcloud, transform);
}
if (Volume *volume = geometry.get_volume_for_write()) {
transform_volume(*volume, transform, depsgraph);
transform_volume(params, *volume, transform, depsgraph);
}
if (geometry.has_instances()) {
transform_instances(geometry.get_component_for_write<InstancesComponent>(), transform);
@ -230,10 +249,11 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Use only translation if rotation and scale don't apply. */
if (use_translate(rotation, scale)) {
translate_geometry_set(geometry_set, translation, *params.depsgraph());
translate_geometry_set(params, geometry_set, translation, *params.depsgraph());
}
else {
transform_geometry_set(geometry_set,
transform_geometry_set(params,
geometry_set,
float4x4::from_loc_eul_scale(translation, rotation, scale),
*params.depsgraph());
}

View File

@ -137,6 +137,14 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
const double3 scale_fac = double3(bounds_max - bounds_min) / double3(resolution - 1);
if (!BKE_volume_grid_determinant_valid(scale_fac.x * scale_fac.y * scale_fac.z)) {
params.error_message_add(NodeWarningType::Warning,
TIP_("Volume scale is lower than permitted by OpenVDB"));
params.set_default_remaining_outputs();
return;
}
Field<float> input_field = params.extract_input<Field<float>>("Density");
/* Evaluate input field on a 3D grid. */
@ -157,8 +165,7 @@ static void node_geo_exec(GeoNodeExecParams params)
openvdb::tools::copyFromDense(dense_grid, *grid, 0.0f);
grid->transform().preTranslate(openvdb::math::Vec3<float>(-0.5f));
const float3 scale_fac = (bounds_max - bounds_min) / float3(resolution - 1);
grid->transform().postScale(openvdb::math::Vec3<float>(scale_fac.x, scale_fac.y, scale_fac.z));
grid->transform().postScale(openvdb::math::Vec3<double>(scale_fac.x, scale_fac.y, scale_fac.z));
grid->transform().postTranslate(
openvdb::math::Vec3<float>(bounds_min.x, bounds_min.y, bounds_min.z));