Cleanup: Consolidate dyntopo bmesh detail_size calculation #118636
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue