1 /** \file blender/editors/sculpt_paint/paint_utils.c
8 #include "DNA_mesh_types.h"
9 #include "DNA_meshdata_types.h"
10 #include "DNA_object_types.h"
12 #include "DNA_scene_types.h"
13 #include "DNA_brush_types.h"
16 #include "BLI_utildefines.h"
18 #include "BKE_brush.h"
19 #include "BKE_context.h"
20 #include "BKE_DerivedMesh.h"
21 #include "BKE_paint.h"
23 #include "RNA_access.h"
24 #include "RNA_define.h"
27 /* TODO: remove once projectf goes away */
28 #include "BIF_glutil.h"
30 #include "RE_shader_ext.h"
32 #include "ED_view3d.h"
33 #include "ED_screen.h"
35 #include "BLO_sys_types.h"
36 #include "ED_mesh.h" /* for face mask functions */
41 #include "paint_intern.h"
43 /* convert a point in model coordinates to 2D screen coordinates */
44 /* TODO: can be deleted once all calls are replaced with
45 view3d_project_float() */
46 void projectf(bglMats *mats, const float v[3], float p[2])
50 gluProject(v[0],v[1],v[2], mats->modelview, mats->projection,
51 (GLint *)mats->viewport, &ux, &uy, &uz);
56 float paint_calc_object_space_radius(ViewContext *vc, float center[3],
59 Object *ob = vc->obact;
60 float delta[3], scale, loc[3];
62 mul_v3_m4v3(loc, ob->obmat, center);
64 initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
65 window_to_3d_delta(vc->ar, delta, pixel_radius, 0);
67 scale= fabsf(mat4_to_scale(ob->obmat));
68 scale= (scale == 0.0f)? 1.0f: scale;
70 return len_v3(delta)/scale;
73 float paint_get_tex_pixel(Brush* br, float u, float v)
83 memset(&texres, 0, sizeof(TexResult));
84 hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
87 texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta;
94 static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco)
99 mul_m4_v3(ob->obmat, pco);
100 mul_m4_v3((float(*)[4])model, pco);
101 mul_m4_v4((float(*)[4])proj, pco);
104 static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w)
106 float pv1[4], pv2[4], pv3[4], h[3], divw;
107 float model[16], proj[16], wmat[3][3], invwmat[3][3];
110 /* compute barycentric coordinates */
112 /* get the needed opengl matrices */
113 glGetIntegerv(GL_VIEWPORT, view);
114 glGetFloatv(GL_MODELVIEW_MATRIX, model);
115 glGetFloatv(GL_PROJECTION_MATRIX, proj);
116 view[0] = view[1] = 0;
118 /* project the verts */
119 imapaint_project(ob, model, proj, v1, pv1);
120 imapaint_project(ob, model, proj, v2, pv2);
121 imapaint_project(ob, model, proj, v3, pv3);
123 /* do inverse view mapping, see gluProject man page */
124 h[0]= (co[0] - view[0])*2.0f/view[2] - 1;
125 h[1]= (co[1] - view[1])*2.0f/view[3] - 1;
128 /* solve for(w1,w2,w3)/perspdiv in:
129 h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */
131 wmat[0][0]= pv1[0]; wmat[1][0]= pv2[0]; wmat[2][0]= pv3[0];
132 wmat[0][1]= pv1[1]; wmat[1][1]= pv2[1]; wmat[2][1]= pv3[1];
133 wmat[0][2]= pv1[3]; wmat[1][2]= pv2[3]; wmat[2][2]= pv3[3];
135 invert_m3_m3(invwmat, wmat);
136 mul_m3_v3(invwmat, h);
140 /* w is still divided by perspdiv, make it sum to one */
141 divw= w[0] + w[1] + w[2];
143 mul_v3_fl(w, 1.0f/divw);
146 /* compute uv coordinates of mouse in face */
147 void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, int *xy, float *uv)
149 DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
150 const int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
151 MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf;
152 int numfaces = dm->getNumTessFaces(dm), a, findex;
153 float p[2], w[3], absw, minabsw;
160 /* test all faces in the derivedmesh with the original index of the picked face */
161 for(a = 0; a < numfaces; a++) {
162 findex= index ? index[a]: a;
164 if(findex == faceindex) {
165 dm->getTessFace(dm, a, &mf);
167 dm->getVert(dm, mf.v1, &mv[0]);
168 dm->getVert(dm, mf.v2, &mv[1]);
169 dm->getVert(dm, mf.v3, &mv[2]);
171 dm->getVert(dm, mf.v4, &mv[3]);
179 /* the triangle with the largest absolute values is the one
180 with the most negative weights */
181 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w);
182 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
184 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2];
185 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2];
189 imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w);
190 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
192 uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2];
193 uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2];
198 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w);
199 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
201 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2];
202 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2];
212 ///* returns 0 if not found, otherwise 1 */
213 int imapaint_pick_face(ViewContext *vc, Mesh *me, int *mval, unsigned int *index)
215 if(!me || me->totface==0)
218 /* sample only on the exact position */
219 *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
221 if((*index)<=0 || (*index)>(unsigned int)me->totface)
229 /* used for both 3d view and image window */
230 void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf */
232 Brush *br = paint_brush(paint_get_active(scene));
236 CLAMP(x, 0, ar->winx);
237 CLAMP(y, 0, ar->winy);
239 glReadBuffer(GL_FRONT);
240 glReadPixels(x+ar->winrct.xmin, y+ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
241 glReadBuffer(GL_BACK);
246 br->rgb[0]= cp[0]/255.0f;
247 br->rgb[1]= cp[1]/255.0f;
248 br->rgb[2]= cp[2]/255.0f;
252 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
254 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
255 brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
257 return OPERATOR_FINISHED;
260 static int brush_curve_preset_poll(bContext *C)
262 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
264 return br && br->curve;
267 void BRUSH_OT_curve_preset(wmOperatorType *ot)
269 static EnumPropertyItem prop_shape_items[] = {
270 {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
271 {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
272 {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
273 {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
274 {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
275 {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
276 {0, NULL, 0, NULL, NULL}};
279 ot->description= "Set brush shape";
280 ot->idname= "BRUSH_OT_curve_preset";
282 ot->exec= brush_curve_preset_exec;
283 ot->poll= brush_curve_preset_poll;
285 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
287 RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
291 /* face-select ops */
292 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
294 paintface_select_linked(C, CTX_data_active_object(C), NULL, 2);
295 ED_region_tag_redraw(CTX_wm_region(C));
296 return OPERATOR_FINISHED;
299 void PAINT_OT_face_select_linked(wmOperatorType *ot)
301 ot->name= "Select Linked";
302 ot->description= "Select linked faces";
303 ot->idname= "PAINT_OT_face_select_linked";
305 ot->exec= paint_select_linked_exec;
306 ot->poll= facemask_paint_poll;
308 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
311 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
313 int mode= RNA_boolean_get(op->ptr, "extend") ? 1:0;
314 paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode);
315 ED_region_tag_redraw(CTX_wm_region(C));
316 return OPERATOR_FINISHED;
319 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
321 ot->name= "Select Linked Pick";
322 ot->description= "Select linked faces";
323 ot->idname= "PAINT_OT_face_select_linked_pick";
325 ot->invoke= paint_select_linked_pick_invoke;
326 ot->poll= facemask_paint_poll;
328 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
330 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
334 static int face_select_all_exec(bContext *C, wmOperator *op)
336 Object *ob= CTX_data_active_object(C);
337 paintface_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
338 ED_region_tag_redraw(CTX_wm_region(C));
339 return OPERATOR_FINISHED;
343 void PAINT_OT_face_select_all(wmOperatorType *ot)
345 ot->name= "Face Selection";
346 ot->description= "Change selection for all faces";
347 ot->idname= "PAINT_OT_face_select_all";
349 ot->exec= face_select_all_exec;
350 ot->poll= facemask_paint_poll;
352 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
354 WM_operator_properties_select_all(ot);
357 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
359 Object *ob= CTX_data_active_object(C);
360 paintface_deselect_all_visible(ob, SEL_INVERT, TRUE);
361 ED_region_tag_redraw(CTX_wm_region(C));
362 return OPERATOR_FINISHED;
366 void PAINT_OT_face_select_inverse(wmOperatorType *ot)
368 ot->name= "Face Select Invert";
369 ot->description= "Invert selection of faces";
370 ot->idname= "PAINT_OT_face_select_inverse";
372 ot->exec= face_select_inverse_exec;
373 ot->poll= facemask_paint_poll;
375 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
378 static int face_select_hide_exec(bContext *C, wmOperator *op)
380 const int unselected= RNA_boolean_get(op->ptr, "unselected");
381 Object *ob= CTX_data_active_object(C);
382 paintface_hide(ob, unselected);
383 ED_region_tag_redraw(CTX_wm_region(C));
384 return OPERATOR_FINISHED;
387 void PAINT_OT_face_select_hide(wmOperatorType *ot)
389 ot->name= "Face Select Hide";
390 ot->description= "Hide selected faces";
391 ot->idname= "PAINT_OT_face_select_hide";
393 ot->exec= face_select_hide_exec;
394 ot->poll= facemask_paint_poll;
396 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
398 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
401 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
403 Object *ob= CTX_data_active_object(C);
404 paintface_reveal(ob);
405 ED_region_tag_redraw(CTX_wm_region(C));
406 return OPERATOR_FINISHED;
409 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
411 ot->name= "Face Select Reveal";
412 ot->description= "Reveal hidden faces";
413 ot->idname= "PAINT_OT_face_select_reveal";
415 ot->exec= face_select_reveal_exec;
416 ot->poll= facemask_paint_poll;
418 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
420 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");