1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2020 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edsculpt
22 */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "BLI_blenlib.h"
27 #include "BLI_hash.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30
31 #include "BLT_translation.h"
32
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35
36 #include "BKE_brush.h"
37 #include "BKE_context.h"
38 #include "BKE_mesh.h"
39 #include "BKE_mesh_mapping.h"
40 #include "BKE_object.h"
41 #include "BKE_paint.h"
42 #include "BKE_pbvh.h"
43 #include "BKE_scene.h"
44 #include "BKE_screen.h"
45
46 #include "DEG_depsgraph.h"
47
48 #include "WM_api.h"
49 #include "WM_message.h"
50 #include "WM_toolsystem.h"
51 #include "WM_types.h"
52
53 #include "ED_object.h"
54 #include "ED_screen.h"
55 #include "ED_sculpt.h"
56 #include "ED_view3d.h"
57 #include "paint_intern.h"
58 #include "sculpt_intern.h"
59
60 #include "RNA_access.h"
61 #include "RNA_define.h"
62
63 #include "UI_interface.h"
64
65 #include "bmesh.h"
66
67 #include <math.h>
68 #include <stdlib.h>
69
70 typedef struct {
71 const float *ray_start;
72 bool hit;
73 float depth;
74 float edge_length;
75
76 struct IsectRayPrecalc isect_precalc;
77 } SculptDetailRaycastData;
78
sculpt_and_constant_or_manual_detail_poll(bContext * C)79 static bool sculpt_and_constant_or_manual_detail_poll(bContext *C)
80 {
81 Object *ob = CTX_data_active_object(C);
82 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
83
84 return SCULPT_mode_poll(C) && ob->sculpt->bm &&
85 (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL));
86 }
87
sculpt_and_dynamic_topology_poll(bContext * C)88 static bool sculpt_and_dynamic_topology_poll(bContext *C)
89 {
90 Object *ob = CTX_data_active_object(C);
91
92 return SCULPT_mode_poll(C) && ob->sculpt->bm;
93 }
94
sculpt_detail_flood_fill_exec(bContext * C,wmOperator * UNUSED (op))95 static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
96 {
97 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
98 Object *ob = CTX_data_active_object(C);
99 SculptSession *ss = ob->sculpt;
100 float size;
101 float bb_min[3], bb_max[3], center[3], dim[3];
102 int totnodes;
103 PBVHNode **nodes;
104
105 BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnodes);
106
107 if (!totnodes) {
108 return OPERATOR_CANCELLED;
109 }
110
111 for (int i = 0; i < totnodes; i++) {
112 BKE_pbvh_node_mark_topology_update(nodes[i]);
113 }
114 /* Get the bounding box, its center and size. */
115 BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
116 add_v3_v3v3(center, bb_min, bb_max);
117 mul_v3_fl(center, 0.5f);
118 sub_v3_v3v3(dim, bb_max, bb_min);
119 size = max_fff(dim[0], dim[1], dim[2]);
120
121 /* Update topology size. */
122 float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
123 BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
124
125 SCULPT_undo_push_begin("Dynamic topology flood fill");
126 SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
127
128 while (BKE_pbvh_bmesh_update_topology(
129 ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, NULL, size, false, false)) {
130 for (int i = 0; i < totnodes; i++) {
131 BKE_pbvh_node_mark_topology_update(nodes[i]);
132 }
133 }
134
135 MEM_SAFE_FREE(nodes);
136 SCULPT_undo_push_end();
137
138 /* Force rebuild of pbvh for better BB placement. */
139 SCULPT_pbvh_clear(ob);
140 /* Redraw. */
141 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
142
143 return OPERATOR_FINISHED;
144 }
145
SCULPT_OT_detail_flood_fill(wmOperatorType * ot)146 void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
147 {
148 /* Identifiers. */
149 ot->name = "Detail Flood Fill";
150 ot->idname = "SCULPT_OT_detail_flood_fill";
151 ot->description = "Flood fill the mesh with the selected detail setting";
152
153 /* API callbacks. */
154 ot->exec = sculpt_detail_flood_fill_exec;
155 ot->poll = sculpt_and_constant_or_manual_detail_poll;
156
157 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
158 }
159
160 typedef enum eSculptSampleDetailModeTypes {
161 SAMPLE_DETAIL_DYNTOPO = 0,
162 SAMPLE_DETAIL_VOXEL = 1,
163 } eSculptSampleDetailModeTypes;
164
165 static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = {
166 {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"},
167 {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"},
168 {0, NULL, 0, NULL, NULL},
169 };
170
sample_detail_voxel(bContext * C,ViewContext * vc,int mx,int my)171 static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
172 {
173 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
174 Object *ob = vc->obact;
175 Mesh *mesh = ob->data;
176
177 SculptSession *ss = ob->sculpt;
178 SculptCursorGeometryInfo sgi;
179 SCULPT_vertex_random_access_ensure(ss);
180
181 /* Update the active vertex. */
182 const float mouse[2] = {mx, my};
183 SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
184 BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
185
186 /* Average the edge length of the connected edges to the active vertex. */
187 int active_vertex = SCULPT_active_vertex_get(ss);
188 const float *active_vertex_co = SCULPT_active_vertex_co_get(ss);
189 float edge_length = 0.0f;
190 int tot = 0;
191 SculptVertexNeighborIter ni;
192 SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) {
193 edge_length += len_v3v3(active_vertex_co, SCULPT_vertex_co_get(ss, ni.index));
194 tot += 1;
195 }
196 SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
197 if (tot > 0) {
198 mesh->remesh_voxel_size = edge_length / (float)tot;
199 }
200 }
201
sculpt_raycast_detail_cb(PBVHNode * node,void * data_v,float * tmin)202 static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
203 {
204 if (BKE_pbvh_node_get_tmin(node) < *tmin) {
205 SculptDetailRaycastData *srd = data_v;
206 if (BKE_pbvh_bmesh_node_raycast_detail(
207 node, srd->ray_start, &srd->isect_precalc, &srd->depth, &srd->edge_length)) {
208 srd->hit = true;
209 *tmin = srd->depth;
210 }
211 }
212 }
213
sample_detail_dyntopo(bContext * C,ViewContext * vc,ARegion * region,int mx,int my)214 static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *region, int mx, int my)
215 {
216 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
217 Object *ob = vc->obact;
218 Brush *brush = BKE_paint_brush(&sd->paint);
219
220 SCULPT_stroke_modifiers_check(C, ob, brush);
221
222 const float mouse[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
223 float ray_start[3], ray_end[3], ray_normal[3];
224 float depth = SCULPT_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false);
225
226 SculptDetailRaycastData srd;
227 srd.hit = 0;
228 srd.ray_start = ray_start;
229 srd.depth = depth;
230 srd.edge_length = 0.0f;
231 isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
232
233 BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false);
234
235 if (srd.hit && srd.edge_length > 0.0f) {
236 /* Convert edge length to world space detail resolution. */
237 sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
238 }
239 }
240
sample_detail(bContext * C,int mx,int my,int mode)241 static int sample_detail(bContext *C, int mx, int my, int mode)
242 {
243 /* Find 3D view to pick from. */
244 bScreen *screen = CTX_wm_screen(C);
245 ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my);
246 ARegion *region = (area) ? BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my) : NULL;
247 if (region == NULL) {
248 return OPERATOR_CANCELLED;
249 }
250
251 /* Set context to 3D view. */
252 ScrArea *prev_area = CTX_wm_area(C);
253 ARegion *prev_region = CTX_wm_region(C);
254 CTX_wm_area_set(C, area);
255 CTX_wm_region_set(C, region);
256
257 Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
258 ViewContext vc;
259 ED_view3d_viewcontext_init(C, &vc, depsgraph);
260
261 Object *ob = vc.obact;
262 if (ob == NULL) {
263 return OPERATOR_CANCELLED;
264 }
265
266 SculptSession *ss = ob->sculpt;
267 if (!ss->pbvh) {
268 return OPERATOR_CANCELLED;
269 }
270
271 /* Pick sample detail. */
272 switch (mode) {
273 case SAMPLE_DETAIL_DYNTOPO:
274 if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
275 CTX_wm_area_set(C, prev_area);
276 CTX_wm_region_set(C, prev_region);
277 return OPERATOR_CANCELLED;
278 }
279 sample_detail_dyntopo(C, &vc, region, mx, my);
280 break;
281 case SAMPLE_DETAIL_VOXEL:
282 if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
283 CTX_wm_area_set(C, prev_area);
284 CTX_wm_region_set(C, prev_region);
285 return OPERATOR_CANCELLED;
286 }
287 sample_detail_voxel(C, &vc, mx, my);
288 break;
289 }
290
291 /* Restore context. */
292 CTX_wm_area_set(C, prev_area);
293 CTX_wm_region_set(C, prev_region);
294
295 return OPERATOR_FINISHED;
296 }
297
sculpt_sample_detail_size_exec(bContext * C,wmOperator * op)298 static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
299 {
300 int ss_co[2];
301 RNA_int_get_array(op->ptr, "location", ss_co);
302 int mode = RNA_enum_get(op->ptr, "mode");
303 return sample_detail(C, ss_co[0], ss_co[1], mode);
304 }
305
sculpt_sample_detail_size_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (e))306 static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
307 {
308 ED_workspace_status_text(C, TIP_("Click on the mesh to set the detail"));
309 WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER);
310 WM_event_add_modal_handler(C, op);
311 return OPERATOR_RUNNING_MODAL;
312 }
313
sculpt_sample_detail_size_modal(bContext * C,wmOperator * op,const wmEvent * event)314 static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wmEvent *event)
315 {
316 switch (event->type) {
317 case LEFTMOUSE:
318 if (event->val == KM_PRESS) {
319 const int ss_co[2] = {event->x, event->y};
320
321 int mode = RNA_enum_get(op->ptr, "mode");
322 sample_detail(C, ss_co[0], ss_co[1], mode);
323
324 RNA_int_set_array(op->ptr, "location", ss_co);
325 WM_cursor_modal_restore(CTX_wm_window(C));
326 ED_workspace_status_text(C, NULL);
327 WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
328
329 return OPERATOR_FINISHED;
330 }
331 break;
332 case EVT_ESCKEY:
333 case RIGHTMOUSE: {
334 WM_cursor_modal_restore(CTX_wm_window(C));
335 ED_workspace_status_text(C, NULL);
336
337 return OPERATOR_CANCELLED;
338 }
339 }
340
341 return OPERATOR_RUNNING_MODAL;
342 }
343
SCULPT_OT_sample_detail_size(wmOperatorType * ot)344 void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
345 {
346 /* Identifiers. */
347 ot->name = "Sample Detail Size";
348 ot->idname = "SCULPT_OT_sample_detail_size";
349 ot->description = "Sample the mesh detail on clicked point";
350
351 /* API callbacks. */
352 ot->invoke = sculpt_sample_detail_size_invoke;
353 ot->exec = sculpt_sample_detail_size_exec;
354 ot->modal = sculpt_sample_detail_size_modal;
355 ot->poll = SCULPT_mode_poll;
356
357 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
358
359 RNA_def_int_array(ot->srna,
360 "location",
361 2,
362 NULL,
363 0,
364 SHRT_MAX,
365 "Location",
366 "Screen Coordinates of sampling",
367 0,
368 SHRT_MAX);
369 RNA_def_enum(ot->srna,
370 "mode",
371 prop_sculpt_sample_detail_mode_types,
372 SAMPLE_DETAIL_DYNTOPO,
373 "Detail Mode",
374 "Target sculpting workflow that is going to use the sampled size");
375 }
376
377 /* Dynamic-topology detail size.
378 *
379 * This should be improved further, perhaps by showing a triangle
380 * grid rather than brush alpha. */
set_brush_rc_props(PointerRNA * ptr,const char * prop)381 static void set_brush_rc_props(PointerRNA *ptr, const char *prop)
382 {
383 char *path = BLI_sprintfN("tool_settings.sculpt.brush.%s", prop);
384 RNA_string_set(ptr, "data_path_primary", path);
385 MEM_freeN(path);
386 }
387
sculpt_set_detail_size_exec(bContext * C,wmOperator * UNUSED (op))388 static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
389 {
390 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
391
392 PointerRNA props_ptr;
393 wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
394
395 WM_operator_properties_create_ptr(&props_ptr, ot);
396
397 if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
398 set_brush_rc_props(&props_ptr, "constant_detail_resolution");
399 RNA_string_set(
400 &props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail_resolution");
401 }
402 else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
403 set_brush_rc_props(&props_ptr, "constant_detail_resolution");
404 RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
405 }
406 else {
407 set_brush_rc_props(&props_ptr, "detail_size");
408 RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
409 }
410
411 WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
412
413 WM_operator_properties_free(&props_ptr);
414
415 return OPERATOR_FINISHED;
416 }
417
SCULPT_OT_set_detail_size(wmOperatorType * ot)418 void SCULPT_OT_set_detail_size(wmOperatorType *ot)
419 {
420 /* Identifiers. */
421 ot->name = "Set Detail Size";
422 ot->idname = "SCULPT_OT_set_detail_size";
423 ot->description =
424 "Set the mesh detail (either relative or constant one, depending on current dyntopo mode)";
425
426 /* API callbacks. */
427 ot->exec = sculpt_set_detail_size_exec;
428 ot->poll = sculpt_and_dynamic_topology_poll;
429
430 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
431 }
432