|
Blender
V2.59
|
00001 00005 #include <math.h> 00006 #include <stdlib.h> 00007 00008 #include "DNA_mesh_types.h" 00009 #include "DNA_meshdata_types.h" 00010 #include "DNA_object_types.h" 00011 00012 #include "DNA_scene_types.h" 00013 #include "DNA_brush_types.h" 00014 00015 #include "BLI_math.h" 00016 #include "BLI_utildefines.h" 00017 00018 #include "BKE_brush.h" 00019 #include "BKE_context.h" 00020 #include "BKE_DerivedMesh.h" 00021 #include "BKE_paint.h" 00022 00023 #include "RNA_access.h" 00024 #include "RNA_define.h" 00025 00026 #include "BIF_gl.h" 00027 /* TODO: remove once projectf goes away */ 00028 #include "BIF_glutil.h" 00029 00030 #include "RE_shader_ext.h" 00031 00032 #include "ED_view3d.h" 00033 #include "ED_screen.h" 00034 00035 #include "BLO_sys_types.h" 00036 #include "ED_mesh.h" /* for face mask functions */ 00037 00038 #include "WM_api.h" 00039 #include "WM_types.h" 00040 00041 #include "paint_intern.h" 00042 00043 /* convert a point in model coordinates to 2D screen coordinates */ 00044 /* TODO: can be deleted once all calls are replaced with 00045 view3d_project_float() */ 00046 void projectf(bglMats *mats, const float v[3], float p[2]) 00047 { 00048 double ux, uy, uz; 00049 00050 gluProject(v[0],v[1],v[2], mats->modelview, mats->projection, 00051 (GLint *)mats->viewport, &ux, &uy, &uz); 00052 p[0]= ux; 00053 p[1]= uy; 00054 } 00055 00056 float paint_calc_object_space_radius(ViewContext *vc, float center[3], 00057 float pixel_radius) 00058 { 00059 Object *ob = vc->obact; 00060 float delta[3], scale, loc[3]; 00061 float mval_f[2]; 00062 00063 mul_v3_m4v3(loc, ob->obmat, center); 00064 00065 initgrabz(vc->rv3d, loc[0], loc[1], loc[2]); 00066 00067 mval_f[0]= pixel_radius; 00068 mval_f[1]= 0.0f; 00069 ED_view3d_win_to_delta(vc->ar, mval_f, delta); 00070 00071 scale= fabsf(mat4_to_scale(ob->obmat)); 00072 scale= (scale == 0.0f)? 1.0f: scale; 00073 00074 return len_v3(delta)/scale; 00075 } 00076 00077 float paint_get_tex_pixel(Brush* br, float u, float v) 00078 { 00079 TexResult texres; 00080 float co[3]; 00081 int hasrgb; 00082 00083 co[0] = u; 00084 co[1] = v; 00085 co[2] = 0; 00086 00087 memset(&texres, 0, sizeof(TexResult)); 00088 hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres); 00089 00090 if (hasrgb & TEX_RGB) 00091 texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta; 00092 00093 return texres.tin; 00094 } 00095 00096 /* 3D Paint */ 00097 00098 static void imapaint_project(Object *ob, float *model, float *proj, float *co, float *pco) 00099 { 00100 VECCOPY(pco, co); 00101 pco[3]= 1.0f; 00102 00103 mul_m4_v3(ob->obmat, pco); 00104 mul_m4_v3((float(*)[4])model, pco); 00105 mul_m4_v4((float(*)[4])proj, pco); 00106 } 00107 00108 static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, float *co, float *w) 00109 { 00110 float pv1[4], pv2[4], pv3[4], h[3], divw; 00111 float model[16], proj[16], wmat[3][3], invwmat[3][3]; 00112 GLint view[4]; 00113 00114 /* compute barycentric coordinates */ 00115 00116 /* get the needed opengl matrices */ 00117 glGetIntegerv(GL_VIEWPORT, view); 00118 glGetFloatv(GL_MODELVIEW_MATRIX, model); 00119 glGetFloatv(GL_PROJECTION_MATRIX, proj); 00120 view[0] = view[1] = 0; 00121 00122 /* project the verts */ 00123 imapaint_project(ob, model, proj, v1, pv1); 00124 imapaint_project(ob, model, proj, v2, pv2); 00125 imapaint_project(ob, model, proj, v3, pv3); 00126 00127 /* do inverse view mapping, see gluProject man page */ 00128 h[0]= (co[0] - view[0])*2.0f/view[2] - 1; 00129 h[1]= (co[1] - view[1])*2.0f/view[3] - 1; 00130 h[2]= 1.0f; 00131 00132 /* solve for(w1,w2,w3)/perspdiv in: 00133 h*perspdiv = Project*Model*(w1*v1 + w2*v2 + w3*v3) */ 00134 00135 wmat[0][0]= pv1[0]; wmat[1][0]= pv2[0]; wmat[2][0]= pv3[0]; 00136 wmat[0][1]= pv1[1]; wmat[1][1]= pv2[1]; wmat[2][1]= pv3[1]; 00137 wmat[0][2]= pv1[3]; wmat[1][2]= pv2[3]; wmat[2][2]= pv3[3]; 00138 00139 invert_m3_m3(invwmat, wmat); 00140 mul_m3_v3(invwmat, h); 00141 00142 VECCOPY(w, h); 00143 00144 /* w is still divided by perspdiv, make it sum to one */ 00145 divw= w[0] + w[1] + w[2]; 00146 if(divw != 0.0f) 00147 mul_v3_fl(w, 1.0f/divw); 00148 } 00149 00150 /* compute uv coordinates of mouse in face */ 00151 void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) 00152 { 00153 DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); 00154 const int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); 00155 MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf; 00156 int numfaces = dm->getNumFaces(dm), a, findex; 00157 float p[2], w[3], absw, minabsw; 00158 MFace mf; 00159 MVert mv[4]; 00160 00161 minabsw = 1e10; 00162 uv[0] = uv[1] = 0.0; 00163 00164 /* test all faces in the derivedmesh with the original index of the picked face */ 00165 for(a = 0; a < numfaces; a++) { 00166 findex= index ? index[a]: a; 00167 00168 if(findex == faceindex) { 00169 dm->getFace(dm, a, &mf); 00170 00171 dm->getVert(dm, mf.v1, &mv[0]); 00172 dm->getVert(dm, mf.v2, &mv[1]); 00173 dm->getVert(dm, mf.v3, &mv[2]); 00174 if(mf.v4) 00175 dm->getVert(dm, mf.v4, &mv[3]); 00176 00177 tf= &tface[a]; 00178 00179 p[0]= xy[0]; 00180 p[1]= xy[1]; 00181 00182 if(mf.v4) { 00183 /* the triangle with the largest absolute values is the one 00184 with the most negative weights */ 00185 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w); 00186 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); 00187 if(absw < minabsw) { 00188 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2]; 00189 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2]; 00190 minabsw = absw; 00191 } 00192 00193 imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w); 00194 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); 00195 if(absw < minabsw) { 00196 uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2]; 00197 uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2]; 00198 minabsw = absw; 00199 } 00200 } 00201 else { 00202 imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w); 00203 absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); 00204 if(absw < minabsw) { 00205 uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2]; 00206 uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2]; 00207 minabsw = absw; 00208 } 00209 } 00210 } 00211 } 00212 00213 dm->release(dm); 00214 } 00215 00217 int imapaint_pick_face(ViewContext *vc, Mesh *me, const int mval[2], unsigned int *index) 00218 { 00219 if(!me || me->totface==0) 00220 return 0; 00221 00222 /* sample only on the exact position */ 00223 *index = view3d_sample_backbuf(vc, mval[0], mval[1]); 00224 00225 if((*index)<=0 || (*index)>(unsigned int)me->totface) 00226 return 0; 00227 00228 (*index)--; 00229 00230 return 1; 00231 } 00232 00233 /* used for both 3d view and image window */ 00234 void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf */ 00235 { 00236 Brush *br = paint_brush(paint_get_active(scene)); 00237 unsigned int col; 00238 char *cp; 00239 00240 CLAMP(x, 0, ar->winx); 00241 CLAMP(y, 0, ar->winy); 00242 00243 glReadBuffer(GL_FRONT); 00244 glReadPixels(x+ar->winrct.xmin, y+ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); 00245 glReadBuffer(GL_BACK); 00246 00247 cp = (char *)&col; 00248 00249 if(br) { 00250 br->rgb[0]= cp[0]/255.0f; 00251 br->rgb[1]= cp[1]/255.0f; 00252 br->rgb[2]= cp[2]/255.0f; 00253 } 00254 } 00255 00256 static int brush_curve_preset_exec(bContext *C, wmOperator *op) 00257 { 00258 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C))); 00259 brush_curve_preset(br, RNA_enum_get(op->ptr, "shape")); 00260 00261 return OPERATOR_FINISHED; 00262 } 00263 00264 static int brush_curve_preset_poll(bContext *C) 00265 { 00266 Brush *br = paint_brush(paint_get_active(CTX_data_scene(C))); 00267 00268 return br && br->curve; 00269 } 00270 00271 void BRUSH_OT_curve_preset(wmOperatorType *ot) 00272 { 00273 static EnumPropertyItem prop_shape_items[] = { 00274 {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, 00275 {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, 00276 {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, 00277 {CURVE_PRESET_LINE, "LINE", 0, "Line", ""}, 00278 {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""}, 00279 {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""}, 00280 {0, NULL, 0, NULL, NULL}}; 00281 00282 ot->name= "Preset"; 00283 ot->description= "Set brush shape"; 00284 ot->idname= "BRUSH_OT_curve_preset"; 00285 00286 ot->exec= brush_curve_preset_exec; 00287 ot->poll= brush_curve_preset_poll; 00288 00289 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00290 00291 RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); 00292 } 00293 00294 00295 /* face-select ops */ 00296 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) 00297 { 00298 paintface_select_linked(C, CTX_data_active_object(C), NULL, 2); 00299 ED_region_tag_redraw(CTX_wm_region(C)); 00300 return OPERATOR_FINISHED; 00301 } 00302 00303 void PAINT_OT_face_select_linked(wmOperatorType *ot) 00304 { 00305 ot->name= "Select Linked"; 00306 ot->description= "Select linked faces"; 00307 ot->idname= "PAINT_OT_face_select_linked"; 00308 00309 ot->exec= paint_select_linked_exec; 00310 ot->poll= facemask_paint_poll; 00311 00312 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00313 } 00314 00315 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) 00316 { 00317 int mode= RNA_boolean_get(op->ptr, "extend") ? 1:0; 00318 paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode); 00319 ED_region_tag_redraw(CTX_wm_region(C)); 00320 return OPERATOR_FINISHED; 00321 } 00322 00323 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot) 00324 { 00325 ot->name= "Select Linked Pick"; 00326 ot->description= "Select linked faces"; 00327 ot->idname= "PAINT_OT_face_select_linked_pick"; 00328 00329 ot->invoke= paint_select_linked_pick_invoke; 00330 ot->poll= facemask_paint_poll; 00331 00332 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00333 00334 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection"); 00335 } 00336 00337 00338 static int face_select_all_exec(bContext *C, wmOperator *op) 00339 { 00340 Object *ob= CTX_data_active_object(C); 00341 paintface_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE); 00342 ED_region_tag_redraw(CTX_wm_region(C)); 00343 return OPERATOR_FINISHED; 00344 } 00345 00346 00347 void PAINT_OT_face_select_all(wmOperatorType *ot) 00348 { 00349 ot->name= "Face Selection"; 00350 ot->description= "Change selection for all faces"; 00351 ot->idname= "PAINT_OT_face_select_all"; 00352 00353 ot->exec= face_select_all_exec; 00354 ot->poll= facemask_paint_poll; 00355 00356 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00357 00358 WM_operator_properties_select_all(ot); 00359 } 00360 00361 static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) 00362 { 00363 Object *ob= CTX_data_active_object(C); 00364 paintface_deselect_all_visible(ob, SEL_INVERT, TRUE); 00365 ED_region_tag_redraw(CTX_wm_region(C)); 00366 return OPERATOR_FINISHED; 00367 } 00368 00369 00370 void PAINT_OT_face_select_inverse(wmOperatorType *ot) 00371 { 00372 ot->name= "Face Select Invert"; 00373 ot->description= "Invert selection of faces"; 00374 ot->idname= "PAINT_OT_face_select_inverse"; 00375 00376 ot->exec= face_select_inverse_exec; 00377 ot->poll= facemask_paint_poll; 00378 00379 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00380 } 00381 00382 static int face_select_hide_exec(bContext *C, wmOperator *op) 00383 { 00384 const int unselected= RNA_boolean_get(op->ptr, "unselected"); 00385 Object *ob= CTX_data_active_object(C); 00386 paintface_hide(ob, unselected); 00387 ED_region_tag_redraw(CTX_wm_region(C)); 00388 return OPERATOR_FINISHED; 00389 } 00390 00391 void PAINT_OT_face_select_hide(wmOperatorType *ot) 00392 { 00393 ot->name= "Face Select Hide"; 00394 ot->description= "Hide selected faces"; 00395 ot->idname= "PAINT_OT_face_select_hide"; 00396 00397 ot->exec= face_select_hide_exec; 00398 ot->poll= facemask_paint_poll; 00399 00400 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00401 00402 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects."); 00403 } 00404 00405 static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op)) 00406 { 00407 Object *ob= CTX_data_active_object(C); 00408 paintface_reveal(ob); 00409 ED_region_tag_redraw(CTX_wm_region(C)); 00410 return OPERATOR_FINISHED; 00411 } 00412 00413 void PAINT_OT_face_select_reveal(wmOperatorType *ot) 00414 { 00415 ot->name= "Face Select Reveal"; 00416 ot->description= "Reveal hidden faces"; 00417 ot->idname= "PAINT_OT_face_select_reveal"; 00418 00419 ot->exec= face_select_reveal_exec; 00420 ot->poll= facemask_paint_poll; 00421 00422 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00423 00424 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects."); 00425 }