2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/sculpt_paint/paint_utils.c
35 #include "DNA_mesh_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_brush_types.h"
43 #include "BLI_utildefines.h"
46 #include "BKE_brush.h"
47 #include "BKE_context.h"
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_paint.h"
51 #include "RNA_access.h"
52 #include "RNA_define.h"
55 /* TODO: remove once projectf goes away */
56 #include "BIF_glutil.h"
58 #include "RE_shader_ext.h"
60 #include "ED_view3d.h"
61 #include "ED_screen.h"
63 #include "BLO_sys_types.h"
64 #include "ED_mesh.h" /* for face mask functions */
69 #include "paint_intern.h"
71 /* Convert the object-space axis-aligned bounding box (expressed as
72 * its minimum and maximum corners) into a screen-space rectangle,
73 * returns zero if the result is empty */
74 int paint_convert_bb_to_rect(rcti *rect,
75 const float bb_min[3],
76 const float bb_max[3],
81 float projection_mat[4][4];
84 BLI_rcti_init_minmax(rect);
86 /* return zero if the bounding box has non-positive volume */
87 if (bb_min[0] > bb_max[0] || bb_min[1] > bb_max[1] || bb_min[2] > bb_max[2])
90 ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);
92 for (i = 0; i < 2; ++i) {
93 for (j = 0; j < 2; ++j) {
94 for (k = 0; k < 2; ++k) {
95 float vec[3], proj[2];
97 vec[0] = i ? bb_min[0] : bb_max[0];
98 vec[1] = j ? bb_min[1] : bb_max[1];
99 vec[2] = k ? bb_min[2] : bb_max[2];
100 /* convert corner to screen space */
101 ED_view3d_project_float_v2(ar, vec, proj, projection_mat);
102 /* expand 2D rectangle */
104 /* we could project directly to int? */
108 BLI_rcti_do_minmax_v(rect, proj_i);
113 /* return false if the rectangle has non-positive area */
114 return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
117 /* Get four planes in object-space that describe the projection of
118 * screen_rect from screen into object-space (essentially converting a
119 * 2D screens-space bounding box into four 3D planes) */
120 void paint_calc_redraw_planes(float planes[4][4],
124 const rcti *screen_rect)
130 memset(&bb, 0, sizeof(BoundBox));
131 view3d_get_transformation(ar, rv3d, ob, &mats);
133 /* use some extra space just in case */
140 ED_view3d_calc_clipping(&bb, planes, &mats, &rect);
141 mul_m4_fl(planes, -1.0f);
144 /* convert a point in model coordinates to 2D screen coordinates */
145 /* TODO: can be deleted once all calls are replaced with
146 * view3d_project_float() */
147 void projectf(bglMats *mats, const float v[3], float p[2])
151 gluProject(v[0], v[1], v[2], mats->modelview, mats->projection,
152 (GLint *)mats->viewport, &ux, &uy, &uz);
157 float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
160 Object *ob = vc->obact;
161 float delta[3], scale, loc[3];
164 mul_v3_m4v3(loc, ob->obmat, center);
166 initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
168 mval_f[0] = pixel_radius;
170 ED_view3d_win_to_delta(vc->ar, mval_f, delta);
172 scale = fabsf(mat4_to_scale(ob->obmat));
173 scale = (scale == 0.0f) ? 1.0f : scale;
175 return len_v3(delta) / scale;
178 float paint_get_tex_pixel(Brush *br, float u, float v)
180 TexResult texres = {0};
181 float co[3] = {u, v, 0.0f};
184 hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
186 if (hasrgb & TEX_RGB)
187 texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta;
194 static void imapaint_project(Object *ob, float model[][4], float proj[][4], const float co[3], float pco[4])
199 mul_m4_v3(ob->obmat, pco);
200 mul_m4_v3(model, pco);
201 mul_m4_v4(proj, pco);
204 static void imapaint_tri_weights(Object *ob,
205 const float v1[3], const float v2[3], const float v3[3],
206 const float co[3], float w[3])
208 float pv1[4], pv2[4], pv3[4], h[3], divw;
209 float model[4][4], proj[4][4], wmat[3][3], invwmat[3][3];
212 /* compute barycentric coordinates */
214 /* get the needed opengl matrices */
215 glGetIntegerv(GL_VIEWPORT, view);
216 glGetFloatv(GL_MODELVIEW_MATRIX, (float *)model);
217 glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
218 view[0] = view[1] = 0;
220 /* project the verts */
221 imapaint_project(ob, model, proj, v1, pv1);
222 imapaint_project(ob, model, proj, v2, pv2);
223 imapaint_project(ob, model, proj, v3, pv3);
225 /* do inverse view mapping, see gluProject man page */
226 h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1;
227 h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1;
230 /* solve for (w1,w2,w3)/perspdiv in:
231 * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
233 wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0];
234 wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1];
235 wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3];
237 invert_m3_m3(invwmat, wmat);
238 mul_m3_v3(invwmat, h);
242 /* w is still divided by perspdiv, make it sum to one */
243 divw = w[0] + w[1] + w[2];
245 mul_v3_fl(w, 1.0f / divw);
249 /* compute uv coordinates of mouse in face */
250 void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
252 DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
253 const int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
254 MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf;
255 int numfaces = dm->getNumTessFaces(dm), a, findex;
256 float p[2], w[3], absw, minabsw;
263 /* test all faces in the derivedmesh with the original index of the picked face */
264 for (a = 0; a < numfaces; a++) {
265 findex = index ? index[a] : a;
267 if (findex == faceindex) {
268 dm->getTessFace(dm, a, &mf);
270 dm->getVert(dm, mf.v1, &mv[0]);
271 dm->getVert(dm, mf.v2, &mv[1]);
272 dm->getVert(dm, mf.v3, &mv[2]);
274 dm->getVert(dm, mf.v4, &mv[3]);
282 /* the triangle with the largest absolute values is the one
283 * with the most negative weights */
284 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w);
285 absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
286 if (absw < minabsw) {
287 uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2];
288 uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2];
292 imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w);
293 absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
294 if (absw < minabsw) {
295 uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2];
296 uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2];
301 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w);
302 absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
303 if (absw < minabsw) {
304 uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2];
305 uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2];
315 /* returns 0 if not found, otherwise 1 */
316 int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface)
321 /* sample only on the exact position */
322 *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
324 if ((*index) <= 0 || (*index) > (unsigned int)totface) {
333 /* used for both 3d view and image window */
334 void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */
336 Brush *br = paint_brush(paint_get_active_from_context(C));
340 CLAMP(x, 0, ar->winx);
341 CLAMP(y, 0, ar->winy);
343 glReadBuffer(GL_FRONT);
344 glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
345 glReadBuffer(GL_BACK);
350 br->rgb[0] = cp[0] / 255.0f;
351 br->rgb[1] = cp[1] / 255.0f;
352 br->rgb[2] = cp[2] / 255.0f;
356 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
358 Brush *br = paint_brush(paint_get_active_from_context(C));
359 BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
361 return OPERATOR_FINISHED;
364 static int brush_curve_preset_poll(bContext *C)
366 Brush *br = paint_brush(paint_get_active_from_context(C));
368 return br && br->curve;
371 void BRUSH_OT_curve_preset(wmOperatorType *ot)
373 static EnumPropertyItem prop_shape_items[] = {
374 {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
375 {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
376 {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
377 {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
378 {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
379 {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
380 {0, NULL, 0, NULL, NULL}};
383 ot->description = "Set brush shape";
384 ot->idname = "BRUSH_OT_curve_preset";
386 ot->exec = brush_curve_preset_exec;
387 ot->poll = brush_curve_preset_poll;
389 RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
393 /* face-select ops */
394 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
396 paintface_select_linked(C, CTX_data_active_object(C), NULL, 2);
397 ED_region_tag_redraw(CTX_wm_region(C));
398 return OPERATOR_FINISHED;
401 void PAINT_OT_face_select_linked(wmOperatorType *ot)
403 ot->name = "Select Linked";
404 ot->description = "Select linked faces";
405 ot->idname = "PAINT_OT_face_select_linked";
407 ot->exec = paint_select_linked_exec;
408 ot->poll = facemask_paint_poll;
410 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
413 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
415 int mode = RNA_boolean_get(op->ptr, "extend") ? 1 : 0;
416 paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode);
417 ED_region_tag_redraw(CTX_wm_region(C));
418 return OPERATOR_FINISHED;
421 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
423 ot->name = "Select Linked Pick";
424 ot->description = "Select linked faces";
425 ot->idname = "PAINT_OT_face_select_linked_pick";
427 ot->invoke = paint_select_linked_pick_invoke;
428 ot->poll = facemask_paint_poll;
430 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
432 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
436 static int face_select_all_exec(bContext *C, wmOperator *op)
438 Object *ob = CTX_data_active_object(C);
439 paintface_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
440 ED_region_tag_redraw(CTX_wm_region(C));
441 return OPERATOR_FINISHED;
445 void PAINT_OT_face_select_all(wmOperatorType *ot)
447 ot->name = "Face Selection";
448 ot->description = "Change selection for all faces";
449 ot->idname = "PAINT_OT_face_select_all";
451 ot->exec = face_select_all_exec;
452 ot->poll = facemask_paint_poll;
454 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
456 WM_operator_properties_select_all(ot);
460 static int vert_select_all_exec(bContext *C, wmOperator *op)
462 Object *ob = CTX_data_active_object(C);
463 paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
464 ED_region_tag_redraw(CTX_wm_region(C));
465 return OPERATOR_FINISHED;
469 void PAINT_OT_vert_select_all(wmOperatorType *ot)
471 ot->name = "Vertex Selection";
472 ot->description = "Change selection for all vertices";
473 ot->idname = "PAINT_OT_vert_select_all";
475 ot->exec = vert_select_all_exec;
476 ot->poll = vert_paint_poll;
478 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
480 WM_operator_properties_select_all(ot);
483 static int vert_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
485 Object *ob = CTX_data_active_object(C);
486 paintvert_deselect_all_visible(ob, SEL_INVERT, TRUE);
487 ED_region_tag_redraw(CTX_wm_region(C));
488 return OPERATOR_FINISHED;
491 void PAINT_OT_vert_select_inverse(wmOperatorType *ot)
493 ot->name = "Vertex Select Invert";
494 ot->description = "Invert selection of vertices";
495 ot->idname = "PAINT_OT_vert_select_inverse";
497 ot->exec = vert_select_inverse_exec;
498 ot->poll = vert_paint_poll;
500 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
502 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
504 Object *ob = CTX_data_active_object(C);
505 paintface_deselect_all_visible(ob, SEL_INVERT, TRUE);
506 ED_region_tag_redraw(CTX_wm_region(C));
507 return OPERATOR_FINISHED;
511 void PAINT_OT_face_select_inverse(wmOperatorType *ot)
513 ot->name = "Face Select Invert";
514 ot->description = "Invert selection of faces";
515 ot->idname = "PAINT_OT_face_select_inverse";
517 ot->exec = face_select_inverse_exec;
518 ot->poll = facemask_paint_poll;
520 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
523 static int face_select_hide_exec(bContext *C, wmOperator *op)
525 const int unselected = RNA_boolean_get(op->ptr, "unselected");
526 Object *ob = CTX_data_active_object(C);
527 paintface_hide(ob, unselected);
528 ED_region_tag_redraw(CTX_wm_region(C));
529 return OPERATOR_FINISHED;
532 void PAINT_OT_face_select_hide(wmOperatorType *ot)
534 ot->name = "Face Select Hide";
535 ot->description = "Hide selected faces";
536 ot->idname = "PAINT_OT_face_select_hide";
538 ot->exec = face_select_hide_exec;
539 ot->poll = facemask_paint_poll;
541 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
543 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
546 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
548 Object *ob = CTX_data_active_object(C);
549 paintface_reveal(ob);
550 ED_region_tag_redraw(CTX_wm_region(C));
551 return OPERATOR_FINISHED;
554 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
556 ot->name = "Face Select Reveal";
557 ot->description = "Reveal hidden faces";
558 ot->idname = "PAINT_OT_face_select_reveal";
560 ot->exec = face_select_reveal_exec;
561 ot->poll = facemask_paint_poll;
563 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
565 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");