Cleanup: Consolidate dyntopo bmesh detail_size calculation #118636

Merged
Raul Fernandez Hernandez merged 1 commits from Sean-Kim/blender:detail-size-cleanup into main 2024-02-28 19:43:05 +01:00
5 changed files with 115 additions and 16 deletions

View File

@ -116,6 +116,19 @@ if(WIN32)
add_definitions(-DNOMINMAX)
endif()
if(WITH_GTESTS)
set(TEST_SRC
sculpt_detail_test.cc
)
set(TEST_INC
)
set(TEST_LIB
${LIB}
bf_rna # RNA_prototypes.h
)
blender_add_test_suite_lib(editor_sculpt_paint "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${TEST_LIB}")
endif()
blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.h

View File

@ -5515,17 +5515,19 @@ static void sculpt_stroke_update_step(bContext *C,
sculpt_restore_mesh(sd, ob);
if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
float object_space_constant_detail = 1.0f / (sd->constant_detail *
mat4_to_scale(ob->object_to_world().ptr()));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
BKE_pbvh_bmesh_detail_size_set(
ss->pbvh, dyntopo::detail_size::constant_to_detail_size(sd->constant_detail, ob));
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f);
BKE_pbvh_bmesh_detail_size_set(
ss->pbvh,
dyntopo::detail_size::brush_to_detail_size(sd->detail_percent, ss->cache->radius));
}
else {
BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
(ss->cache->radius / ss->cache->dyntopo_pixel_radius) *
(sd->detail_size * U.pixelsize) / 0.4f);
BKE_pbvh_bmesh_detail_size_set(
ss->pbvh,
dyntopo::detail_size::relative_to_detail_size(
sd->detail_size, ss->cache->radius, ss->cache->dyntopo_pixel_radius, U.pixelsize));
}
if (dyntopo::stroke_is_dyntopo(ss, brush)) {

View File

@ -517,17 +517,16 @@ static void dyntopo_detail_size_parallel_lines_draw(uint pos3d,
{
float object_space_constant_detail;
if (cd->mode == DETAILING_MODE_RESOLUTION) {
object_space_constant_detail = 1.0f /
(cd->current_value *
mat4_to_scale(cd->active_object->object_to_world().ptr()));
object_space_constant_detail = detail_size::constant_to_detail_size(cd->current_value,
cd->active_object);
}
else if (cd->mode == DETAILING_MODE_BRUSH_PERCENT) {
object_space_constant_detail = cd->brush_radius * cd->current_value / 100.0f;
object_space_constant_detail = detail_size::brush_to_detail_size(cd->current_value,
cd->brush_radius);
}
else {
object_space_constant_detail = (cd->brush_radius / cd->pixel_radius) *
(cd->current_value * U.pixelsize) /
detail_size::RELATIVE_SCALE_FACTOR;
object_space_constant_detail = detail_size::relative_to_detail_size(
cd->current_value, cd->brush_radius, cd->pixel_radius, U.pixelsize);
}
/* The constant detail represents the maximum edge length allowed before subdividing it. If the
@ -677,7 +676,7 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob,
}
else {
sampled_value = detail_size::constant_to_relative_detail(
detail_size, cd->brush_radius, cd->pixel_radius, cd->active_object);
detail_size, cd->brush_radius, cd->pixel_radius, U.pixelsize, cd->active_object);
}
cd->current_value = clamp_f(sampled_value, cd->min_value, cd->max_value);
}
@ -933,6 +932,24 @@ void SCULPT_OT_dyntopo_detail_size_edit(wmOperatorType *ot)
} // namespace blender::ed::sculpt_paint::dyntopo
namespace blender::ed::sculpt_paint::dyntopo::detail_size {
float constant_to_detail_size(const float constant_detail, const Object *ob)
{
return 1.0f / (constant_detail * mat4_to_scale(ob->object_to_world().ptr()));
}
float brush_to_detail_size(const float brush_percent, const float brush_radius)
{
return brush_radius * brush_percent / 100.0f;
}
float relative_to_detail_size(const float relative_detail,
const float brush_radius,
const float pixel_radius,
const float pixel_size)
{
return (brush_radius / pixel_radius) * (relative_detail * pixel_size) / RELATIVE_SCALE_FACTOR;
}
float constant_to_brush_detail(const float constant_detail,
const float brush_radius,
const Object *ob)
@ -945,11 +962,12 @@ float constant_to_brush_detail(const float constant_detail,
float constant_to_relative_detail(const float constant_detail,
const float brush_radius,
const float pixel_radius,
const float pixel_size,
const Object *ob)
{
const float object_scale = mat4_to_scale(ob->object_to_world().ptr());
return (pixel_radius / brush_radius) * (RELATIVE_SCALE_FACTOR / U.pixelsize) *
return (pixel_radius / brush_radius) * (RELATIVE_SCALE_FACTOR / pixel_size) *
(1.0f / (constant_detail * object_scale));
}
} // namespace blender::ed::sculpt_paint::dyntopo::detail_size

View File

@ -0,0 +1,43 @@
#include "sculpt_intern.hh"
#include "BKE_object_types.hh"
#include "testing/testing.h"
namespace blender::ed::sculpt_paint::dyntopo::detail_size::test {
constexpr float CONSTANT_DETAIL = 50.0f;
constexpr float BRUSH_RADIUS = 0.5f;
constexpr float PIXEL_RADIUS = 200;
constexpr float PIXEL_SIZE = 100;
TEST(Conversion, ConstantToBrushDetail)
{
blender::bke::ObjectRuntime runtime;
runtime.object_to_world = MatBase<float, 4, 4>::identity();
Object ob;
ob.runtime = &runtime;
const float brush_percent = constant_to_brush_detail(CONSTANT_DETAIL, BRUSH_RADIUS, &ob);
const float converted = brush_to_detail_size(brush_percent, BRUSH_RADIUS);
const float expected = constant_to_detail_size(CONSTANT_DETAIL, &ob);
EXPECT_FLOAT_EQ(expected, converted);
}
TEST(Conversion, ConstantToRelativeDetail)
{
blender::bke::ObjectRuntime runtime;
runtime.object_to_world = MatBase<float, 4, 4>::identity();
Object ob;
ob.runtime = &runtime;
const float relative_detail = constant_to_relative_detail(
CONSTANT_DETAIL, BRUSH_RADIUS, PIXEL_RADIUS, PIXEL_SIZE, &ob);
const float converted = relative_to_detail_size(
relative_detail, BRUSH_RADIUS, PIXEL_RADIUS, PIXEL_SIZE);
const float expected = constant_to_detail_size(CONSTANT_DETAIL, &ob);
EXPECT_FLOAT_EQ(expected, converted);
}
} // namespace blender::ed::sculpt_paint::dyntopo::detail_size::test

View File

@ -1230,8 +1230,30 @@ void triangulate(BMesh *bm);
WarnFlag check_attribute_warning(Scene *scene, Object *ob);
namespace detail_size {
/**
* Scaling factor to match the displayed size to the actual sculpted size
*/
constexpr float RELATIVE_SCALE_FACTOR = 0.4f;
/**
* Converts from Sculpt#constant_detail to the PBVH max edge length.
*/
float constant_to_detail_size(const float constant_detail, const Object *ob);
/**
* Converts from Sculpt#detail_percent to the PBVH max edge length.
*/
float brush_to_detail_size(const float brush_percent, const float brush_radius);
/**
* Converts from Sculpt#detail_size to the PBVH max edge length.
*/
float relative_to_detail_size(const float relative_detail,
const float brush_radius,
const float pixel_radius,
const float pixel_size);
/**
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_percent value.
*
@ -1249,6 +1271,7 @@ float constant_to_brush_detail(const float constant_detail,
float constant_to_relative_detail(const float constant_detail,
const float brush_radius,
const float pixel_radius,
const float pixel_size,
const Object *ob);
}
}