svn merge -r36603:36628 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[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
62         mul_v3_m4v3(loc, ob->obmat, center);
63
64         initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
65         window_to_3d_delta(vc->ar, delta, pixel_radius, 0);
66
67         scale= fabsf(mat4_to_scale(ob->obmat));
68         scale= (scale == 0.0f)? 1.0f: scale;
69
70         return len_v3(delta)/scale;
71 }
72
73 float paint_get_tex_pixel(Brush* br, float u, float v)
74 {
75         TexResult texres;
76         float co[3];
77         int hasrgb;
78
79         co[0] = u;
80         co[1] = v;
81         co[2] = 0;
82
83         memset(&texres, 0, sizeof(TexResult));
84         hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
85
86         if (hasrgb & TEX_RGB)
87                 texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta;
88
89         return texres.tin;
90 }
91
92 /* 3D Paint */
93
94 static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco)
95 {
96         VECCOPY(pco, co);
97         pco[3]= 1.0f;
98
99         mul_m4_v3(ob->obmat, pco);
100         mul_m4_v3((float(*)[4])model, pco);
101         mul_m4_v4((float(*)[4])proj, pco);
102 }
103
104 static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w)
105 {
106         float pv1[4], pv2[4], pv3[4], h[3], divw;
107         float model[16], proj[16], wmat[3][3], invwmat[3][3];
108         GLint view[4];
109
110         /* compute barycentric coordinates */
111
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;
117
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);
122
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;
126         h[2]= 1.0f;
127
128         /* solve for(w1,w2,w3)/perspdiv in:
129            h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */
130
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];
134
135         invert_m3_m3(invwmat, wmat);
136         mul_m3_v3(invwmat, h);
137
138         VECCOPY(w, h);
139
140         /* w is still divided by perspdiv, make it sum to one */
141         divw= w[0] + w[1] + w[2];
142         if(divw != 0.0f)
143                 mul_v3_fl(w, 1.0f/divw);
144 }
145
146 /* compute uv coordinates of mouse in face */
147 void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, int *xy, float *uv)
148 {
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;
154         MFace mf;
155         MVert mv[4];
156
157         minabsw = 1e10;
158         uv[0] = uv[1] = 0.0;
159
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;
163
164                 if(findex == faceindex) {
165                         dm->getTessFace(dm, a, &mf);
166
167                         dm->getVert(dm, mf.v1, &mv[0]);
168                         dm->getVert(dm, mf.v2, &mv[1]);
169                         dm->getVert(dm, mf.v3, &mv[2]);
170                         if(mf.v4)
171                                 dm->getVert(dm, mf.v4, &mv[3]);
172
173                         tf= &tface[a];
174
175                         p[0]= xy[0];
176                         p[1]= xy[1];
177
178                         if(mf.v4) {
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]);
183                                 if(absw < minabsw) {
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];
186                                         minabsw = absw;
187                                 }
188
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]);
191                                 if(absw < minabsw) {
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];
194                                         minabsw = absw;
195                                 }
196                         }
197                         else {
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]);
200                                 if(absw < minabsw) {
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];
203                                         minabsw = absw;
204                                 }
205                         }
206                 }
207         }
208
209         dm->release(dm);
210 }
211
212 ///* returns 0 if not found, otherwise 1 */
213 int imapaint_pick_face(ViewContext *vc, Mesh *me, int *mval, unsigned int *index)
214 {
215         if(!me || me->totface==0)
216                 return 0;
217
218         /* sample only on the exact position */
219         *index = view3d_sample_backbuf(vc, mval[0], mval[1]);
220
221         if((*index)<=0 || (*index)>(unsigned int)me->totface)
222                 return 0;
223
224         (*index)--;
225         
226         return 1;
227 }
228
229 /* used for both 3d view and image window */
230 void paint_sample_color(Scene *scene, ARegion *ar, int x, int y)        /* frontbuf */
231 {
232         Brush *br = paint_brush(paint_get_active(scene));
233         unsigned int col;
234         char *cp;
235
236         CLAMP(x, 0, ar->winx);
237         CLAMP(y, 0, ar->winy);
238         
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);
242
243         cp = (char *)&col;
244         
245         if(br) {
246                 br->rgb[0]= cp[0]/255.0f;
247                 br->rgb[1]= cp[1]/255.0f;
248                 br->rgb[2]= cp[2]/255.0f;
249         }
250 }
251
252 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
253 {
254         Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
255         brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
256
257         return OPERATOR_FINISHED;
258 }
259
260 static int brush_curve_preset_poll(bContext *C)
261 {
262         Brush *br = paint_brush(paint_get_active(CTX_data_scene(C)));
263
264         return br && br->curve;
265 }
266
267 void BRUSH_OT_curve_preset(wmOperatorType *ot)
268 {
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}};
277
278         ot->name= "Preset";
279         ot->description= "Set brush shape";
280         ot->idname= "BRUSH_OT_curve_preset";
281
282         ot->exec= brush_curve_preset_exec;
283         ot->poll= brush_curve_preset_poll;
284
285         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
286
287         RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
288 }
289
290
291 /* face-select ops */
292 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
293 {
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;
297 }
298
299 void PAINT_OT_face_select_linked(wmOperatorType *ot)
300 {
301         ot->name= "Select Linked";
302         ot->description= "Select linked faces";
303         ot->idname= "PAINT_OT_face_select_linked";
304
305         ot->exec= paint_select_linked_exec;
306         ot->poll= facemask_paint_poll;
307
308         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
309 }
310
311 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
312 {
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;
317 }
318
319 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
320 {
321         ot->name= "Select Linked Pick";
322         ot->description= "Select linked faces";
323         ot->idname= "PAINT_OT_face_select_linked_pick";
324
325         ot->invoke= paint_select_linked_pick_invoke;
326         ot->poll= facemask_paint_poll;
327
328         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
329
330         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
331 }
332
333
334 static int face_select_all_exec(bContext *C, wmOperator *op)
335 {
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;
340 }
341
342
343 void PAINT_OT_face_select_all(wmOperatorType *ot)
344 {
345         ot->name= "Face Selection";
346         ot->description= "Change selection for all faces";
347         ot->idname= "PAINT_OT_face_select_all";
348
349         ot->exec= face_select_all_exec;
350         ot->poll= facemask_paint_poll;
351
352         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
353
354         WM_operator_properties_select_all(ot);
355 }
356
357 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
358 {
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;
363 }
364
365
366 void PAINT_OT_face_select_inverse(wmOperatorType *ot)
367 {
368         ot->name= "Face Select Invert";
369         ot->description= "Invert selection of faces";
370         ot->idname= "PAINT_OT_face_select_inverse";
371
372         ot->exec= face_select_inverse_exec;
373         ot->poll= facemask_paint_poll;
374
375         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
376 }
377
378 static int face_select_hide_exec(bContext *C, wmOperator *op)
379 {
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;
385 }
386
387 void PAINT_OT_face_select_hide(wmOperatorType *ot)
388 {
389         ot->name= "Face Select Hide";
390         ot->description= "Hide selected faces";
391         ot->idname= "PAINT_OT_face_select_hide";
392
393         ot->exec= face_select_hide_exec;
394         ot->poll= facemask_paint_poll;
395
396         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
397
398         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
399 }
400
401 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
402 {
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;
407 }
408
409 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
410 {
411         ot->name= "Face Select Reveal";
412         ot->description= "Reveal hidden faces";
413         ot->idname= "PAINT_OT_face_select_reveal";
414
415         ot->exec= face_select_reveal_exec;
416         ot->poll= facemask_paint_poll;
417
418         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
419
420         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
421 }