82 if (ob ==
nullptr || ob->
data ==
nullptr) {
103 C,
"The remesher cannot run with a Multires modifier in the modifier stack");
117 if (
mesh->remesh_voxel_size <= 0.0f) {
122 if (
mesh->faces_num == 0) {
126 float isovalue = 0.0f;
128 isovalue =
mesh->remesh_voxel_size * 0.3f;
146 new_mesh = mesh_fixed_poles;
157 const VArray<bool> sharp_face = *
mesh->attributes().lookup_or_default<
bool>(
180 ot->name =
"Voxel Remesh";
182 "Calculates a new manifold mesh based on the volume of the current mesh. All data layers "
184 ot->idname =
"OBJECT_OT_voxel_remesh";
199#define VOXEL_SIZE_EDIT_MAX_GRIDS_LINES 500
200#define VOXEL_SIZE_EDIT_MAX_STR_LEN 20
223 const float initial_co[3],
224 const float end_co[3],
225 const float length_co[3],
228 const float total_len =
len_v3v3(initial_co, end_co);
229 const int tot_lines = int(total_len / spacing);
230 const int tot_lines_half = (tot_lines / 2) + 1;
231 float spacing_dir[3], lines_start[3];
245 for (
int i = 0;
i < tot_lines_half;
i++) {
258 for (
int i = 1;
i < tot_lines_half;
i++) {
277 immVertexFormat(),
"pos", blender::gpu::VertAttrType::SFLOAT_32_32_32);
304 const int tot_lines = int(total_len / cd->
voxel_size);
309 const float x =
clamp_f((tot_lines - a) / (
b - a), 0.0f, 1.0);
310 const float alpha_factor = 1.0f - (
x *
x * (3.0f - 2.0f *
x));
322 float strwidth, strheight;
323 short fstyle_points = fstyle->
points;
325 short strdrawlen = 0;
337 BLF_size(fontid, 10.0f * fstyle_points);
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);
445 "Voxel Size Edit OP Custom Data");
461 const int BB_faces[6][4] = {
478 float current_normal[3];
479 float view_normal[3] = {0.0f, 0.0f, 1.0f};
483 active_object->object_to_world().ptr());
486 copy_m3_m4(mat, active_object->world_to_object().ptr());
492 float min_dot =
dot_v3v3(current_normal, view_normal);
493 float current_dot = 1;
496 for (
int i = 0;
i < 6;
i++) {
498 bounds_box[BB_faces[
i][0]],
499 bounds_box[BB_faces[
i][1]],
500 bounds_box[BB_faces[
i][2]]);
501 current_dot =
dot_v3v3(current_normal, view_normal);
503 if (current_dot < min_dot) {
504 min_dot = current_dot;
524 float scale_mat[4][4];
526 float d_a[3], d_b[3];
527 float d_a_proj[2], d_b_proj[2];
528 float preview_plane_proj[4][2];
529 const float y_axis_proj[2] = {0.0f, 1.0f};
534 for (
int i = 0;
i < 4;
i++) {
535 float preview_plane_world_space[3];
537 preview_plane_world_space, active_object->object_to_world().ptr(), cd->
preview_plane[
i]);
548 sub_v2_v2v2(d_a_proj, preview_plane_proj[1], preview_plane_proj[0]);
549 sub_v2_v2v2(d_b_proj, preview_plane_proj[3], preview_plane_proj[0]);
561 if (d_b_proj[0] < 0.0f) {
564 if (d_a_proj[1] < 0.0f) {
571 if (d_a_proj[0] < 0.0f) {
574 if (d_b_proj[1] < 0.0f) {
584 mat4_to_size(scale, active_object->object_to_world().ptr());
594 float text_pos_word_space[3];
595 mul_v3_m4v3(text_pos_word_space, active_object->object_to_world().ptr(), text_pos);
617 ot->name =
"Edit Voxel Size";
618 ot->description =
"Modify the mesh voxel size interactively used in the voxel remesher";
619 ot->idname =
"OBJECT_OT_voxel_size_edit";
636#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE 0.005f
691 bool is_manifold_consistent =
true;
699 for (
const int corner_i : corner_verts.
index_range()) {
700 const int vert = corner_verts[corner_i];
701 const int edge = corner_edges[corner_i];
702 edge_faces[edge] += 1;
703 if (edge_faces[edge] > 2) {
704 is_manifold_consistent =
false;
708 if (edge_vert[edge] == -1) {
709 edge_vert[edge] = vert;
711 else if (edge_vert[edge] == vert) {
713 is_manifold_consistent =
false;
718 if (is_manifold_consistent) {
721 if (edge_faces[
i] == 0) {
722 is_manifold_consistent =
false;
726 if (
compare_v3v3(positions[edges[
i][0]], positions[edges[
i][1]], 1e-4f)) {
727 is_manifold_consistent =
false;
736 return is_manifold_consistent;
754 bool should_break =
false;
757 bool should_break = (
G.is_break);
787 Mesh *mesh_bisect, *mesh_bisect_temp;
791 float plane_co[3], plane_no[3];
794 for (
char i = 0;
i < 3;
i++) {
796 if (symmetry_axes & symm_it) {
801 plane_no[axis] = -1.0f;
802 mesh_bisect_temp = mesh_bisect;
804 &mmd, mesh_bisect, axis, plane_co, plane_no);
805 if (mesh_bisect_temp != mesh_bisect) {
820 Mesh *mesh_mirror, *mesh_mirror_temp;
826 for (
char i = 0;
i < 3;
i++) {
828 if (symmetry_axes & symm_it) {
832 mesh_mirror_temp = mesh_mirror;
834 &mmd, ob, mesh_mirror, axis,
true,
nullptr,
nullptr);
835 if (mesh_mirror_temp != mesh_mirror) {
879#ifdef USE_MESH_CURVATURE
889 if (new_mesh ==
nullptr) {
891 worker_status->
stop =
false;
921 worker_status->
stop =
false;
951 "QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
952 "consistent direction");
973#ifdef USE_MESH_CURVATURE
985 for (
char i = 0;
i < 3;
i++) {
1016 "Remeshing with QuadriFlow...",
1050 faces_num = area / (edge_len * edge_len);
1060 faces_num =
mesh->faces_num * ratio;
1079 if (
STREQ(prop_id,
"target_faces")) {
1110 "Specify target number of faces relative to the current mesh"},
1115 "Input target edge length in the new mesh"},
1117 {0,
nullptr, 0,
nullptr,
nullptr},
1123 C, op, event,
IFACE_(
"QuadriFlow Remesh the Selected Mesh"),
IFACE_(
"Remesh"));
1129 ot->name =
"QuadriFlow Remesh";
1131 "Create a new quad based mesh using the surface data of the current mesh. All data "
1132 "layers will be lost";
1133 ot->idname =
"OBJECT_OT_quadriflow_remesh";
1148 "use_mesh_symmetry",
1150 "Use Mesh Symmetry",
1151 "Generates a symmetrical mesh using the mesh symmetry configuration");
1154 "use_preserve_sharp",
1157 "Try to preserve sharp features on the mesh");
1160 "use_preserve_boundary",
1162 "Preserve Mesh Boundary",
1163 "Try to preserve mesh boundary on the mesh");
1164#ifdef USE_MESH_CURVATURE
1166 "use_mesh_curvature",
1168 "Use Mesh Curvature",
1169 "Take the mesh curvature into account when remeshing");
1172 "preserve_attributes",
1174 "Preserve Attributes",
1175 "Reproject attributes onto the new mesh");
1181 "Set the output mesh normals to smooth");
1188 "How to specify the amount of detail for the new mesh");
1196 "Relative number of faces compared to the current mesh",
1201 "target_edge_length",
1206 "Target edge length in the new mesh",
1216 "Approximate number of faces (quads) in the new mesh",
1226 "Old Object Face Area",
1227 "This property is only used to cache the object area for later calculations",
1238 "Random seed to use with the solver. Different seeds will cause the remesher to "
1239 "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, bool process_shape_keys=true)
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_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)
#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_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_line_width(float width)
void GPU_line_smooth(bool enable)
void GPU_blend(GPUBlend blend)
Read Guarded memory(de)allocation.
const uiStyle * UI_style_get()
@ WM_JOB_TYPE_QUADRIFLOW_REMESH
constexpr IndexRange index_range() const
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)
void mesh_apply_spatial_organization(Mesh &mesh)
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
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 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)
@ QUADRIFLOW_REMESH_FACES
@ QUADRIFLOW_REMESH_RATIO
@ QUADRIFLOW_REMESH_EDGE_LENGTH
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
void WM_locked_interface_set(wmWindowManager *wm, bool lock)
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_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, std::optional< std::string > message)