81 if (ob ==
nullptr || ob->
data ==
nullptr) {
102 C,
"The remesher cannot run with a Multires modifier in the modifier stack");
116 if (
mesh->remesh_voxel_size <= 0.0f) {
121 if (
mesh->faces_num == 0) {
125 float isovalue = 0.0f;
127 isovalue =
mesh->remesh_voxel_size * 0.3f;
145 new_mesh = mesh_fixed_poles;
156 const VArray<bool> sharp_face = *
mesh->attributes().lookup_or_default<
bool>(
178 ot->name =
"Voxel Remesh";
180 "Calculates a new manifold mesh based on the volume of the current mesh. All data layers "
182 ot->idname =
"OBJECT_OT_voxel_remesh";
197#define VOXEL_SIZE_EDIT_MAX_GRIDS_LINES 500
198#define VOXEL_SIZE_EDIT_MAX_STR_LEN 20
221 const float initial_co[3],
222 const float end_co[3],
223 const float length_co[3],
226 const float total_len =
len_v3v3(initial_co, end_co);
227 const int tot_lines = int(total_len / spacing);
228 const int tot_lines_half = (tot_lines / 2) + 1;
229 float spacing_dir[3], lines_start[3];
243 for (
int i = 0;
i < tot_lines_half;
i++) {
256 for (
int i = 1;
i < tot_lines_half;
i++) {
301 const int tot_lines = int(total_len / cd->
voxel_size);
306 const float x =
clamp_f((tot_lines - a) / (
b - a), 0.0f, 1.0);
307 const float alpha_factor = 1.0f - (
x *
x * (3.0f - 2.0f *
x));
319 float strwidth, strheight;
320 short fstyle_points = fstyle->
points;
322 short strdrawlen = 0;
334 BLF_size(fontid, 10.0f * fstyle_points);
337 BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
363 status.
item(
IFACE_(
"Confirm"), ICON_EVENT_RETURN, ICON_MOUSE_LMB);
364 status.
item(
IFACE_(
"Cancel"), ICON_EVENT_ESC, ICON_MOUSE_RMB);
365 status.
item(
IFACE_(
"Change Size"), ICON_MOUSE_MOVE);
399 const float mval[2] = {float(event->
mval[0]), float(event->
mval[1])};
442 "Voxel Size Edit OP Custom Data");
459 const int BB_faces[6][4] = {
476 float current_normal[3];
477 float view_normal[3] = {0.0f, 0.0f, 1.0f};
481 active_object->object_to_world().ptr());
484 copy_m3_m4(mat, active_object->world_to_object().ptr());
490 float min_dot =
dot_v3v3(current_normal, view_normal);
491 float current_dot = 1;
494 for (
int i = 0;
i < 6;
i++) {
496 current_normal, bb.
vec[BB_faces[
i][0]], bb.
vec[BB_faces[
i][1]], bb.
vec[BB_faces[
i][2]]);
497 current_dot =
dot_v3v3(current_normal, view_normal);
499 if (current_dot < min_dot) {
500 min_dot = current_dot;
520 float scale_mat[4][4];
522 float d_a[3], d_b[3];
523 float d_a_proj[2], d_b_proj[2];
524 float preview_plane_proj[4][2];
525 const float y_axis_proj[2] = {0.0f, 1.0f};
530 for (
int i = 0;
i < 4;
i++) {
531 float preview_plane_world_space[3];
533 preview_plane_world_space, active_object->object_to_world().ptr(), cd->
preview_plane[
i]);
544 sub_v2_v2v2(d_a_proj, preview_plane_proj[1], preview_plane_proj[0]);
545 sub_v2_v2v2(d_b_proj, preview_plane_proj[3], preview_plane_proj[0]);
557 if (d_b_proj[0] < 0.0f) {
560 if (d_a_proj[1] < 0.0f) {
567 if (d_a_proj[0] < 0.0f) {
570 if (d_b_proj[1] < 0.0f) {
580 mat4_to_size(scale, active_object->object_to_world().ptr());
590 float text_pos_word_space[3];
591 mul_v3_m4v3(text_pos_word_space, active_object->object_to_world().ptr(), text_pos);
613 ot->name =
"Edit Voxel Size";
614 ot->description =
"Modify the mesh voxel size interactively used in the voxel remesher";
615 ot->idname =
"OBJECT_OT_voxel_size_edit";
632#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE 0.005f
687 bool is_manifold_consistent =
true;
695 for (
const int corner_i : corner_verts.
index_range()) {
696 const int vert = corner_verts[corner_i];
697 const int edge = corner_edges[corner_i];
698 edge_faces[edge] += 1;
699 if (edge_faces[edge] > 2) {
700 is_manifold_consistent =
false;
704 if (edge_vert[edge] == -1) {
705 edge_vert[edge] = vert;
707 else if (edge_vert[edge] == vert) {
709 is_manifold_consistent =
false;
714 if (is_manifold_consistent) {
717 if (edge_faces[
i] == 0) {
718 is_manifold_consistent =
false;
722 if (
compare_v3v3(positions[edges[
i][0]], positions[edges[
i][1]], 1e-4f)) {
723 is_manifold_consistent =
false;
732 return is_manifold_consistent;
750 bool should_break =
false;
753 bool should_break = (
G.is_break);
783 Mesh *mesh_bisect, *mesh_bisect_temp;
787 float plane_co[3], plane_no[3];
790 for (
char i = 0;
i < 3;
i++) {
792 if (symmetry_axes & symm_it) {
797 plane_no[axis] = -1.0f;
798 mesh_bisect_temp = mesh_bisect;
800 &mmd, mesh_bisect, axis, plane_co, plane_no);
801 if (mesh_bisect_temp != mesh_bisect) {
816 Mesh *mesh_mirror, *mesh_mirror_temp;
822 for (
char i = 0;
i < 3;
i++) {
824 if (symmetry_axes & symm_it) {
828 mesh_mirror_temp = mesh_mirror;
830 &mmd, ob, mesh_mirror, axis,
true,
nullptr,
nullptr);
831 if (mesh_mirror_temp != mesh_mirror) {
875#ifdef USE_MESH_CURVATURE
885 if (new_mesh ==
nullptr) {
886 worker_status->do_update =
true;
887 worker_status->stop =
false;
917 worker_status->do_update =
true;
918 worker_status->stop =
false;
946 "QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
947 "consistent direction");
968#ifdef USE_MESH_CURVATURE
980 for (
char i = 0;
i < 3;
i++) {
996 wmJobWorkerStatus worker_status = {};
997 worker_status.reports = op->
reports;
1011 "QuadriFlow Remesh",
1045 faces_num = area / (edge_len * edge_len);
1055 faces_num =
mesh->faces_num * ratio;
1074 if (
STREQ(prop_id,
"target_faces")) {
1105 "Specify target number of faces relative to the current mesh"},
1110 "Input target edge length in the new mesh"},
1112 {0,
nullptr, 0,
nullptr,
nullptr},
1118 C, op, event,
IFACE_(
"QuadriFlow Remesh the Selected Mesh"),
IFACE_(
"Remesh"));
1124 ot->name =
"QuadriFlow Remesh";
1126 "Create a new quad based mesh using the surface data of the current mesh. All data "
1127 "layers will be lost";
1128 ot->idname =
"OBJECT_OT_quadriflow_remesh";
1143 "use_mesh_symmetry",
1145 "Use Mesh Symmetry",
1146 "Generates a symmetrical mesh using the mesh symmetry configuration");
1149 "use_preserve_sharp",
1152 "Try to preserve sharp features on the mesh");
1155 "use_preserve_boundary",
1157 "Preserve Mesh Boundary",
1158 "Try to preserve mesh boundary on the mesh");
1159#ifdef USE_MESH_CURVATURE
1161 "use_mesh_curvature",
1163 "Use Mesh Curvature",
1164 "Take the mesh curvature into account when remeshing");
1167 "preserve_attributes",
1169 "Preserve Attributes",
1170 "Reproject attributes onto the new mesh");
1176 "Set the output mesh normals to smooth");
1183 "How to specify the amount of detail for the new mesh");
1191 "Relative number of faces compared to the current mesh",
1196 "target_edge_length",
1201 "Target edge length in the new mesh",
1211 "Approximate number of faces (quads) in the new mesh",
1221 "Old Object Face Area",
1222 "This property is only used to cache the object area for later calculations",
1233 "Random seed to use with the solver. Different seeds will cause the remesher to "
1234 "come up with different quad layouts on the mesh",
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_id_free(Main *bmain, void *idv)
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
@ BKE_MESH_BATCH_DIRTY_ALL
float BKE_mesh_calc_area(const Mesh *mesh)
Mesh * BKE_mesh_from_object(Object *ob)
Mesh * BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, Object *ob, const Mesh *mesh, int axis, bool use_correct_order_on_merge, int **r_vert_merge_map, int *r_vert_merge_map_len)
Mesh * BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mmd, const Mesh *mesh, int axis, const float plane_co[3], float plane_no[3])
Mesh * BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
Mesh * BKE_mesh_remesh_voxel(const Mesh *mesh, float voxel_size, float adaptivity, float isovalue, const Object *object, ModifierData *modifier_data)
Mesh * BKE_mesh_remesh_quadriflow(const Mesh *mesh, int target_faces, int seed, bool preserve_sharp, bool preserve_boundary, bool adaptive_scale, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
bool BKE_modifiers_uses_multires(Object *ob)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
void BKE_sculptsession_free_pbvh(Object &object)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
size_t BKE_unit_value_as_string_scaled(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings &settings, bool pad)
void BLF_size(int fontid, float size)
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
void BLF_color3f(int fontid, float r, float g, float b)
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
void BLF_position(int fontid, float x, float y, float z)
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
void mul_m3_v3(const float M[3][3], float r[3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_m4_m4_pre(float R[4][4], const float A[4][4])
void size_to_mat4(float R[4][4], const float size[3])
void scale_m4_fl(float R[4][4], float scale)
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mat4_to_size(float size[3], const float M[4][4])
void mul_m4_m4_post(float R[4][4], const float B[4][4])
void unit_m4(float m[4][4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void invert_v3(float r[3])
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float n[2])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ME_REMESH_REPROJECT_ATTRIBUTES
@ ME_REMESH_REPROJECT_VOLUME
Object is a sort of wrapper for general info.
bool ED_operator_object_active_editable_mesh(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
void ED_region_tag_redraw(ARegion *region)
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3])
void ED_view3d_project_v2(const ARegion *region, const float world[3], float r_region_co[2])
#define GPU_matrix_mul(x)
@ GPU_SHADER_3D_UNIFORM_COLOR
void GPU_blend(eGPUBlend blend)
void GPU_line_width(float width)
void GPU_line_smooth(bool enable)
Read Guarded memory(de)allocation.
const uiStyle * UI_style_get()
@ WM_JOB_TYPE_QUADRIFLOW_REMESH
void item_bool(std::string text, bool inverted, int icon1, int icon2=0)
void item(std::string text, int icon1, int icon2=0)
constexpr IndexRange index_range() const
#define ID_IS_EDITABLE(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void mesh_remesh_reproject_attributes(const Mesh &src, Mesh &dst)
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges=false)
static bool object_remesh_poll(bContext *C)
static Mesh * remesh_symmetry_bisect(Mesh *mesh, eSymmetryAxes symmetry_axes)
static void quadriflow_end_job(void *customdata)
@ QUADRIFLOW_REMESH_FACES
@ QUADRIFLOW_REMESH_RATIO
@ QUADRIFLOW_REMESH_EDGE_LENGTH
static void quadriflow_update_job(void *customdata, float progress, int *cancel)
static wmOperatorStatus voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int quadriflow_break_job(void *customdata)
static void voxel_size_edit_cancel(bContext *C, wmOperator *op)
static bool mesh_is_manifold_consistent(Mesh *mesh)
static bool voxel_size_edit_poll(bContext *C)
static bool quadriflow_check(bContext *C, wmOperator *op)
void OBJECT_OT_voxel_size_edit(wmOperatorType *ot)
static const EnumPropertyItem mode_type_items[]
static void voxel_size_parallel_lines_draw(uint pos3d, const float initial_co[3], const float end_co[3], const float length_co[3], const float spacing)
static void voxel_size_edit_update_header(wmOperator *op, bContext *C)
static void voxel_size_edit_draw(const bContext *C, ARegion *, void *arg)
void OBJECT_OT_voxel_remesh(wmOperatorType *ot)
static wmOperatorStatus voxel_remesh_exec(bContext *C, wmOperator *op)
static wmOperatorStatus quadriflow_remesh_exec(bContext *C, wmOperator *op)
static Mesh * remesh_symmetry_mirror(Object *ob, Mesh *mesh, eSymmetryAxes symmetry_axes)
static void quadriflow_free_job(void *customdata)
@ QUADRIFLOW_STATUS_NONMANIFOLD
@ QUADRIFLOW_STATUS_SUCCESS
@ QUADRIFLOW_STATUS_CANCELED
void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
static void quadriflow_start_job(void *customdata, wmJobWorkerStatus *worker_status)
static wmOperatorStatus voxel_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool quadriflow_poll_property(const bContext *C, wmOperator *op, const PropertyRNA *prop)
static wmOperatorStatus quadriflow_remesh_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void geometry_begin(const Scene &scene, Object &ob, const wmOperator *op)
void geometry_end(Object &ob)
#define VOXEL_SIZE_EDIT_MAX_GRIDS_LINES
#define VOXEL_SIZE_EDIT_MAX_STR_LEN
#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
ARegionRuntimeHandle * runtime
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
eSymmetryAxes symmetry_axes
wmJobWorkerStatus * worker_status
bool use_preserve_boundary
float preview_plane[4][3]
struct ReportList * reports
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
wmOperatorStatus WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)