e76d21a9eec51038d2bb719cfa283ade3acab132
[blender.git] / source / blender / editors / sculpt_paint / paint_utils.c
1 /** \file blender/editors/sculpt_paint/paint_utils.c
2  *  \ingroup edsculpt
3  */
4
5 #include <math.h>
6 #include <stdlib.h>
7
8 #include "DNA_mesh_types.h"
9 #include "DNA_meshdata_types.h"
10 #include "DNA_object_types.h"
11
12 #include "DNA_scene_types.h"
13 #include "DNA_brush_types.h"
14
15 #include "BLI_math.h"
16 #include "BLI_utildefines.h"
17
18 #include "BKE_brush.h"
19 #include "BKE_context.h"
20 #include "BKE_DerivedMesh.h"
21 #include "BKE_paint.h"
22
23 #include "RNA_access.h"
24 #include "RNA_define.h"
25
26 #include "BIF_gl.h"
27 /* TODO: remove once projectf goes away */
28 #include "BIF_glutil.h"
29
30 #include "RE_shader_ext.h"
31
32 #include "ED_view3d.h"
33 #include "ED_screen.h"
34
35 #include "BLO_sys_types.h"
36 #include "ED_mesh.h" /* for face mask functions */
37
38 #include "WM_api.h"
39 #include "WM_types.h"
40
41 #include "paint_intern.h"
42
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])
47 {
48         double ux, uy, uz;
49
50         gluProject(v[0],v[1],v[2], mats->modelview, mats->projection,
51                    (GLint *)mats->viewport, &ux, &uy, &uz);
52         p[0]= ux;
53         p[1]= uy;
54 }
55
56 float paint_calc_object_space_radius(ViewContext *vc, float center[3],
57                                      float pixel_radius)
58 {
59         Object *ob = vc->obact;
60         float delta[3], scale, loc[3];
61         float mval_f[2];
62
63         mul_v3_m4v3(loc, ob->obmat, center);
64
65         initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
66
67         mval_f[0]= pixel_radius;
68         mval_f[1]= 0.0f;
69         ED_view3d_win_to_delta(vc->ar, mval_f, delta);
70
71         scale= fabsf(mat4_to_scale(ob->obmat));
72         scale= (scale == 0.0f)? 1.0f: scale;
73
74         return len_v3(delta)/scale;
75 }
76
77 float paint_get_tex_pixel(Brush* br, float u, float v)
78 {
79         TexResult texres;
80         float co[3];
81         int hasrgb;
82
83         co[0] = u;
84         co[1] = v;
85         co[2] = 0;
86
87         memset(&texres, 0, sizeof(TexResult));
88         hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
89
90         if (hasrgb & TEX_RGB)
91                 texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta;
92
93         return texres.tin;
94 }
95
96 /* 3D Paint */
97
98 static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco)
99 {
100         VECCOPY(pco, co);
101         pco[3]= 1.0f;
102
103         mul_m4_v3(ob->obmat, pco);
104         mul_m4_v3((float(*)[4])model, pco);
105         mul_m4_v4((float(*)[4])proj, pco);
106 }
107
108 static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w)
109 {
110         float pv1[4], pv2[4], pv3[4], h[3], divw;
111         float model[16], proj[16], wmat[3][3], invwmat[3][3];
112         GLint view[4];
113
114         /* compute barycentric coordinates */
115
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;
121
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);
126
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;
130         h[2]= 1.0f;
131
132         /* solve for(w1,w2,w3)/perspdiv in:
133            h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */
134
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];
138
139         invert_m3_m3(invwmat, wmat);
140         mul_m3_v3(invwmat, h);
141
142         VECCOPY(w, h);
143
144         /* w is still divided by perspdiv, make it sum to one */
145         divw= w[0] + w[1] + w[2];
146         if(divw != 0.0f)
147                 mul_v3_fl(w, 1.0f/divw);
148 }
149
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])
152 {
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;
158         MFace mf;
159         MVert mv[4];
160
161         minabsw = 1e10;
162         uv[0] = uv[1] = 0.0;
163
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;
167
168                 if(findex == faceindex) {
169                         dm->getFace(dm, a, &mf);
170
171                         dm->getVert(dm, mf.v1, &mv[0]);
172                         dm->getVert(dm, mf.v2, &mv[1]);
173                         dm->getVert(dm, mf.v3, &mv[2]);
174                         if(mf.v4)
175                                 dm->getVert(dm, mf.v4, &mv[3]);
176
177                         tf= &tface[a];
178
179                         p[0]= xy[0];
180                         p[1]= xy[1];
181
182                         if(mf.v4) {
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]);
187                                 if(absw < minabsw) {
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];
190                                         minabsw = absw;
191                                 }
192
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]);
195                                 if(absw < minabsw) {
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];
198                                         minabsw = absw;
199                                 }
200                         }
201                         else {
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]);
204                                 if(absw < minabsw) {
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];
207                                         minabsw = absw;
208                                 }
209                         }
210                 }
211         }
212
213         dm->release(dm);
214 }
215
216 ///* returns 0 if not found, otherwise 1 */
217 int imapaint_pick_face(ViewContext *vc, Mesh *me, const int mval[2], unsigned int *index)
218 {
219         if(!me || me->totface==0)
220                 return 0;
221
222         /* sample only on the exact position */
223         *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
224
225         if((*index)<=0 || (*index)>(unsigned int)me->totface)
226                 return 0;
227
228         (*index)--;
229         
230         return 1;
231 }
232
233 /* used for both 3d view and image window */
234 void paint_sample_color(Scene *scene, ARegion *ar, int x, int y)        /* frontbuf */
235 {
236         Brush *br = paint_brush(paint_get_active(scene));
237         unsigned int col;
238         char *cp;
239
240         CLAMP(x, 0, ar->winx);
241         CLAMP(y, 0, ar->winy);
242         
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);
246
247         cp = (char *)&col;
248         
249         if(br) {
250                 br->rgb[0]= cp[0]/255.0f;
251                 br->rgb[1]= cp[1]/255.0f;
252                 br->rgb[2]= cp[2]/255.0f;
253         }
254 }
255
256 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
257 {
258         Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
259         brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
260
261         return OPERATOR_FINISHED;
262 }
263
264 static int brush_curve_preset_poll(bContext *C)
265 {
266         Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
267
268         return br && br->curve;
269 }
270
271 void BRUSH_OT_curve_preset(wmOperatorType *ot)
272 {
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}};
281
282         ot->name= "Preset";
283         ot->description= "Set brush shape";
284         ot->idname= "BRUSH_OT_curve_preset";
285
286         ot->exec= brush_curve_preset_exec;
287         ot->poll= brush_curve_preset_poll;
288
289         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
290
291         RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
292 }
293
294
295 /* face-select ops */
296 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
297 {
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;
301 }
302
303 void PAINT_OT_face_select_linked(wmOperatorType *ot)
304 {
305         ot->name= "Select Linked";
306         ot->description= "Select linked faces";
307         ot->idname= "PAINT_OT_face_select_linked";
308
309         ot->exec= paint_select_linked_exec;
310         ot->poll= facemask_paint_poll;
311
312         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
313 }
314
315 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
316 {
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;
321 }
322
323 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
324 {
325         ot->name= "Select Linked Pick";
326         ot->description= "Select linked faces";
327         ot->idname= "PAINT_OT_face_select_linked_pick";
328
329         ot->invoke= paint_select_linked_pick_invoke;
330         ot->poll= facemask_paint_poll;
331
332         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
333
334         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
335 }
336
337
338 static int face_select_all_exec(bContext *C, wmOperator *op)
339 {
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;
344 }
345
346
347 void PAINT_OT_face_select_all(wmOperatorType *ot)
348 {
349         ot->name= "Face Selection";
350         ot->description= "Change selection for all faces";
351         ot->idname= "PAINT_OT_face_select_all";
352
353         ot->exec= face_select_all_exec;
354         ot->poll= facemask_paint_poll;
355
356         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
357
358         WM_operator_properties_select_all(ot);
359 }
360
361 /* Radish */
362 static int vert_select_all_exec(bContext *C, wmOperator *op)
363 {
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;
368 }
369
370 /* Radish */
371 void PAINT_OT_vert_select_all(wmOperatorType *ot)
372 {
373         ot->name= "Vertex Selection";
374         ot->description= "Change selection for all vertices";
375         ot->idname= "PAINT_OT_vert_select_all";
376
377         ot->exec= vert_select_all_exec;
378         ot->poll= vert_paint_poll;
379
380         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
381
382         WM_operator_properties_select_all(ot);
383 }
384 /* Radish */
385 static int vert_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
386 {
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;
391 }
392 /* Radish */
393 void PAINT_OT_vert_select_inverse(wmOperatorType *ot)
394 {
395         ot->name= "Vertex Select Invert";
396         ot->description= "Invert selection of vertices";
397         ot->idname= "PAINT_OT_vert_select_inverse";
398
399         ot->exec= vert_select_inverse_exec;
400         ot->poll= vert_paint_poll;
401
402         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
403 }
404 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
405 {
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;
410 }
411
412
413 void PAINT_OT_face_select_inverse(wmOperatorType *ot)
414 {
415         ot->name= "Face Select Invert";
416         ot->description= "Invert selection of faces";
417         ot->idname= "PAINT_OT_face_select_inverse";
418
419         ot->exec= face_select_inverse_exec;
420         ot->poll= facemask_paint_poll;
421
422         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
423 }
424
425 static int face_select_hide_exec(bContext *C, wmOperator *op)
426 {
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;
432 }
433
434 void PAINT_OT_face_select_hide(wmOperatorType *ot)
435 {
436         ot->name= "Face Select Hide";
437         ot->description= "Hide selected faces";
438         ot->idname= "PAINT_OT_face_select_hide";
439
440         ot->exec= face_select_hide_exec;
441         ot->poll= facemask_paint_poll;
442
443         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
444
445         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
446 }
447
448 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
449 {
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;
454 }
455
456 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
457 {
458         ot->name= "Face Select Reveal";
459         ot->description= "Reveal hidden faces";
460         ot->idname= "PAINT_OT_face_select_reveal";
461
462         ot->exec= face_select_reveal_exec;
463         ot->poll= facemask_paint_poll;
464
465         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
466
467         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
468 }