Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/brush.cc
| Show All 32 Lines | |||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_paint.h" | #include "BKE_paint.h" | ||||
| #include "BKE_texture.h" | #include "BKE_texture.h" | ||||
| #include "IMB_colormanagement.h" | #include "IMB_colormanagement.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "NOD_texture_evaluate.hh" | |||||
| #include "RE_texture.h" /* RE_texture_evaluate */ | #include "RE_texture.h" /* RE_texture_evaluate */ | ||||
| #include "BLO_read_write.h" | #include "BLO_read_write.h" | ||||
| static void brush_init_data(ID *id) | static void brush_init_data(ID *id) | ||||
| { | { | ||||
| Brush *brush = (Brush *)id; | Brush *brush = (Brush *)id; | ||||
| BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(brush, id)); | BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(brush, id)); | ||||
| ▲ Show 20 Lines • Show All 1,509 Lines • ▼ Show 20 Lines | void BKE_brush_init_curves_sculpt_settings(Brush *brush) | ||||
| BrushCurvesSculptSettings *settings = brush->curves_sculpt_settings; | BrushCurvesSculptSettings *settings = brush->curves_sculpt_settings; | ||||
| settings->add_amount = 1; | settings->add_amount = 1; | ||||
| settings->points_per_curve = 8; | settings->points_per_curve = 8; | ||||
| settings->minimum_length = 0.01f; | settings->minimum_length = 0.01f; | ||||
| settings->curve_length = 0.3f; | settings->curve_length = 0.3f; | ||||
| settings->density_add_attempts = 100; | settings->density_add_attempts = 100; | ||||
| } | } | ||||
| struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode) | Brush *BKE_brush_first_search(Main *bmain, const eObjectMode ob_mode) | ||||
| { | { | ||||
| LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { | LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { | ||||
| if (brush->ob_mode & ob_mode) { | if (brush->ob_mode & ob_mode) { | ||||
| return brush; | return brush; | ||||
| } | } | ||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 375 Lines • ▼ Show 20 Lines | void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) | ||||
| cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; | cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; | ||||
| cumap->preset = preset; | cumap->preset = preset; | ||||
| cuma = b->curve->cm; | cuma = b->curve->cm; | ||||
| BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); | BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); | ||||
| BKE_curvemapping_changed(cumap, false); | BKE_curvemapping_changed(cumap, false); | ||||
| } | } | ||||
| float BKE_brush_sample_tex_3d(const Scene *scene, | static bool brush_sample_texco( | ||||
| const Brush *br, | const Scene *scene, const Brush *br, const MTex *mtex, const float point[3], float texco[3]) | ||||
| const float point[3], | |||||
| float rgba[4], | |||||
| const int thread, | |||||
| struct ImagePool *pool) | |||||
| { | { | ||||
| UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { | ||||
| const MTex *mtex = &br->mtex; | /* Use location directly as texture coordinate. */ | ||||
| float intensity = 1.0; | copy_v3_v3(texco, point); | ||||
| bool hasrgb = false; | |||||
| if (!mtex->tex) { | |||||
| intensity = 1; | |||||
| } | |||||
| else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { | |||||
| /* Get strength by feeding the vertex | |||||
| * location directly into a texture */ | |||||
| hasrgb = RE_texture_evaluate(mtex, point, thread, pool, false, false, &intensity, rgba); | |||||
| } | } | ||||
| else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { | else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { | ||||
| float rotation = -mtex->rot; | float rotation = -mtex->rot; | ||||
| const float point_2d[2] = {point[0], point[1]}; | const float point_2d[2] = {point[0], point[1]}; | ||||
| float x, y; | float x, y; | ||||
| float co[3]; | |||||
| x = point_2d[0] - br->stencil_pos[0]; | x = point_2d[0] - br->stencil_pos[0]; | ||||
| y = point_2d[1] - br->stencil_pos[1]; | y = point_2d[1] - br->stencil_pos[1]; | ||||
| if (rotation > 0.001f || rotation < -0.001f) { | if (rotation > 0.001f || rotation < -0.001f) { | ||||
| const float angle = atan2f(y, x) + rotation; | const float angle = atan2f(y, x) + rotation; | ||||
| const float flen = sqrtf(x * x + y * y); | const float flen = sqrtf(x * x + y * y); | ||||
| x = flen * cosf(angle); | x = flen * cosf(angle); | ||||
| y = flen * sinf(angle); | y = flen * sinf(angle); | ||||
| } | } | ||||
| if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) { | if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) { | ||||
| zero_v4(rgba); | return false; | ||||
| return 0.0f; | |||||
| } | } | ||||
| x /= (br->stencil_dimension[0]); | x /= (br->stencil_dimension[0]); | ||||
| y /= (br->stencil_dimension[1]); | y /= (br->stencil_dimension[1]); | ||||
| co[0] = x; | texco[0] = x; | ||||
| co[1] = y; | texco[1] = y; | ||||
| co[2] = 0.0f; | texco[2] = 0.0f; | ||||
| hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); | |||||
| } | } | ||||
| else { | else { | ||||
| const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | |||||
| float rotation = -mtex->rot; | float rotation = -mtex->rot; | ||||
| const float point_2d[2] = {point[0], point[1]}; | const float point_2d[2] = {point[0], point[1]}; | ||||
| float x = 0.0f, y = 0.0f; /* Quite warnings */ | float x = 0.0f, y = 0.0f; /* Quite warnings */ | ||||
| float invradius = 1.0f; /* Quite warnings */ | float invradius = 1.0f; /* Quite warnings */ | ||||
| float co[3]; | |||||
| if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { | if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { | ||||
| /* keep coordinates relative to mouse */ | /* keep coordinates relative to mouse */ | ||||
| rotation += ups->brush_rotation; | rotation += ups->brush_rotation; | ||||
| x = point_2d[0] - ups->tex_mouse[0]; | x = point_2d[0] - ups->tex_mouse[0]; | ||||
| y = point_2d[1] - ups->tex_mouse[1]; | y = point_2d[1] - ups->tex_mouse[1]; | ||||
| Show All 28 Lines | else { | ||||
| if (rotation > 0.001f || rotation < -0.001f) { | if (rotation > 0.001f || rotation < -0.001f) { | ||||
| const float angle = atan2f(y, x) + rotation; | const float angle = atan2f(y, x) + rotation; | ||||
| const float flen = sqrtf(x * x + y * y); | const float flen = sqrtf(x * x + y * y); | ||||
| x = flen * cosf(angle); | x = flen * cosf(angle); | ||||
| y = flen * sinf(angle); | y = flen * sinf(angle); | ||||
| } | } | ||||
| co[0] = x; | texco[0] = x; | ||||
| co[1] = y; | texco[1] = y; | ||||
| co[2] = 0.0f; | texco[2] = 0.0f; | ||||
| } | |||||
| RE_texture_mapping_transform(mtex, texco, texco); | |||||
| hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); | return true; | ||||
| } | |||||
| void BKE_brush_sample_tex_intensity(const Scene *scene, | |||||
| const Brush *br, | |||||
| const int num_points, | |||||
| const float (*points)[3], | |||||
| float *r_intensity, | |||||
| const int thread, | |||||
| struct ImagePool *UNUSED(pool)) | |||||
| { | |||||
| const MTex *mtex = &br->mtex; | |||||
| if (mtex->tex == NULL) { | |||||
| for (int i = 0; i < num_points; i++) { | |||||
| r_intensity[i] = 1.0f; | |||||
| } | |||||
| return; | |||||
| } | } | ||||
| intensity += br->texture_sample_bias; | if (num_points == 1) { | ||||
| float texco[3]; | |||||
| if (brush_sample_texco(scene, br, mtex, points[0], texco)) { | |||||
| blender::nodes::texture_evaluate_single( | |||||
| mtex->tex, blender::float3(texco), thread, r_intensity); | |||||
| } | |||||
| else { | |||||
| *r_intensity = 0.0f; | |||||
| } | |||||
| } | |||||
| else { | |||||
| blender::nodes::TextureBatch batch(mtex->tex, num_points); | |||||
| blender::Vector<int64_t> mask; | |||||
| if (!hasrgb) { | for (int i = 0; i < num_points; i++) { | ||||
| rgba[0] = intensity; | if (brush_sample_texco(scene, br, mtex, points[i], &batch.positions[i].x)) { | ||||
| rgba[1] = intensity; | mask.append(i); | ||||
| rgba[2] = intensity; | } | ||||
| rgba[3] = 1.0f; | else { | ||||
| r_intensity[i] = 0.0f; | |||||
| } | } | ||||
| /* For consistency, sampling always returns color in linear space */ | |||||
| else if (ups->do_linear_conversion) { | |||||
| IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, ups->colorspace); | |||||
| } | } | ||||
| return intensity; | batch.evaluate(blender::MutableSpan(r_intensity, num_points), blender::IndexMask(mask)); | ||||
| if (br->texture_sample_bias != 0.0f) { | |||||
| for (int i = 0; i < mask.size(); i++) { | |||||
| r_intensity[mask[i]] += br->texture_sample_bias; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| float BKE_brush_sample_masktex( | void BKE_brush_sample_tex_rgba(const Scene *scene, | ||||
| const Scene *scene, Brush *br, const float point[2], const int thread, struct ImagePool *pool) | const Brush *br, | ||||
| const int num_points, | |||||
| const float (*points)[3], | |||||
| float (*r_rgba)[4], | |||||
| const int thread, | |||||
| struct ImagePool *pool) | |||||
| { | { | ||||
| UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | const MTex *mtex = &br->mtex; | ||||
| MTex *mtex = &br->mask_mtex; | |||||
| float rgba[4], intensity; | if (mtex->tex == NULL) { | ||||
| for (int i = 0; i < num_points; i++) { | |||||
| copy_v4_fl(r_rgba[i], 1.0f); | |||||
| } | |||||
| return; | |||||
| } | |||||
| if (num_points == 1) { | |||||
| float texco[3]; | |||||
| if (brush_sample_texco(scene, br, mtex, points[0], texco)) { | |||||
| blender::nodes::texture_evaluate_single( | |||||
| mtex->tex, blender::float3(texco), thread, (blender::float4 *)r_rgba[0]); | |||||
| } | |||||
| else { | |||||
| zero_v4(r_rgba[0]); | |||||
| } | |||||
| } | |||||
| else { | |||||
| blender::nodes::TextureBatch batch(mtex->tex, num_points); | |||||
| blender::Vector<int64_t> mask; | |||||
| if (!mtex->tex) { | for (int i = 0; i < num_points; i++) { | ||||
| return 1.0f; | if (brush_sample_texco(scene, br, mtex, points[i], &batch.positions[i].x)) { | ||||
| mask.append(i); | |||||
| } | } | ||||
| else { | |||||
| zero_v4(r_rgba[i]); | |||||
| } | |||||
| } | |||||
| batch.evaluate(blender::MutableSpan((blender::float4 *)r_rgba, num_points), | |||||
| blender::IndexMask(mask)); | |||||
| } | |||||
| /* TODO: obsolete for new texture nodes. */ | |||||
| #if 0 | |||||
| /* Do colorspace conversion here, as it was skipped in RE_texture_evaluate_mtex to | |||||
| * avoid bad performance with mutex locks. */ | |||||
| const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | |||||
| if (ups->do_linear_conversion) { | |||||
| for (int i = 0; i < num_points; i++) { | |||||
| IMB_colormanagement_colorspace_to_scene_linear_v3(r_rgba[i], ups->colorspace); | |||||
| } | |||||
| } | |||||
| #endif | |||||
| } | |||||
| static bool brush_sample_mask_texco( | |||||
| const Scene *scene, const Brush *br, const MTex *mtex, const float point[2], float texco[3]) | |||||
| { | |||||
| if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { | if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { | ||||
| float rotation = -mtex->rot; | float rotation = -mtex->rot; | ||||
| const float point_2d[2] = {point[0], point[1]}; | const float point_2d[2] = {point[0], point[1]}; | ||||
| float x, y; | float x, y; | ||||
| float co[3]; | |||||
| x = point_2d[0] - br->mask_stencil_pos[0]; | x = point_2d[0] - br->mask_stencil_pos[0]; | ||||
| y = point_2d[1] - br->mask_stencil_pos[1]; | y = point_2d[1] - br->mask_stencil_pos[1]; | ||||
| if (rotation > 0.001f || rotation < -0.001f) { | if (rotation > 0.001f || rotation < -0.001f) { | ||||
| const float angle = atan2f(y, x) + rotation; | const float angle = atan2f(y, x) + rotation; | ||||
| const float flen = sqrtf(x * x + y * y); | const float flen = sqrtf(x * x + y * y); | ||||
| x = flen * cosf(angle); | x = flen * cosf(angle); | ||||
| y = flen * sinf(angle); | y = flen * sinf(angle); | ||||
| } | } | ||||
| if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) { | if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) { | ||||
| zero_v4(rgba); | return false; | ||||
| return 0.0f; | |||||
| } | } | ||||
| x /= (br->mask_stencil_dimension[0]); | x /= (br->mask_stencil_dimension[0]); | ||||
| y /= (br->mask_stencil_dimension[1]); | y /= (br->mask_stencil_dimension[1]); | ||||
| co[0] = x; | texco[0] = x; | ||||
| co[1] = y; | texco[1] = y; | ||||
| co[2] = 0.0f; | texco[2] = 0.0f; | ||||
| RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); | |||||
| } | } | ||||
| else { | else { | ||||
| const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | |||||
| float rotation = -mtex->rot; | float rotation = -mtex->rot; | ||||
| const float point_2d[2] = {point[0], point[1]}; | const float point_2d[2] = {point[0], point[1]}; | ||||
| float x = 0.0f, y = 0.0f; /* Quite warnings */ | float x = 0.0f, y = 0.0f; /* Quite warnings */ | ||||
| float invradius = 1.0f; /* Quite warnings */ | float invradius = 1.0f; /* Quite warnings */ | ||||
| float co[3]; | |||||
| if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { | if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { | ||||
| /* keep coordinates relative to mouse */ | /* keep coordinates relative to mouse */ | ||||
| rotation += ups->brush_rotation_sec; | rotation += ups->brush_rotation_sec; | ||||
| x = point_2d[0] - ups->mask_tex_mouse[0]; | x = point_2d[0] - ups->mask_tex_mouse[0]; | ||||
| y = point_2d[1] - ups->mask_tex_mouse[1]; | y = point_2d[1] - ups->mask_tex_mouse[1]; | ||||
| Show All 28 Lines | else { | ||||
| if (rotation > 0.001f || rotation < -0.001f) { | if (rotation > 0.001f || rotation < -0.001f) { | ||||
| const float angle = atan2f(y, x) + rotation; | const float angle = atan2f(y, x) + rotation; | ||||
| const float flen = sqrtf(x * x + y * y); | const float flen = sqrtf(x * x + y * y); | ||||
| x = flen * cosf(angle); | x = flen * cosf(angle); | ||||
| y = flen * sinf(angle); | y = flen * sinf(angle); | ||||
| } | } | ||||
| co[0] = x; | texco[0] = x; | ||||
| co[1] = y; | texco[1] = y; | ||||
| co[2] = 0.0f; | texco[2] = 0.0f; | ||||
| } | |||||
| RE_texture_mapping_transform(mtex, texco, texco); | |||||
| RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); | return true; | ||||
| } | } | ||||
| CLAMP(intensity, 0.0f, 1.0f); | void BKE_brush_sample_tex_mask(const Scene *scene, | ||||
| const Brush *br, | |||||
| const int num_points, | |||||
| const float (*points)[3], | |||||
| float *r_masks, | |||||
| const int thread, | |||||
| struct ImagePool *pool) | |||||
| { | |||||
| const MTex *mtex = &br->mask_mtex; | |||||
| const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | |||||
| if (mtex->tex == NULL) { | |||||
| for (int i = 0; i < num_points; i++) { | |||||
| r_masks[i] = 1.0f; | |||||
| } | |||||
| return; | |||||
| } | |||||
| if (num_points == 1) { | |||||
| float texco[3]; | |||||
| if (brush_sample_mask_texco(scene, br, mtex, points[0], texco)) { | |||||
| blender::nodes::texture_evaluate_single(mtex->tex, blender::float3(texco), thread, r_masks); | |||||
| } | |||||
| else { | |||||
| r_masks[0] = 0.0f; | |||||
| } | |||||
| } | |||||
| else { | |||||
| blender::nodes::TextureBatch batch(mtex->tex, num_points); | |||||
| blender::Vector<int64_t> mask; | |||||
| for (int i = 0; i < num_points; i++) { | |||||
| if (brush_sample_mask_texco(scene, br, mtex, points[i], &batch.positions[i].x)) { | |||||
| mask.append(i); | |||||
| } | |||||
| else { | |||||
| r_masks[i] = 0.0f; | |||||
| } | |||||
| } | |||||
| batch.evaluate(blender::MutableSpan(r_masks, num_points), blender::IndexMask(mask)); | |||||
| } | |||||
| for (int i = 0; i < num_points; i++) { | |||||
| CLAMP(r_masks[i], 0.0f, 1.0f); | |||||
| switch (br->mask_pressure) { | switch (br->mask_pressure) { | ||||
| case BRUSH_MASK_PRESSURE_CUTOFF: | case BRUSH_MASK_PRESSURE_CUTOFF: | ||||
| intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f; | r_masks[i] = ((1.0f - r_masks[i]) < ups->size_pressure_value) ? 1.0f : 0.0f; | ||||
| break; | break; | ||||
| case BRUSH_MASK_PRESSURE_RAMP: | case BRUSH_MASK_PRESSURE_RAMP: | ||||
| intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value); | r_masks[i] = ups->size_pressure_value + r_masks[i] * (1.0f - ups->size_pressure_value); | ||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| } | |||||
| return intensity; | |||||
| } | } | ||||
| /* Unified Size / Strength / Color */ | /* Unified Size / Strength / Color */ | ||||
| /* XXX: be careful about setting size and unprojected radius | /* XXX: be careful about setting size and unprojected radius | ||||
| * because they depend on one another | * because they depend on one another | ||||
| * these functions do not set the other corresponding value | * these functions do not set the other corresponding value | ||||
| * this can lead to odd behavior if size and unprojected | * this can lead to odd behavior if size and unprojected | ||||
| * radius become inconsistent. | * radius become inconsistent. | ||||
| * the biggest problem is that it isn't possible to change | * the biggest problem is that it isn't possible to change | ||||
| * unprojected radius because a view context is not | * unprojected radius because a view context is not | ||||
| * available. my usual solution to this is to use the | * available. my usual solution to this is to use the | ||||
| * ratio of change of the size to change the unprojected | * ratio of change of the size to change the unprojected | ||||
| * radius. Not completely convinced that is correct. | * radius. Not completely convinced that is correct. | ||||
| * In any case, a better solution is needed to prevent | * In any case, a better solution is needed to prevent | ||||
| * inconsistency. */ | * inconsistency. */ | ||||
| const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush) | const float *BKE_brush_color_get(const Scene *scene, const Brush *brush) | ||||
| { | { | ||||
| UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | ||||
| return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb; | return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb; | ||||
| } | } | ||||
| const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush) | const float *BKE_brush_secondary_color_get(const Scene *scene, const Brush *brush) | ||||
| { | { | ||||
| UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | const UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | ||||
| return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb; | return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb; | ||||
| } | } | ||||
| void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]) | void BKE_brush_color_set(Scene *scene, Brush *brush, const float color[3]) | ||||
| { | { | ||||
| UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; | ||||
| if (ups->flag & UNIFIED_PAINT_COLOR) { | if (ups->flag & UNIFIED_PAINT_COLOR) { | ||||
| copy_v3_v3(ups->rgb, color); | copy_v3_v3(ups->rgb, color); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(brush->rgb, color); | copy_v3_v3(brush->rgb, color); | ||||
| ▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | static bool brush_gen_texture(const Brush *br, | ||||
| if (mtex->tex == nullptr) { | if (mtex->tex == nullptr) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| const float step = 2.0 / side; | const float step = 2.0 / side; | ||||
| int ix, iy; | int ix, iy; | ||||
| float x, y; | float x, y; | ||||
| /* Do normalized canonical view coords for texture. */ | blender::nodes::TextureBatch batch(mtex->tex, side * side); | ||||
| /* Compute normalized canonical view texture coords. */ | |||||
| for (y = -1.0, iy = 0; iy < side; iy++, y += step) { | for (y = -1.0, iy = 0; iy < side; iy++, y += step) { | ||||
| for (x = -1.0, ix = 0; ix < side; ix++, x += step) { | for (x = -1.0, ix = 0; ix < side; ix++, x += step) { | ||||
| const float co[3] = {x, y, 0.0f}; | const float co[3] = {x, y, 0.0f}; | ||||
| RE_texture_mapping_transform(mtex, co, &batch.positions[iy * side + ix].x); | |||||
| float intensity; | |||||
| float rgba_dummy[4]; | |||||
| RE_texture_evaluate(mtex, co, 0, nullptr, false, false, &intensity, rgba_dummy); | |||||
| rect[iy * side + ix] = intensity; | |||||
| } | } | ||||
| } | } | ||||
| /* Evaluate texture. */ | |||||
| batch.evaluate(blender::MutableSpan(rect, side * side), blender::IndexRange(side * side)); | |||||
| return true; | return true; | ||||
| } | } | ||||
| struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient) | ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient) | ||||
| { | { | ||||
| ImBuf *im = MEM_cnew<ImBuf>("radial control texture"); | ImBuf *im = MEM_cnew<ImBuf>("radial control texture"); | ||||
| int side = 512; | int side = 512; | ||||
| int half = side / 2; | int half = side / 2; | ||||
| BKE_curvemapping_init(br->curve); | BKE_curvemapping_init(br->curve); | ||||
| im->rect_float = (float *)MEM_callocN(sizeof(float) * side * side, "radial control rect"); | im->rect_float = (float *)MEM_callocN(sizeof(float) * side * side, "radial control rect"); | ||||
| im->x = im->y = side; | im->x = im->y = side; | ||||
| Show All 14 Lines | |||||