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];
63 mul_v3_m4v3(loc, ob->obmat, center);
65 initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
67 mval_f[0]= pixel_radius;
69 ED_view3d_win_to_delta(vc->ar, mval_f, delta);
71 scale= fabsf(mat4_to_scale(ob->obmat));
72 scale= (scale == 0.0f)? 1.0f: scale;
74 return len_v3(delta)/scale;
77 float paint_get_tex_pixel(Brush* br, float u, float v)
87 memset(&texres, 0, sizeof(TexResult));
88 hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
91 texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta;
98 static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco)
103 mul_m4_v3(ob->obmat, pco);
104 mul_m4_v3((float(*)[4])model, pco);
105 mul_m4_v4((float(*)[4])proj, pco);
108 static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w)
110 float pv1[4], pv2[4], pv3[4], h[3], divw;
111 float model[16], proj[16], wmat[3][3], invwmat[3][3];
114 /* compute barycentric coordinates */
116 /* get the needed opengl matrices */
117 glGetIntegerv(GL_VIEWPORT, view);
118 glGetFloatv(GL_MODELVIEW_MATRIX, model);
119 glGetFloatv(GL_PROJECTION_MATRIX, proj);
120 view[0] = view[1] = 0;
122 /* project the verts */
123 imapaint_project(ob, model, proj, v1, pv1);
124 imapaint_project(ob, model, proj, v2, pv2);
125 imapaint_project(ob, model, proj, v3, pv3);
127 /* do inverse view mapping, see gluProject man page */
128 h[0]= (co[0] - view[0])*2.0f/view[2] - 1;
129 h[1]= (co[1] - view[1])*2.0f/view[3] - 1;
132 /* solve for(w1,w2,w3)/perspdiv in:
133 h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */
135 wmat[0][0]= pv1[0]; wmat[1][0]= pv2[0]; wmat[2][0]= pv3[0];
136 wmat[0][1]= pv1[1]; wmat[1][1]= pv2[1]; wmat[2][1]= pv3[1];
137 wmat[0][2]= pv1[3]; wmat[1][2]= pv2[3]; wmat[2][2]= pv3[3];
139 invert_m3_m3(invwmat, wmat);
140 mul_m3_v3(invwmat, h);
144 /* w is still divided by perspdiv, make it sum to one */
145 divw= w[0] + w[1] + w[2];
147 mul_v3_fl(w, 1.0f/divw);
150 /* compute uv coordinates of mouse in face */
151 void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
153 DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
154 const int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
155 MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf;
156 int numfaces = dm->getNumFaces(dm), a, findex;
157 float p[2], w[3], absw, minabsw;
164 /* test all faces in the derivedmesh with the original index of the picked face */
165 for(a = 0; a < numfaces; a++) {
166 findex= index ? index[a]: a;
168 if(findex == faceindex) {
169 dm->getFace(dm, a, &mf);
171 dm->getVert(dm, mf.v1, &mv[0]);
172 dm->getVert(dm, mf.v2, &mv[1]);
173 dm->getVert(dm, mf.v3, &mv[2]);
175 dm->getVert(dm, mf.v4, &mv[3]);
183 /* the triangle with the largest absolute values is the one
184 with the most negative weights */
185 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w);
186 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
188 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2];
189 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2];
193 imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w);
194 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
196 uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2];
197 uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2];
202 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w);
203 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
205 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2];
206 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2];
216 ///* returns 0 if not found, otherwise 1 */
217 int imapaint_pick_face(ViewContext *vc, Mesh *me, const int mval[2], unsigned int *index)
219 if(!me || me->totface==0)
222 /* sample only on the exact position */
223 *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
225 if((*index)<=0 || (*index)>(unsigned int)me->totface)
233 /* used for both 3d view and image window */
234 void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf */
236 Brush *br = paint_brush(paint_get_active(scene));
240 CLAMP(x, 0, ar->winx);
241 CLAMP(y, 0, ar->winy);
243 glReadBuffer(GL_FRONT);
244 glReadPixels(x+ar->winrct.xmin, y+ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
245 glReadBuffer(GL_BACK);
250 br->rgb[0]= cp[0]/255.0f;
251 br->rgb[1]= cp[1]/255.0f;
252 br->rgb[2]= cp[2]/255.0f;
256 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
258 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
259 brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
261 return OPERATOR_FINISHED;
264 static int brush_curve_preset_poll(bContext *C)
266 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
268 return br && br->curve;
271 void BRUSH_OT_curve_preset(wmOperatorType *ot)
273 static EnumPropertyItem prop_shape_items[] = {
274 {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
275 {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
276 {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
277 {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
278 {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
279 {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
280 {0, NULL, 0, NULL, NULL}};
283 ot->description= "Set brush shape";
284 ot->idname= "BRUSH_OT_curve_preset";
286 ot->exec= brush_curve_preset_exec;
287 ot->poll= brush_curve_preset_poll;
289 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
291 RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
295 /* face-select ops */
296 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
298 paintface_select_linked(C, CTX_data_active_object(C), NULL, 2);
299 ED_region_tag_redraw(CTX_wm_region(C));
300 return OPERATOR_FINISHED;
303 void PAINT_OT_face_select_linked(wmOperatorType *ot)
305 ot->name= "Select Linked";
306 ot->description= "Select linked faces";
307 ot->idname= "PAINT_OT_face_select_linked";
309 ot->exec= paint_select_linked_exec;
310 ot->poll= facemask_paint_poll;
312 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
315 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
317 int mode= RNA_boolean_get(op->ptr, "extend") ? 1:0;
318 paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode);
319 ED_region_tag_redraw(CTX_wm_region(C));
320 return OPERATOR_FINISHED;
323 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
325 ot->name= "Select Linked Pick";
326 ot->description= "Select linked faces";
327 ot->idname= "PAINT_OT_face_select_linked_pick";
329 ot->invoke= paint_select_linked_pick_invoke;
330 ot->poll= facemask_paint_poll;
332 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
334 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
338 static int face_select_all_exec(bContext *C, wmOperator *op)
340 Object *ob= CTX_data_active_object(C);
341 paintface_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
342 ED_region_tag_redraw(CTX_wm_region(C));
343 return OPERATOR_FINISHED;
347 void PAINT_OT_face_select_all(wmOperatorType *ot)
349 ot->name= "Face Selection";
350 ot->description= "Change selection for all faces";
351 ot->idname= "PAINT_OT_face_select_all";
353 ot->exec= face_select_all_exec;
354 ot->poll= facemask_paint_poll;
356 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
358 WM_operator_properties_select_all(ot);
362 static int vert_select_all_exec(bContext *C, wmOperator *op)
364 Object *ob= CTX_data_active_object(C);
365 paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
366 ED_region_tag_redraw(CTX_wm_region(C));
367 return OPERATOR_FINISHED;
371 void PAINT_OT_vert_select_all(wmOperatorType *ot)
373 ot->name= "Vertex Selection";
374 ot->description= "Change selection for all vertices";
375 ot->idname= "PAINT_OT_vert_select_all";
377 ot->exec= vert_select_all_exec;
378 ot->poll= vert_paint_poll;
380 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
382 WM_operator_properties_select_all(ot);
385 static int vert_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
387 Object *ob= CTX_data_active_object(C);
388 paintvert_deselect_all_visible(ob, SEL_INVERT, TRUE);
389 ED_region_tag_redraw(CTX_wm_region(C));
390 return OPERATOR_FINISHED;
393 void PAINT_OT_vert_select_inverse(wmOperatorType *ot)
395 ot->name= "Vertex Select Invert";
396 ot->description= "Invert selection of vertices";
397 ot->idname= "PAINT_OT_vert_select_inverse";
399 ot->exec= vert_select_inverse_exec;
400 ot->poll= vert_paint_poll;
402 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
404 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
406 Object *ob= CTX_data_active_object(C);
407 paintface_deselect_all_visible(ob, SEL_INVERT, TRUE);
408 ED_region_tag_redraw(CTX_wm_region(C));
409 return OPERATOR_FINISHED;
413 void PAINT_OT_face_select_inverse(wmOperatorType *ot)
415 ot->name= "Face Select Invert";
416 ot->description= "Invert selection of faces";
417 ot->idname= "PAINT_OT_face_select_inverse";
419 ot->exec= face_select_inverse_exec;
420 ot->poll= facemask_paint_poll;
422 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
425 static int face_select_hide_exec(bContext *C, wmOperator *op)
427 const int unselected= RNA_boolean_get(op->ptr, "unselected");
428 Object *ob= CTX_data_active_object(C);
429 paintface_hide(ob, unselected);
430 ED_region_tag_redraw(CTX_wm_region(C));
431 return OPERATOR_FINISHED;
434 void PAINT_OT_face_select_hide(wmOperatorType *ot)
436 ot->name= "Face Select Hide";
437 ot->description= "Hide selected faces";
438 ot->idname= "PAINT_OT_face_select_hide";
440 ot->exec= face_select_hide_exec;
441 ot->poll= facemask_paint_poll;
443 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
445 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
448 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
450 Object *ob= CTX_data_active_object(C);
451 paintface_reveal(ob);
452 ED_region_tag_redraw(CTX_wm_region(C));
453 return OPERATOR_FINISHED;
456 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
458 ot->name= "Face Select Reveal";
459 ot->description= "Reveal hidden faces";
460 ot->idname= "PAINT_OT_face_select_reveal";
462 ot->exec= face_select_reveal_exec;
463 ot->poll= facemask_paint_poll;
465 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
467 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");