Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <math.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_brush_types.h" 00039 #include "DNA_color_types.h" 00040 #include "DNA_scene_types.h" 00041 #include "DNA_object_types.h" 00042 #include "DNA_windowmanager_types.h" 00043 00044 #include "WM_types.h" 00045 00046 #include "RNA_access.h" 00047 00048 #include "BLI_bpath.h" 00049 #include "BLI_math.h" 00050 #include "BLI_blenlib.h" 00051 #include "BLI_rand.h" 00052 #include "BLI_utildefines.h" 00053 00054 #include "BKE_brush.h" 00055 #include "BKE_colortools.h" 00056 #include "BKE_global.h" 00057 #include "BKE_image.h" 00058 #include "BKE_library.h" 00059 #include "BKE_main.h" 00060 #include "BKE_paint.h" 00061 #include "BKE_texture.h" 00062 #include "BKE_icons.h" 00063 00064 #include "IMB_imbuf.h" 00065 #include "IMB_imbuf_types.h" 00066 00067 #include "RE_render_ext.h" /* externtex */ 00068 #include "RE_shader_ext.h" 00069 00070 static void brush_set_defaults(Brush *brush) 00071 { 00072 brush->blend = 0; 00073 brush->flag = 0; 00074 00075 brush->ob_mode = OB_MODE_ALL_PAINT; 00076 00077 /* BRUSH SCULPT TOOL SETTINGS */ 00078 brush->size= 35; /* radius of the brush in pixels */ 00079 brush->alpha= 0.5f; /* brush strength/intensity probably variable should be renamed? */ 00080 brush->autosmooth_factor= 0.0f; 00081 brush->crease_pinch_factor= 0.5f; 00082 brush->sculpt_plane = SCULPT_DISP_DIR_AREA; 00083 brush->plane_offset= 0.0f; /* how far above or below the plane that is found by averaging the faces */ 00084 brush->plane_trim= 0.5f; 00085 brush->clone.alpha= 0.5f; 00086 brush->normal_weight= 0.0f; 00087 brush->flag |= BRUSH_ALPHA_PRESSURE; 00088 00089 /* BRUSH PAINT TOOL SETTINGS */ 00090 brush->rgb[0]= 1.0f; /* default rgb color of the brush when painting - white */ 00091 brush->rgb[1]= 1.0f; 00092 brush->rgb[2]= 1.0f; 00093 00094 /* BRUSH STROKE SETTINGS */ 00095 brush->flag |= (BRUSH_SPACE|BRUSH_SPACE_ATTEN); 00096 brush->spacing= 10; /* how far each brush dot should be spaced as a percentage of brush diameter */ 00097 00098 brush->smooth_stroke_radius= 75; 00099 brush->smooth_stroke_factor= 0.9f; 00100 00101 brush->rate= 0.1f; /* time delay between dots of paint or sculpting when doing airbrush mode */ 00102 00103 brush->jitter= 0.0f; 00104 00105 /* BRUSH TEXTURE SETTINGS */ 00106 default_mtex(&brush->mtex); 00107 00108 brush->texture_sample_bias= 0; /* value to added to texture samples */ 00109 brush->texture_overlay_alpha= 33; 00110 00111 /* brush appearance */ 00112 00113 brush->add_col[0]= 1.00; /* add mode color is light red */ 00114 brush->add_col[1]= 0.39; 00115 brush->add_col[2]= 0.39; 00116 00117 brush->sub_col[0]= 0.39; /* subtract mode color is light blue */ 00118 brush->sub_col[1]= 0.39; 00119 brush->sub_col[2]= 1.00; 00120 } 00121 00122 /* Datablock add/copy/free/make_local */ 00123 00124 Brush *add_brush(const char *name) 00125 { 00126 Brush *brush; 00127 00128 brush= alloc_libblock(&G.main->brush, ID_BR, name); 00129 00130 /* enable fake user by default */ 00131 brush->id.flag |= LIB_FAKEUSER; 00132 00133 brush_set_defaults(brush); 00134 00135 brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */ 00136 00137 /* the default alpha falloff curve */ 00138 brush_curve_preset(brush, CURVE_PRESET_SMOOTH); 00139 00140 return brush; 00141 } 00142 00143 Brush *copy_brush(Brush *brush) 00144 { 00145 Brush *brushn; 00146 00147 brushn= copy_libblock(&brush->id); 00148 00149 if (brush->mtex.tex) 00150 id_us_plus((ID*)brush->mtex.tex); 00151 00152 if (brush->icon_imbuf) 00153 brushn->icon_imbuf= IMB_dupImBuf(brush->icon_imbuf); 00154 00155 brushn->preview = NULL; 00156 00157 brushn->curve= curvemapping_copy(brush->curve); 00158 00159 /* enable fake user by default */ 00160 if (!(brushn->id.flag & LIB_FAKEUSER)) { 00161 brushn->id.flag |= LIB_FAKEUSER; 00162 brushn->id.us++; 00163 } 00164 00165 return brushn; 00166 } 00167 00168 /* not brush itself */ 00169 void free_brush(Brush *brush) 00170 { 00171 if (brush->mtex.tex) 00172 brush->mtex.tex->id.us--; 00173 00174 if (brush->icon_imbuf) 00175 IMB_freeImBuf(brush->icon_imbuf); 00176 00177 BKE_previewimg_free(&(brush->preview)); 00178 00179 curvemapping_free(brush->curve); 00180 } 00181 00182 static void extern_local_brush(Brush *brush) 00183 { 00184 id_lib_extern((ID *)brush->mtex.tex); 00185 id_lib_extern((ID *)brush->clone.image); 00186 } 00187 00188 void make_local_brush(Brush *brush) 00189 { 00190 00191 /* - only lib users: do nothing 00192 * - only local users: set flag 00193 * - mixed: make copy 00194 */ 00195 00196 Main *bmain= G.main; 00197 Scene *scene; 00198 int is_local= FALSE, is_lib= FALSE; 00199 00200 if(brush->id.lib==NULL) return; 00201 00202 if(brush->clone.image) { 00203 /* special case: ima always local immediately. Clone image should only 00204 have one user anyway. */ 00205 id_clear_lib_data(bmain, &brush->clone.image->id); 00206 extern_local_brush(brush); 00207 } 00208 00209 for(scene= bmain->scene.first; scene && ELEM(0, is_lib, is_local); scene=scene->id.next) { 00210 if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) { 00211 if(scene->id.lib) is_lib= TRUE; 00212 else is_local= TRUE; 00213 } 00214 } 00215 00216 if(is_local && is_lib == FALSE) { 00217 id_clear_lib_data(bmain, &brush->id); 00218 extern_local_brush(brush); 00219 00220 /* enable fake user by default */ 00221 if (!(brush->id.flag & LIB_FAKEUSER)) { 00222 brush->id.flag |= LIB_FAKEUSER; 00223 brush->id.us++; 00224 } 00225 } 00226 else if(is_local && is_lib) { 00227 Brush *brush_new= copy_brush(brush); 00228 brush_new->id.us= 1; /* only keep fake user */ 00229 brush_new->id.flag |= LIB_FAKEUSER; 00230 00231 /* Remap paths of new ID using old library as base. */ 00232 BKE_id_lib_local_paths(bmain, brush->id.lib, &brush_new->id); 00233 00234 for(scene= bmain->scene.first; scene; scene=scene->id.next) { 00235 if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) { 00236 if(scene->id.lib==NULL) { 00237 paint_brush_set(&scene->toolsettings->imapaint.paint, brush_new); 00238 } 00239 } 00240 } 00241 } 00242 } 00243 00244 void brush_debug_print_state(Brush *br) 00245 { 00246 /* create a fake brush and set it to the defaults */ 00247 Brush def= {{NULL}}; 00248 brush_set_defaults(&def); 00249 00250 #define BR_TEST(field, t) \ 00251 if(br->field != def.field) \ 00252 printf("br->" #field " = %" #t ";\n", br->field) 00253 00254 #define BR_TEST_FLAG(_f) \ 00255 if((br->flag & _f) && !(def.flag & _f)) \ 00256 printf("br->flag |= " #_f ";\n"); \ 00257 else if(!(br->flag & _f) && (def.flag & _f)) \ 00258 printf("br->flag &= ~" #_f ";\n") 00259 00260 00261 /* print out any non-default brush state */ 00262 BR_TEST(normal_weight, f); 00263 00264 BR_TEST(blend, d); 00265 BR_TEST(size, d); 00266 00267 /* br->flag */ 00268 BR_TEST_FLAG(BRUSH_AIRBRUSH); 00269 BR_TEST_FLAG(BRUSH_TORUS); 00270 BR_TEST_FLAG(BRUSH_ALPHA_PRESSURE); 00271 BR_TEST_FLAG(BRUSH_SIZE_PRESSURE); 00272 BR_TEST_FLAG(BRUSH_JITTER_PRESSURE); 00273 BR_TEST_FLAG(BRUSH_SPACING_PRESSURE); 00274 BR_TEST_FLAG(BRUSH_FIXED_TEX); 00275 BR_TEST_FLAG(BRUSH_RAKE); 00276 BR_TEST_FLAG(BRUSH_ANCHORED); 00277 BR_TEST_FLAG(BRUSH_DIR_IN); 00278 BR_TEST_FLAG(BRUSH_SPACE); 00279 BR_TEST_FLAG(BRUSH_SMOOTH_STROKE); 00280 BR_TEST_FLAG(BRUSH_PERSISTENT); 00281 BR_TEST_FLAG(BRUSH_ACCUMULATE); 00282 BR_TEST_FLAG(BRUSH_LOCK_ALPHA); 00283 BR_TEST_FLAG(BRUSH_ORIGINAL_NORMAL); 00284 BR_TEST_FLAG(BRUSH_OFFSET_PRESSURE); 00285 BR_TEST_FLAG(BRUSH_SPACE_ATTEN); 00286 BR_TEST_FLAG(BRUSH_ADAPTIVE_SPACE); 00287 BR_TEST_FLAG(BRUSH_LOCK_SIZE); 00288 BR_TEST_FLAG(BRUSH_TEXTURE_OVERLAY); 00289 BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE); 00290 BR_TEST_FLAG(BRUSH_RESTORE_MESH); 00291 BR_TEST_FLAG(BRUSH_INVERSE_SMOOTH_PRESSURE); 00292 BR_TEST_FLAG(BRUSH_RANDOM_ROTATION); 00293 BR_TEST_FLAG(BRUSH_PLANE_TRIM); 00294 BR_TEST_FLAG(BRUSH_FRONTFACE); 00295 BR_TEST_FLAG(BRUSH_CUSTOM_ICON); 00296 00297 BR_TEST(jitter, f); 00298 BR_TEST(spacing, d); 00299 BR_TEST(smooth_stroke_radius, d); 00300 BR_TEST(smooth_stroke_factor, f); 00301 BR_TEST(rate, f); 00302 00303 BR_TEST(alpha, f); 00304 00305 BR_TEST(sculpt_plane, d); 00306 00307 BR_TEST(plane_offset, f); 00308 00309 BR_TEST(autosmooth_factor, f); 00310 00311 BR_TEST(crease_pinch_factor, f); 00312 00313 BR_TEST(plane_trim, f); 00314 00315 BR_TEST(texture_sample_bias, f); 00316 BR_TEST(texture_overlay_alpha, d); 00317 00318 BR_TEST(add_col[0], f); 00319 BR_TEST(add_col[1], f); 00320 BR_TEST(add_col[2], f); 00321 BR_TEST(sub_col[0], f); 00322 BR_TEST(sub_col[1], f); 00323 BR_TEST(sub_col[2], f); 00324 00325 printf("\n"); 00326 00327 #undef BR_TEST 00328 #undef BR_TEST_FLAG 00329 } 00330 00331 void brush_reset_sculpt(Brush *br) 00332 { 00333 /* enable this to see any non-default 00334 settings used by a brush: 00335 00336 brush_debug_print_state(br); 00337 */ 00338 00339 brush_set_defaults(br); 00340 brush_curve_preset(br, CURVE_PRESET_SMOOTH); 00341 00342 switch(br->sculpt_tool) { 00343 case SCULPT_TOOL_CLAY: 00344 br->flag |= BRUSH_FRONTFACE; 00345 break; 00346 case SCULPT_TOOL_CREASE: 00347 br->flag |= BRUSH_DIR_IN; 00348 br->alpha = 0.25; 00349 break; 00350 case SCULPT_TOOL_FILL: 00351 br->add_col[1] = 1; 00352 br->sub_col[0] = 0.25; 00353 br->sub_col[1] = 1; 00354 break; 00355 case SCULPT_TOOL_FLATTEN: 00356 br->add_col[1] = 1; 00357 br->sub_col[0] = 0.25; 00358 br->sub_col[1] = 1; 00359 break; 00360 case SCULPT_TOOL_INFLATE: 00361 br->add_col[0] = 0.750000; 00362 br->add_col[1] = 0.750000; 00363 br->add_col[2] = 0.750000; 00364 br->sub_col[0] = 0.250000; 00365 br->sub_col[1] = 0.250000; 00366 br->sub_col[2] = 0.250000; 00367 break; 00368 case SCULPT_TOOL_NUDGE: 00369 br->add_col[0] = 0.250000; 00370 br->add_col[1] = 1.000000; 00371 br->add_col[2] = 0.250000; 00372 break; 00373 case SCULPT_TOOL_PINCH: 00374 br->add_col[0] = 0.750000; 00375 br->add_col[1] = 0.750000; 00376 br->add_col[2] = 0.750000; 00377 br->sub_col[0] = 0.250000; 00378 br->sub_col[1] = 0.250000; 00379 br->sub_col[2] = 0.250000; 00380 break; 00381 case SCULPT_TOOL_SCRAPE: 00382 br->add_col[1] = 1.000000; 00383 br->sub_col[0] = 0.250000; 00384 br->sub_col[1] = 1.000000; 00385 break; 00386 case SCULPT_TOOL_ROTATE: 00387 br->alpha = 1.0; 00388 break; 00389 case SCULPT_TOOL_SMOOTH: 00390 br->flag &= ~BRUSH_SPACE_ATTEN; 00391 br->spacing = 5; 00392 br->add_col[0] = 0.750000; 00393 br->add_col[1] = 0.750000; 00394 br->add_col[2] = 0.750000; 00395 break; 00396 case SCULPT_TOOL_GRAB: 00397 case SCULPT_TOOL_SNAKE_HOOK: 00398 case SCULPT_TOOL_THUMB: 00399 br->size = 75; 00400 br->flag &= ~BRUSH_ALPHA_PRESSURE; 00401 br->flag &= ~BRUSH_SPACE; 00402 br->flag &= ~BRUSH_SPACE_ATTEN; 00403 br->add_col[0] = 0.250000; 00404 br->add_col[1] = 1.000000; 00405 br->add_col[2] = 0.250000; 00406 break; 00407 default: 00408 break; 00409 } 00410 } 00411 00412 /* Library Operations */ 00413 void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset) 00414 { 00415 CurveMap *cm = NULL; 00416 00417 if(!b->curve) 00418 b->curve = curvemapping_add(1, 0, 0, 1, 1); 00419 00420 cm = b->curve->cm; 00421 cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; 00422 00423 b->curve->preset = preset; 00424 curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE); 00425 curvemapping_changed(b->curve, 0); 00426 } 00427 00428 int brush_texture_set_nr(Brush *brush, int nr) 00429 { 00430 ID *idtest, *id=NULL; 00431 00432 id= (ID *)brush->mtex.tex; 00433 00434 idtest= (ID*)BLI_findlink(&G.main->tex, nr-1); 00435 if(idtest==NULL) { /* new tex */ 00436 if(id) idtest= (ID *)copy_texture((Tex *)id); 00437 else idtest= (ID *)add_texture("Tex"); 00438 idtest->us--; 00439 } 00440 if(idtest!=id) { 00441 brush_texture_delete(brush); 00442 00443 brush->mtex.tex= (Tex*)idtest; 00444 id_us_plus(idtest); 00445 00446 return 1; 00447 } 00448 00449 return 0; 00450 } 00451 00452 int brush_texture_delete(Brush *brush) 00453 { 00454 if(brush->mtex.tex) 00455 brush->mtex.tex->id.us--; 00456 00457 return 1; 00458 } 00459 00460 int brush_clone_image_set_nr(Brush *brush, int nr) 00461 { 00462 if(brush && nr > 0) { 00463 Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1); 00464 00465 if(ima) { 00466 brush_clone_image_delete(brush); 00467 brush->clone.image= ima; 00468 id_us_plus(&ima->id); 00469 brush->clone.offset[0]= brush->clone.offset[1]= 0.0f; 00470 00471 return 1; 00472 } 00473 } 00474 00475 return 0; 00476 } 00477 00478 int brush_clone_image_delete(Brush *brush) 00479 { 00480 if (brush && brush->clone.image) { 00481 brush->clone.image->id.us--; 00482 brush->clone.image= NULL; 00483 return 1; 00484 } 00485 00486 return 0; 00487 } 00488 00489 /* Brush Sampling */ 00490 void brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) 00491 { 00492 MTex *mtex= &brush->mtex; 00493 00494 if (mtex && mtex->tex) { 00495 float co[3], tin, tr, tg, tb, ta; 00496 int hasrgb; 00497 const int radius= brush_size(scene, brush); 00498 00499 co[0]= xy[0]/radius; 00500 co[1]= xy[1]/radius; 00501 co[2]= 0.0f; 00502 00503 hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); 00504 00505 if (hasrgb) { 00506 rgba[0]= tr; 00507 rgba[1]= tg; 00508 rgba[2]= tb; 00509 rgba[3]= ta; 00510 } 00511 else { 00512 rgba[0]= tin; 00513 rgba[1]= tin; 00514 rgba[2]= tin; 00515 rgba[3]= 1.0f; 00516 } 00517 } 00518 else { 00519 rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f; 00520 } 00521 } 00522 00523 /* TODO, use define for 'texfall' arg */ 00524 void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) 00525 { 00526 ImBuf *ibuf; 00527 float xy[2], rgba[4], *dstf; 00528 int x, y, rowbytes, xoff, yoff, imbflag; 00529 const int radius= brush_size(scene, brush); 00530 char *dst, crgb[3]; 00531 const float alpha= brush_alpha(scene, brush); 00532 float brush_rgb[3]; 00533 00534 imbflag= (flt)? IB_rectfloat: IB_rect; 00535 xoff = -bufsize/2.0f + 0.5f; 00536 yoff = -bufsize/2.0f + 0.5f; 00537 rowbytes= bufsize*4; 00538 00539 if (*outbuf) 00540 ibuf= *outbuf; 00541 else 00542 ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag); 00543 00544 if (flt) { 00545 copy_v3_v3(brush_rgb, brush->rgb); 00546 if(use_color_correction){ 00547 srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); 00548 } 00549 00550 for (y=0; y < ibuf->y; y++) { 00551 dstf = ibuf->rect_float + y*rowbytes; 00552 00553 for (x=0; x < ibuf->x; x++, dstf+=4) { 00554 xy[0] = x + xoff; 00555 xy[1] = y + yoff; 00556 00557 if (texfall == 0) { 00558 copy_v3_v3(dstf, brush_rgb); 00559 dstf[3]= alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius); 00560 } 00561 else if (texfall == 1) { 00562 brush_sample_tex(scene, brush, xy, dstf, 0); 00563 } 00564 else { 00565 brush_sample_tex(scene, brush, xy, rgba, 0); 00566 mul_v3_v3v3(dstf, rgba, brush_rgb); 00567 dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius); 00568 } 00569 } 00570 } 00571 } 00572 else { 00573 float alpha_f; /* final float alpha to convert to char */ 00574 F3TOCHAR3(brush->rgb, crgb); 00575 00576 for (y=0; y < ibuf->y; y++) { 00577 dst = (char*)ibuf->rect + y*rowbytes; 00578 00579 for (x=0; x < ibuf->x; x++, dst+=4) { 00580 xy[0] = x + xoff; 00581 xy[1] = y + yoff; 00582 00583 if (texfall == 0) { 00584 alpha_f = alpha * brush_curve_strength(brush, len_v2(xy), radius); 00585 00586 dst[0] = crgb[0]; 00587 dst[1] = crgb[1]; 00588 dst[2] = crgb[2]; 00589 dst[3] = FTOCHAR(alpha_f); 00590 } 00591 else if (texfall == 1) { 00592 brush_sample_tex(scene, brush, xy, rgba, 0); 00593 dst[0] = FTOCHAR(rgba[0]); 00594 dst[1] = FTOCHAR(rgba[1]); 00595 dst[2] = FTOCHAR(rgba[2]); 00596 dst[3] = FTOCHAR(rgba[3]); 00597 } 00598 else if (texfall == 2) { 00599 brush_sample_tex(scene, brush, xy, rgba, 0); 00600 mul_v3_v3(rgba, brush->rgb); 00601 alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius); 00602 00603 dst[0] = FTOCHAR(rgba[0]); 00604 dst[1] = FTOCHAR(rgba[1]); 00605 dst[2] = FTOCHAR(rgba[2]); 00606 dst[3] = FTOCHAR(alpha_f); 00607 } 00608 else { 00609 brush_sample_tex(scene, brush, xy, rgba, 0); 00610 alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius); 00611 00612 dst[0] = crgb[0]; 00613 dst[1] = crgb[1]; 00614 dst[2] = crgb[2]; 00615 dst[3] = FTOCHAR(alpha_f); 00616 } 00617 } 00618 } 00619 } 00620 00621 *outbuf= ibuf; 00622 } 00623 00624 /* Unified Size and Strength */ 00625 00626 // XXX: be careful about setting size and unprojected radius 00627 // because they depend on one another 00628 // these functions do not set the other corresponding value 00629 // this can lead to odd behavior if size and unprojected 00630 // radius become inconsistent. 00631 // the biggest problem is that it isn't possible to change 00632 // unprojected radius because a view context is not 00633 // available. my ussual solution to this is to use the 00634 // ratio of change of the size to change the unprojected 00635 // radius. Not completely convinced that is correct. 00636 // In anycase, a better solution is needed to prevent 00637 // inconsistency. 00638 00639 void brush_set_size(Scene *scene, Brush *brush, int size) 00640 { 00641 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00642 00643 if (ups->flag & UNIFIED_PAINT_SIZE) 00644 ups->size= size; 00645 else 00646 brush->size= size; 00647 } 00648 00649 int brush_size(const Scene *scene, Brush *brush) 00650 { 00651 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00652 00653 return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size; 00654 } 00655 00656 int brush_use_locked_size(const Scene *scene, Brush *brush) 00657 { 00658 const short us_flag = scene->toolsettings->unified_paint_settings.flag; 00659 00660 return (us_flag & UNIFIED_PAINT_SIZE) ? 00661 (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) : 00662 (brush->flag & BRUSH_LOCK_SIZE); 00663 } 00664 00665 int brush_use_size_pressure(const Scene *scene, Brush *brush) 00666 { 00667 const short us_flag = scene->toolsettings->unified_paint_settings.flag; 00668 00669 return (us_flag & UNIFIED_PAINT_SIZE) ? 00670 (us_flag & UNIFIED_PAINT_BRUSH_SIZE_PRESSURE) : 00671 (brush->flag & BRUSH_SIZE_PRESSURE); 00672 } 00673 00674 int brush_use_alpha_pressure(const Scene *scene, Brush *brush) 00675 { 00676 const short us_flag = scene->toolsettings->unified_paint_settings.flag; 00677 00678 return (us_flag & UNIFIED_PAINT_ALPHA) ? 00679 (us_flag & UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE) : 00680 (brush->flag & BRUSH_ALPHA_PRESSURE); 00681 } 00682 00683 void brush_set_unprojected_radius(Scene *scene, Brush *brush, float unprojected_radius) 00684 { 00685 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00686 00687 if (ups->flag & UNIFIED_PAINT_SIZE) 00688 ups->unprojected_radius= unprojected_radius; 00689 else 00690 brush->unprojected_radius= unprojected_radius; 00691 } 00692 00693 float brush_unprojected_radius(const Scene *scene, Brush *brush) 00694 { 00695 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00696 00697 return (ups->flag & UNIFIED_PAINT_SIZE) ? 00698 ups->unprojected_radius : 00699 brush->unprojected_radius; 00700 } 00701 00702 static void brush_set_alpha(Scene *scene, Brush *brush, float alpha) 00703 { 00704 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00705 00706 if (ups->flag & UNIFIED_PAINT_ALPHA) 00707 ups->alpha= alpha; 00708 else 00709 brush->alpha= alpha; 00710 } 00711 00712 float brush_alpha(const Scene *scene, Brush *brush) 00713 { 00714 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; 00715 00716 return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha; 00717 } 00718 00719 /* scale unprojected radius to reflect a change in the brush's 2D size */ 00720 void brush_scale_unprojected_radius(float *unprojected_radius, 00721 int new_brush_size, 00722 int old_brush_size) 00723 { 00724 float scale = new_brush_size; 00725 /* avoid division by zero */ 00726 if(old_brush_size != 0) 00727 scale /= (float)old_brush_size; 00728 (*unprojected_radius) *= scale; 00729 } 00730 00731 /* scale brush size to reflect a change in the brush's unprojected radius */ 00732 void brush_scale_size(int *brush_size, 00733 float new_unprojected_radius, 00734 float old_unprojected_radius) 00735 { 00736 float scale = new_unprojected_radius; 00737 /* avoid division by zero */ 00738 if(old_unprojected_radius != 0) 00739 scale /= new_unprojected_radius; 00740 (*brush_size)= (int)((float)(*brush_size) * scale); 00741 } 00742 00743 /* Brush Painting */ 00744 00745 typedef struct BrushPainterCache { 00746 short enabled; 00747 00748 int size; /* size override, if 0 uses 2*brush_size(brush) */ 00749 short flt; /* need float imbuf? */ 00750 short texonly; /* no alpha, color or fallof, only texture in imbuf */ 00751 00752 int lastsize; 00753 float lastalpha; 00754 float lastjitter; 00755 00756 ImBuf *ibuf; 00757 ImBuf *texibuf; 00758 ImBuf *maskibuf; 00759 } BrushPainterCache; 00760 00761 struct BrushPainter { 00762 Scene *scene; 00763 Brush *brush; 00764 00765 float lastmousepos[2]; /* mouse position of last paint call */ 00766 00767 float accumdistance; /* accumulated distance of brush since last paint op */ 00768 float lastpaintpos[2]; /* position of last paint op */ 00769 float startpaintpos[2]; /* position of first paint */ 00770 00771 double accumtime; /* accumulated time since last paint op (airbrush) */ 00772 double lasttime; /* time of last update */ 00773 00774 float lastpressure; 00775 00776 short firsttouch; /* first paint op */ 00777 00778 float startsize; 00779 float startalpha; 00780 float startjitter; 00781 float startspacing; 00782 00783 BrushPainterCache cache; 00784 }; 00785 00786 BrushPainter *brush_painter_new(Scene *scene, Brush *brush) 00787 { 00788 BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter"); 00789 00790 painter->brush= brush; 00791 painter->scene= scene; 00792 painter->firsttouch= 1; 00793 painter->cache.lastsize= -1; /* force ibuf create in refresh */ 00794 00795 painter->startsize = brush_size(scene, brush); 00796 painter->startalpha = brush_alpha(scene, brush); 00797 painter->startjitter = brush->jitter; 00798 painter->startspacing = brush->spacing; 00799 00800 return painter; 00801 } 00802 00803 void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size) 00804 { 00805 if ((painter->cache.flt != flt) || (painter->cache.size != size) || 00806 ((painter->cache.texonly != texonly) && texonly)) { 00807 if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); 00808 if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); 00809 painter->cache.ibuf= painter->cache.maskibuf= NULL; 00810 painter->cache.lastsize= -1; /* force ibuf create in refresh */ 00811 } 00812 00813 if (painter->cache.flt != flt) { 00814 if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); 00815 painter->cache.texibuf= NULL; 00816 painter->cache.lastsize= -1; /* force ibuf create in refresh */ 00817 } 00818 00819 painter->cache.size= size; 00820 painter->cache.flt= flt; 00821 painter->cache.texonly= texonly; 00822 painter->cache.enabled= 1; 00823 } 00824 00825 void brush_painter_free(BrushPainter *painter) 00826 { 00827 Brush *brush = painter->brush; 00828 00829 brush_set_size(painter->scene, brush, painter->startsize); 00830 brush_set_alpha(painter->scene, brush, painter->startalpha); 00831 brush->jitter = painter->startjitter; 00832 brush->spacing = painter->startspacing; 00833 00834 if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); 00835 if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); 00836 if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); 00837 MEM_freeN(painter); 00838 } 00839 00840 static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos) 00841 { 00842 Scene *scene= painter->scene; 00843 Brush *brush= painter->brush; 00844 ImBuf *ibuf, *maskibuf, *texibuf; 00845 float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4]; 00846 char *b, *m, *t, *ot= NULL; 00847 int dotexold, origx= x, origy= y; 00848 const int radius= brush_size(painter->scene, brush); 00849 00850 xoff = -radius + 0.5f; 00851 yoff = -radius + 0.5f; 00852 xoff += (int)pos[0] - (int)painter->startpaintpos[0]; 00853 yoff += (int)pos[1] - (int)painter->startpaintpos[1]; 00854 00855 ibuf = painter->cache.ibuf; 00856 texibuf = painter->cache.texibuf; 00857 maskibuf = painter->cache.maskibuf; 00858 00859 dotexold = (oldtexibuf != NULL); 00860 00861 /* not sure if it's actually needed or it's a mistake in coords/sizes 00862 calculation in brush_painter_fixed_tex_partial_update(), but without this 00863 limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */ 00864 w = MIN2(w, ibuf->x); 00865 h = MIN2(h, ibuf->y); 00866 00867 if (painter->cache.flt) { 00868 for (; y < h; y++) { 00869 bf = ibuf->rect_float + (y*ibuf->x + origx)*4; 00870 tf = texibuf->rect_float + (y*texibuf->x + origx)*4; 00871 mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4; 00872 00873 if (dotexold) 00874 otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4; 00875 00876 for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) { 00877 if (dotexold) { 00878 copy_v3_v3(tf, otf); 00879 tf[3] = otf[3]; 00880 otf += 4; 00881 } 00882 else { 00883 xy[0] = x + xoff; 00884 xy[1] = y + yoff; 00885 00886 brush_sample_tex(scene, brush, xy, tf, 0); 00887 } 00888 00889 bf[0] = tf[0]*mf[0]; 00890 bf[1] = tf[1]*mf[1]; 00891 bf[2] = tf[2]*mf[2]; 00892 bf[3] = tf[3]*mf[3]; 00893 } 00894 } 00895 } 00896 else { 00897 for (; y < h; y++) { 00898 b = (char*)ibuf->rect + (y*ibuf->x + origx)*4; 00899 t = (char*)texibuf->rect + (y*texibuf->x + origx)*4; 00900 m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4; 00901 00902 if (dotexold) 00903 ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4; 00904 00905 for (x=origx; x < w; x++, b+=4, m+=4, t+=4) { 00906 if (dotexold) { 00907 t[0] = ot[0]; 00908 t[1] = ot[1]; 00909 t[2] = ot[2]; 00910 t[3] = ot[3]; 00911 ot += 4; 00912 } 00913 else { 00914 xy[0] = x + xoff; 00915 xy[1] = y + yoff; 00916 00917 brush_sample_tex(scene, brush, xy, rgba, 0); 00918 t[0]= FTOCHAR(rgba[0]); 00919 t[1]= FTOCHAR(rgba[1]); 00920 t[2]= FTOCHAR(rgba[2]); 00921 t[3]= FTOCHAR(rgba[3]); 00922 } 00923 00924 b[0] = t[0]*m[0]/255; 00925 b[1] = t[1]*m[1]/255; 00926 b[2] = t[2]*m[2]/255; 00927 b[3] = t[3]*m[3]/255; 00928 } 00929 } 00930 } 00931 } 00932 00933 static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) 00934 { 00935 const Scene *scene= painter->scene; 00936 Brush *brush= painter->brush; 00937 BrushPainterCache *cache= &painter->cache; 00938 ImBuf *oldtexibuf, *ibuf; 00939 int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2; 00940 const int diameter= 2*brush_size(scene, brush); 00941 00942 imbflag= (cache->flt)? IB_rectfloat: IB_rect; 00943 if (!cache->ibuf) 00944 cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag); 00945 ibuf= cache->ibuf; 00946 00947 oldtexibuf= cache->texibuf; 00948 cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag); 00949 00950 if (oldtexibuf) { 00951 srcx= srcy= 0; 00952 destx= (int)painter->lastpaintpos[0] - (int)pos[0]; 00953 desty= (int)painter->lastpaintpos[1] - (int)pos[1]; 00954 w= oldtexibuf->x; 00955 h= oldtexibuf->y; 00956 00957 IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h); 00958 } 00959 else { 00960 srcx= srcy= 0; 00961 destx= desty= 0; 00962 w= h= 0; 00963 } 00964 00965 x1= destx; 00966 y1= desty; 00967 x2= destx+w; 00968 y2= desty+h; 00969 00970 /* blend existing texture in new position */ 00971 if ((x1 < x2) && (y1 < y2)) 00972 brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos); 00973 00974 if (oldtexibuf) 00975 IMB_freeImBuf(oldtexibuf); 00976 00977 /* sample texture in new areas */ 00978 if ((0 < x1) && (0 < ibuf->y)) 00979 brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos); 00980 if ((x2 < ibuf->x) && (0 < ibuf->y)) 00981 brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos); 00982 if ((x1 < x2) && (0 < y1)) 00983 brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos); 00984 if ((x1 < x2) && (y2 < ibuf->y)) 00985 brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); 00986 } 00987 00988 static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction) 00989 { 00990 const Scene *scene= painter->scene; 00991 Brush *brush= painter->brush; 00992 BrushPainterCache *cache= &painter->cache; 00993 MTex *mtex= &brush->mtex; 00994 int size; 00995 short flt; 00996 const int diameter= 2*brush_size(scene, brush); 00997 const float alpha= brush_alpha(scene, brush); 00998 00999 if (diameter != cache->lastsize || 01000 alpha != cache->lastalpha || 01001 brush->jitter != cache->lastjitter) 01002 { 01003 if (cache->ibuf) { 01004 IMB_freeImBuf(cache->ibuf); 01005 cache->ibuf= NULL; 01006 } 01007 if (cache->maskibuf) { 01008 IMB_freeImBuf(cache->maskibuf); 01009 cache->maskibuf= NULL; 01010 } 01011 01012 flt= cache->flt; 01013 size= (cache->size)? cache->size: diameter; 01014 01015 if (brush->flag & BRUSH_FIXED_TEX) { 01016 brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); 01017 brush_painter_fixed_tex_partial_update(painter, pos); 01018 } 01019 else 01020 brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction); 01021 01022 cache->lastsize= diameter; 01023 cache->lastalpha= alpha; 01024 cache->lastjitter= brush->jitter; 01025 } 01026 else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { 01027 int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; 01028 int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; 01029 01030 if ((dx != 0) || (dy != 0)) 01031 brush_painter_fixed_tex_partial_update(painter, pos); 01032 } 01033 } 01034 01035 void brush_painter_break_stroke(BrushPainter *painter) 01036 { 01037 painter->firsttouch= 1; 01038 } 01039 01040 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure) 01041 { 01042 if (brush_use_alpha_pressure(painter->scene, brush)) 01043 brush_set_alpha(painter->scene, brush, MAX2(0.0f, painter->startalpha*pressure)); 01044 if (brush_use_size_pressure(painter->scene, brush)) 01045 brush_set_size(painter->scene, brush, MAX2(1.0f, painter->startsize*pressure)); 01046 if (brush->flag & BRUSH_JITTER_PRESSURE) 01047 brush->jitter = MAX2(0.0f, painter->startjitter*pressure); 01048 if (brush->flag & BRUSH_SPACING_PRESSURE) 01049 brush->spacing = MAX2(1.0f, painter->startspacing*(1.5f-pressure)); 01050 } 01051 01052 void brush_jitter_pos(const Scene *scene, Brush *brush, float pos[2], float jitterpos[2]) 01053 { 01054 int use_jitter= brush->jitter != 0; 01055 01056 /* jitter-ed brush gives weird and unpredictable result for this 01057 kinds of stroke, so manyally disable jitter usage (sergey) */ 01058 use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0; 01059 01060 if(use_jitter){ 01061 float rand_pos[2]; 01062 const int radius= brush_size(scene, brush); 01063 const int diameter= 2*radius; 01064 01065 // find random position within a circle of diameter 1 01066 do { 01067 rand_pos[0] = BLI_frand()-0.5f; 01068 rand_pos[1] = BLI_frand()-0.5f; 01069 } while (len_v2(rand_pos) > 0.5f); 01070 01071 jitterpos[0] = pos[0] + 2*rand_pos[0]*diameter*brush->jitter; 01072 jitterpos[1] = pos[1] + 2*rand_pos[1]*diameter*brush->jitter; 01073 } 01074 else { 01075 copy_v2_v2(jitterpos, pos); 01076 } 01077 } 01078 01079 int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction) 01080 { 01081 Scene *scene= painter->scene; 01082 Brush *brush= painter->brush; 01083 int totpaintops= 0; 01084 01085 if (pressure == 0.0f) { 01086 if(painter->lastpressure) // XXX - hack, operator misses 01087 pressure= painter->lastpressure; 01088 else 01089 pressure = 1.0f; /* zero pressure == not using tablet */ 01090 } 01091 if (painter->firsttouch) { 01092 /* paint exactly once on first touch */ 01093 painter->startpaintpos[0]= pos[0]; 01094 painter->startpaintpos[1]= pos[1]; 01095 01096 brush_apply_pressure(painter, brush, pressure); 01097 if (painter->cache.enabled) 01098 brush_painter_refresh_cache(painter, pos, use_color_correction); 01099 totpaintops += func(user, painter->cache.ibuf, pos, pos); 01100 01101 painter->lasttime= time; 01102 painter->firsttouch= 0; 01103 painter->lastpaintpos[0]= pos[0]; 01104 painter->lastpaintpos[1]= pos[1]; 01105 } 01106 #if 0 01107 else if (painter->brush->flag & BRUSH_AIRBRUSH) { 01108 float spacing, step, paintpos[2], dmousepos[2], len; 01109 double starttime, curtime= time; 01110 01111 /* compute brush spacing adapted to brush size */ 01112 spacing= brush->rate; //radius*brush->spacing*0.01f; 01113 01114 /* setup starting time, direction vector and accumulated time */ 01115 starttime= painter->accumtime; 01116 sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); 01117 len= normalize_v2(dmousepos); 01118 painter->accumtime += curtime - painter->lasttime; 01119 01120 /* do paint op over unpainted time distance */ 01121 while (painter->accumtime >= spacing) { 01122 step= (spacing - starttime)*len; 01123 paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step; 01124 paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step; 01125 01126 if (painter->cache.enabled) 01127 brush_painter_refresh_cache(painter); 01128 totpaintops += func(user, painter->cache.ibuf, 01129 painter->lastpaintpos, paintpos); 01130 01131 painter->lastpaintpos[0]= paintpos[0]; 01132 painter->lastpaintpos[1]= paintpos[1]; 01133 painter->accumtime -= spacing; 01134 starttime -= spacing; 01135 } 01136 01137 painter->lasttime= curtime; 01138 } 01139 #endif 01140 else { 01141 float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; 01142 float t, len, press; 01143 const int radius= brush_size(scene, brush); 01144 01145 /* compute brush spacing adapted to brush radius, spacing may depend 01146 on pressure, so update it */ 01147 brush_apply_pressure(painter, brush, painter->lastpressure); 01148 spacing= MAX2(1.0f, radius)*brush->spacing*0.01f; 01149 01150 /* setup starting distance, direction vector and accumulated distance */ 01151 startdistance= painter->accumdistance; 01152 sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); 01153 len= normalize_v2(dmousepos); 01154 painter->accumdistance += len; 01155 01156 if (brush->flag & BRUSH_SPACE) { 01157 /* do paint op over unpainted distance */ 01158 while ((len > 0.0f) && (painter->accumdistance >= spacing)) { 01159 step= spacing - startdistance; 01160 paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step; 01161 paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step; 01162 01163 t = step/len; 01164 press= (1.0f-t)*painter->lastpressure + t*pressure; 01165 brush_apply_pressure(painter, brush, press); 01166 spacing= MAX2(1.0f, radius)*brush->spacing*0.01f; 01167 01168 brush_jitter_pos(scene, brush, paintpos, finalpos); 01169 01170 if (painter->cache.enabled) 01171 brush_painter_refresh_cache(painter, finalpos, use_color_correction); 01172 01173 totpaintops += 01174 func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); 01175 01176 painter->lastpaintpos[0]= paintpos[0]; 01177 painter->lastpaintpos[1]= paintpos[1]; 01178 painter->accumdistance -= spacing; 01179 startdistance -= spacing; 01180 } 01181 } else { 01182 brush_jitter_pos(scene, brush, pos, finalpos); 01183 01184 if (painter->cache.enabled) 01185 brush_painter_refresh_cache(painter, finalpos, use_color_correction); 01186 01187 totpaintops += func(user, painter->cache.ibuf, pos, finalpos); 01188 01189 painter->lastpaintpos[0]= pos[0]; 01190 painter->lastpaintpos[1]= pos[1]; 01191 painter->accumdistance= 0; 01192 } 01193 01194 /* do airbrush paint ops, based on the number of paint ops left over 01195 from regular painting. this is a temporary solution until we have 01196 accurate time stamps for mouse move events */ 01197 if (brush->flag & BRUSH_AIRBRUSH) { 01198 double curtime= time; 01199 double painttime= brush->rate*totpaintops; 01200 01201 painter->accumtime += curtime - painter->lasttime; 01202 if (painter->accumtime <= painttime) 01203 painter->accumtime= 0.0; 01204 else 01205 painter->accumtime -= painttime; 01206 01207 while (painter->accumtime >= (double)brush->rate) { 01208 brush_apply_pressure(painter, brush, pressure); 01209 01210 brush_jitter_pos(scene, brush, pos, finalpos); 01211 01212 if (painter->cache.enabled) 01213 brush_painter_refresh_cache(painter, finalpos, use_color_correction); 01214 01215 totpaintops += 01216 func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); 01217 painter->accumtime -= (double)brush->rate; 01218 } 01219 01220 painter->lasttime= curtime; 01221 } 01222 } 01223 01224 painter->lastmousepos[0]= pos[0]; 01225 painter->lastmousepos[1]= pos[1]; 01226 painter->lastpressure= pressure; 01227 01228 brush_set_alpha(scene, brush, painter->startalpha); 01229 brush_set_size(scene, brush, painter->startsize); 01230 brush->jitter = painter->startjitter; 01231 brush->spacing = painter->startspacing; 01232 01233 return totpaintops; 01234 } 01235 01236 /* Uses the brush curve control to find a strength value between 0 and 1 */ 01237 float brush_curve_strength_clamp(Brush *br, float p, const float len) 01238 { 01239 if(p >= len) return 0; 01240 else p= p/len; 01241 01242 p= curvemapping_evaluateF(br->curve, 0, p); 01243 if(p < 0.0f) p= 0.0f; 01244 else if(p > 1.0f) p= 1.0f; 01245 return p; 01246 } 01247 /* same as above but can return negative values if the curve enables 01248 * used for sculpt only */ 01249 float brush_curve_strength(Brush *br, float p, const float len) 01250 { 01251 if(p >= len) 01252 p= 1.0f; 01253 else 01254 p= p/len; 01255 01256 return curvemapping_evaluateF(br->curve, 0, p); 01257 } 01258 01259 /* TODO: should probably be unified with BrushPainter stuff? */ 01260 unsigned int *brush_gen_texture_cache(Brush *br, int half_side) 01261 { 01262 unsigned int *texcache = NULL; 01263 MTex *mtex = &br->mtex; 01264 TexResult texres= {0}; 01265 int hasrgb, ix, iy; 01266 int side = half_side * 2; 01267 01268 if(mtex->tex) { 01269 float x, y, step = 2.0 / side, co[3]; 01270 01271 texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); 01272 01273 BKE_image_get_ibuf(mtex->tex->ima, NULL); 01274 01275 /*do normalized cannonical view coords for texture*/ 01276 for (y=-1.0, iy=0; iy<side; iy++, y += step) { 01277 for (x=-1.0, ix=0; ix<side; ix++, x += step) { 01278 co[0]= x; 01279 co[1]= y; 01280 co[2]= 0.0f; 01281 01282 /* This is copied from displace modifier code */ 01283 hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); 01284 01285 /* if the texture gave an RGB value, we assume it didn't give a valid 01286 * intensity, so calculate one (formula from do_material_tex). 01287 * if the texture didn't give an RGB value, copy the intensity across 01288 */ 01289 if(hasrgb & TEX_RGB) 01290 texres.tin = (0.35f * texres.tr + 0.45f * 01291 texres.tg + 0.2f * texres.tb); 01292 01293 texres.tin = texres.tin * 255.0f; 01294 ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin; 01295 ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin; 01296 ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin; 01297 ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin; 01298 } 01299 } 01300 } 01301 01302 return texcache; 01303 } 01304 01305 /**** Radial Control ****/ 01306 struct ImBuf *brush_gen_radial_control_imbuf(Brush *br) 01307 { 01308 ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture"); 01309 unsigned int *texcache; 01310 int side = 128; 01311 int half = side / 2; 01312 int i, j; 01313 01314 texcache = brush_gen_texture_cache(br, half); 01315 im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect"); 01316 im->x = im->y = side; 01317 01318 for(i=0; i<side; ++i) { 01319 for(j=0; j<side; ++j) { 01320 float magn= sqrt(pow(i - half, 2) + pow(j - half, 2)); 01321 im->rect_float[i*side + j]= brush_curve_strength_clamp(br, magn, half); 01322 } 01323 } 01324 01325 /* Modulate curve with texture */ 01326 if(texcache) { 01327 for(i=0; i<side; ++i) { 01328 for(j=0; j<side; ++j) { 01329 const int col= texcache[i*side+j]; 01330 im->rect_float[i*side+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; 01331 } 01332 } 01333 01334 MEM_freeN(texcache); 01335 } 01336 01337 return im; 01338 }