78 if (ob ==
nullptr || ob->
data ==
nullptr) {
99 C,
"The remesher cannot run with a Multires modifier in the modifier stack");
113 if (mesh->remesh_voxel_size <= 0.0f) {
118 if (mesh->faces_num == 0) {
122 float isovalue = 0.0f;
124 isovalue = mesh->remesh_voxel_size * 0.3f;
128 mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity, isovalue);
144 new_mesh = mesh_fixed_poles;
155 const VArray<bool> sharp_face = *mesh->attributes().lookup_or_default<
bool>(
177 ot->
name =
"Voxel Remesh";
179 "Calculates a new manifold mesh based on the volume of the current mesh. All data layers "
181 ot->
idname =
"OBJECT_OT_voxel_remesh";
196#define VOXEL_SIZE_EDIT_MAX_GRIDS_LINES 500
197#define VOXEL_SIZE_EDIT_MAX_STR_LEN 20
220 const float initial_co[3],
221 const float end_co[3],
222 const float length_co[3],
225 const float total_len =
len_v3v3(initial_co, end_co);
226 const int tot_lines =
int(total_len / spacing);
227 const int tot_lines_half = (tot_lines / 2) + 1;
228 float spacing_dir[3], lines_start[3];
242 for (
int i = 0; i < tot_lines_half; i++) {
245 madd_v3_v3v3fl(line_start, lines_start, spacing_dir, spacing * i);
255 for (
int i = 1; i < tot_lines_half; i++) {
258 madd_v3_v3v3fl(line_start, lines_start, spacing_dir, spacing * i);
305 const float x =
clamp_f((tot_lines - a) / (
b - a), 0.0f, 1.0);
306 const float alpha_factor = 1.0f - (x * x * (3.0f - 2.0f *
x));
318 float strwidth, strheight;
319 short fstyle_points = fstyle->
points;
321 short strdrawlen = 0;
340 BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
366 status.
item(
IFACE_(
"Confirm"), ICON_EVENT_RETURN, ICON_MOUSE_LMB);
367 status.
item(
IFACE_(
"Cancel"), ICON_EVENT_ESC, ICON_MOUSE_RMB);
368 status.
item(
IFACE_(
"Change Size"), ICON_MOUSE_MOVE);
445 "Voxel Size Edit OP Custom Data");
464 const int BB_faces[6][4] = {
481 float current_normal[3];
482 float view_normal[3] = {0.0f, 0.0f, 1.0f};
486 active_object->object_to_world().ptr());
489 copy_m3_m4(mat, active_object->world_to_object().ptr());
495 float min_dot =
dot_v3v3(current_normal, view_normal);
496 float current_dot = 1;
499 for (
int i = 0; i < 6; i++) {
501 current_normal, bb.
vec[BB_faces[i][0]], bb.
vec[BB_faces[i][1]], bb.
vec[BB_faces[i][2]]);
502 current_dot =
dot_v3v3(current_normal, view_normal);
504 if (current_dot < min_dot) {
505 min_dot = current_dot;
522 float scale_mat[4][4];
524 float d_a[3], d_b[3];
525 float d_a_proj[2], d_b_proj[2];
526 float preview_plane_proj[4][2];
527 const float y_axis_proj[2] = {0.0f, 1.0f};
532 for (
int i = 0; i < 4; i++) {
533 float preview_plane_world_space[3];
535 preview_plane_world_space, active_object->object_to_world().ptr(), cd->
preview_plane[i]);
546 sub_v2_v2v2(d_a_proj, preview_plane_proj[1], preview_plane_proj[0]);
547 sub_v2_v2v2(d_b_proj, preview_plane_proj[3], preview_plane_proj[0]);
559 if (d_b_proj[0] < 0.0f) {
562 if (d_a_proj[1] < 0.0f) {
569 if (d_a_proj[0] < 0.0f) {
572 if (d_b_proj[1] < 0.0f) {
582 mat4_to_size(scale, active_object->object_to_world().ptr());
592 float text_pos_word_space[3];
593 mul_v3_m4v3(text_pos_word_space, active_object->object_to_world().ptr(), text_pos);
615 ot->
name =
"Edit Voxel Size";
616 ot->
description =
"Modify the mesh voxel size interactively used in the voxel remesher";
617 ot->
idname =
"OBJECT_OT_voxel_size_edit";
634#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE 0.005f
680 const Span<int> corner_verts = mesh->corner_verts();
681 const Span<int> corner_edges = mesh->corner_edges();
683 bool is_manifold_consistent =
true;
684 char *edge_faces = (
char *)
MEM_callocN(mesh->edges_num *
sizeof(
char),
"remesh_manifold_check");
686 mesh->edges_num,
sizeof(
uint),
"remesh_consistent_check");
688 for (
uint i = 0; i < mesh->edges_num; i++) {
692 for (
const int corner_i : corner_verts.
index_range()) {
693 const int vert = corner_verts[corner_i];
694 const int edge = corner_edges[corner_i];
695 edge_faces[edge] += 1;
696 if (edge_faces[edge] > 2) {
697 is_manifold_consistent =
false;
701 if (edge_vert[edge] == -1) {
702 edge_vert[edge] = vert;
704 else if (edge_vert[edge] == vert) {
706 is_manifold_consistent =
false;
711 if (is_manifold_consistent) {
712 for (
const int i : edges.index_range()) {
714 if (edge_faces[i] == 0) {
715 is_manifold_consistent =
false;
719 if (
compare_v3v3(positions[edges[i][0]], positions[edges[i][1]], 1e-4f)) {
720 is_manifold_consistent =
false;
729 return is_manifold_consistent;
747 bool should_break = (
G.is_break);
777 Mesh *mesh_bisect, *mesh_bisect_temp;
781 float plane_co[3], plane_no[3];
784 for (
char i = 0; i < 3; i++) {
786 if (symmetry_axes & symm_it) {
791 plane_no[axis] = -1.0f;
792 mesh_bisect_temp = mesh_bisect;
794 &mmd, mesh_bisect, axis, plane_co, plane_no);
795 if (mesh_bisect_temp != mesh_bisect) {
810 Mesh *mesh_mirror, *mesh_mirror_temp;
816 for (
char i = 0; i < 3; i++) {
818 if (symmetry_axes & symm_it) {
822 mesh_mirror_temp = mesh_mirror;
824 &mmd, ob, mesh_mirror, axis,
true,
nullptr,
nullptr);
825 if (mesh_mirror_temp != mesh_mirror) {
871#ifdef USE_MESH_CURVATURE
881 if (new_mesh ==
nullptr) {
883 worker_status->
stop =
false;
914 worker_status->
stop =
false;
940 "QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
941 "consistent direction");
962#ifdef USE_MESH_CURVATURE
974 for (
char i = 0; i < 3; i++) {
1001 "QuadriFlow Remesh",
1030 faces_num = area / (edge_len * edge_len);
1040 faces_num = mesh->faces_num * ratio;
1059 if (
STREQ(prop_id,
"target_faces")) {
1090 "Specify target number of faces relative to the current mesh"},
1095 "Input target edge length in the new mesh"},
1097 {0,
nullptr, 0,
nullptr,
nullptr},
1103 C, op, event,
IFACE_(
"QuadriFlow Remesh the Selected Mesh"),
IFACE_(
"Remesh"));
1109 ot->
name =
"QuadriFlow Remesh";
1111 "Create a new quad based mesh using the surface data of the current mesh. All data "
1112 "layers will be lost";
1113 ot->
idname =
"OBJECT_OT_quadriflow_remesh";
1128 "use_mesh_symmetry",
1130 "Use Mesh Symmetry",
1131 "Generates a symmetrical mesh using the mesh symmetry configuration");
1134 "use_preserve_sharp",
1137 "Try to preserve sharp features on the mesh");
1140 "use_preserve_boundary",
1142 "Preserve Mesh Boundary",
1143 "Try to preserve mesh boundary on the mesh");
1144#ifdef USE_MESH_CURVATURE
1146 "use_mesh_curvature",
1148 "Use Mesh Curvature",
1149 "Take the mesh curvature into account when remeshing");
1152 "preserve_attributes",
1154 "Preserve Attributes",
1155 "Reproject attributes onto the new mesh");
1161 "Set the output mesh normals to smooth");
1168 "How to specify the amount of detail for the new mesh");
1176 "Relative number of faces compared to the current mesh",
1181 "target_edge_length",
1186 "Target edge length in the new mesh",
1196 "Approximate number of faces (quads) in the new mesh",
1206 "Old Object Face Area",
1207 "This property is only used to cache the object area for later calculations",
1218 "Random seed to use with the solver. Different seeds will cause the remesher to "
1219 "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)
Depsgraph * CTX_data_depsgraph_pointer(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)
float BKE_mesh_calc_area(const Mesh *mesh)
Mesh * BKE_mesh_from_object(Object *ob)
@ BKE_MESH_BATCH_DIRTY_ALL
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)
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_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
void BKE_sculptsession_free_pbvh(Object &object)
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(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 unit_m4(float m[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])
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)
#define ID_IS_EDITABLE(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
@ 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(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
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(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 *(* MEM_callocN)(size_t len, const char *str)
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)
static void quadriflow_update_job(void *customdata, float progress, int *cancel)
static int quadriflow_break_job(void *customdata)
static int voxel_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
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 int quadriflow_remesh_exec(bContext *C, wmOperator *op)
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 int quadriflow_remesh_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static Mesh * remesh_symmetry_mirror(Object *ob, Mesh *mesh, eSymmetryAxes symmetry_axes)
static void quadriflow_free_job(void *customdata)
static int voxel_remesh_exec(bContext *C, wmOperator *op)
void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
static void quadriflow_start_job(void *customdata, wmJobWorkerStatus *worker_status)
static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@ QUADRIFLOW_REMESH_FACES
@ QUADRIFLOW_REMESH_RATIO
@ QUADRIFLOW_REMESH_EDGE_LENGTH
static bool quadriflow_poll_property(const bContext *C, wmOperator *op, const PropertyRNA *prop)
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)
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
eSymmetryAxes symmetry_axes
bool use_preserve_boundary
float preview_plane[4][3]
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
bool(* check)(bContext *C, wmOperator *op)
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
void(* cancel)(bContext *C, wmOperator *op)
struct ReportList * reports
void WM_report(eReportType type, const char *message)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_reportf(eReportType type, const char *format,...)
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))
int 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)