[Bf-blender-cvs] [28b9e3f9222] soc-2016-pbvh-painting: Merge branch 'master' into soc-2016-pbvh-painting
Campbell Barton
noreply at git.blender.org
Wed Sep 27 03:09:55 CEST 2017
Commit: 28b9e3f92220c38af81583b145dc42e39f14e34e
Author: Campbell Barton
Date: Wed Sep 27 11:19:21 2017 +1000
Branches: soc-2016-pbvh-painting
https://developer.blender.org/rB28b9e3f92220c38af81583b145dc42e39f14e34e
Merge branch 'master' into soc-2016-pbvh-painting
===================================================================
===================================================================
diff --cc source/blender/editors/sculpt_paint/paint_vertex.c
index 53e4f639540,729dd9dc57b..2d45bc5504d
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@@ -575,22 -605,13 +575,22 @@@ BLI_INLINE uint mcol_blend(uint col1, u
mfac = 255 - fac;
- cp1 = (unsigned char *)&col1;
- cp2 = (unsigned char *)&col2;
- cp = (unsigned char *)&col;
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
- cp[0] = divide_round_i((mfac * cp1[0] + fac * cp2[0]), 255);
- cp[1] = divide_round_i((mfac * cp1[1] + fac * cp2[1]), 255);
- cp[2] = divide_round_i((mfac * cp1[2] + fac * cp2[2]), 255);
+ /* Updated to use the rgb squared color model which blends nicer. */
+ int r1 = cp1[0] * cp1[0];
+ int g1 = cp1[1] * cp1[1];
+ int b1 = cp1[2] * cp1[2];
+
+ int r2 = cp2[0] * cp2[0];
+ int g2 = cp2[1] * cp2[1];
+ int b2 = cp2[2] * cp2[2];
+
- cp[0] = iroundf(sqrtf(divide_round_i((mfac * r1 + fac * r2), 255)));
- cp[1] = iroundf(sqrtf(divide_round_i((mfac * g1 + fac * g2), 255)));
- cp[2] = iroundf(sqrtf(divide_round_i((mfac * b1 + fac * b2), 255)));
++ cp[0] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * r1 + fac * r2), 255)));
++ cp[1] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * g1 + fac * g2), 255)));
++ cp[2] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * b1 + fac * b2), 255)));
cp[3] = 255;
return col;
@@@ -3237,492 -2721,73 +3237,492 @@@ static bool vpaint_stroke_test_start(bC
return 1;
}
-static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
- const unsigned int index, const float mval[2],
- const float brush_size_pressure, const float brush_alpha_pressure)
+static void do_vpaint_brush_calc_ave_color_cb_ex(
+ void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id)) {
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
+
+ StrokeCache *cache = ss->cache;
+ uint *lcol = data->lcol;
+ uint blend[3] = {0};
+ char *col;
+ data->ob->sculpt->modes.vwpaint.tot_loops_hit[n] = 0;
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+
+ SculptBrushTest test;
+ sculpt_brush_test_init(ss, &test);
+
+ /* For each vertex */
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test_fast(&test, vd.co)) {
+ const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
+ if (BKE_brush_curve_strength(data->brush, test.dist, cache->radius) > 0.0) {
+ /* If the vertex is selected for painting. */
+ const MVert *mv = &data->me->mvert[v_index];
+ if (!use_face_sel || mv->flag & SELECT) {
+ ss->modes.vwpaint.tot_loops_hit[n] += ss->modes.vwpaint.vert_to_loop[v_index].count;
+ /* if a vertex is within the brush region, then add it's color to the blend. */
+ for (int j = 0; j < ss->modes.vwpaint.vert_to_loop[v_index].count; j++) {
+ const int l_index = ss->modes.vwpaint.vert_to_loop[v_index].indices[j];
+ col = (char *)(&lcol[l_index]);
+ /* Color is squared to compensate the sqrt color encoding. */
+ blend[0] += col[0] * col[0];
+ blend[1] += col[1] * col[1];
+ blend[2] += col[2] * col[2];
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ data->ob->sculpt->modes.vwpaint.total_color[n][0] = blend[0];
+ data->ob->sculpt->modes.vwpaint.total_color[n][1] = blend[1];
+ data->ob->sculpt->modes.vwpaint.total_color[n][2] = blend[2];
+}
+
+static void handle_texture_brush(
+ SculptThreadedTaskData *data, PBVHVertexIter vd, float size_pressure, float alpha_pressure,
+ float *r_alpha, uint *r_color)
{
- ViewContext *vc = &vpd->vc;
- Brush *brush = BKE_paint_brush(&vp->paint);
- MPoly *mpoly = &me->mpoly[index];
- MLoop *ml;
- unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart;
- unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart;
- bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL;
- float alpha;
- int i, j;
- int totloop = mpoly->totloop;
+ SculptSession *ss = data->ob->sculpt;
+ CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
+ const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- int brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f);
+ float rgba[4];
+ float rgba_br[3];
- if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
- unsigned int blend[4] = {0};
- unsigned int tcol;
- char *col;
-
- for (j = 0; j < totloop; j++) {
- col = (char *)(lcol + j);
- blend[0] += col[0];
- blend[1] += col[1];
- blend[2] += col[2];
- blend[3] += col[3];
- }
-
- blend[0] = divide_round_i(blend[0], totloop);
- blend[1] = divide_round_i(blend[1], totloop);
- blend[2] = divide_round_i(blend[2], totloop);
- blend[3] = divide_round_i(blend[3], totloop);
- col = (char *)&tcol;
- col[0] = blend[0];
- col[1] = blend[1];
- col[2] = blend[2];
- col[3] = blend[3];
-
- vpd->paintcol = *((unsigned int *)col);
- }
-
- ml = me->mloop + mpoly->loopstart;
- for (i = 0; i < totloop; i++, ml++) {
- float rgba[4];
- unsigned int paintcol;
- alpha = calc_vp_alpha_col_dl(vp, vc, vpd->vpimat,
- &vpd->vertexcosnos[ml->v], mval,
- brush_size_pressure, brush_alpha_pressure, rgba);
-
- if (vpd->is_texbrush) {
- float rgba_br[3];
- rgb_uchar_to_float(rgba_br, (const unsigned char *)&vpd->paintcol);
- mul_v3_v3(rgba_br, rgba);
- rgb_float_to_uchar((unsigned char *)&paintcol, rgba_br);
+ *r_alpha = calc_vp_alpha_col_dl(
+ data->vp, &data->vpd->vc, data->vpd->vpimat,
+ &data->vpd->vertexcosnos[v_index], ss->cache->mouse, size_pressure, alpha_pressure, rgba);
+ rgb_uchar_to_float(rgba_br, (const uchar *)&data->vpd->paintcol);
+ mul_v3_v3(rgba_br, rgba);
+ rgb_float_to_uchar((uchar *)r_color, rgba_br);
+}
+
+static void do_vpaint_brush_draw_task_cb_ex(
+ void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
+
+ Brush *brush = data->brush;
+ StrokeCache *cache = ss->cache;
+ const float brush_strength = cache->bstrength;
+ uint *lcol = data->lcol;
+ Scene *scene = CTX_data_scene(data->C);
+ float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
+ get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+
+ SculptBrushTest test;
+ sculpt_brush_test_init(ss, &test);
+
+ /* For each vertex*/
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ /* Test to see if the vertex coordinates are within the spherical brush region. */
+ if (sculpt_brush_test(&test, vd.co)) {
+ /* Note: Grids are 1:1 with corners (aka loops).
+ * For grid based pbvh, take the vert whose loop cooresponds to the current grid.
+ * Otherwise, take the current vert. */
+ const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
+ const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
+ const MVert *mv = &data->me->mvert[v_index];
+
+ /* If the vertex is selected for painting. */
+ if (!use_face_sel || mv->flag & SELECT) {
+ /* Calc the dot prod. between ray norm on surf and current vert
+ * (ie splash prevention factor), and only paint front facing verts. */
+ const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
+ if (view_dot > 0.0f) {
+ const float brush_fade = BKE_brush_curve_strength(brush, test.dist, cache->radius);
+ uint color_final = data->vpd->paintcol;
+
+ /* If we're painting with a texture, sample the texture color and alpha. */
+ float tex_alpha = 1.0;
+ if (data->vpd->is_texbrush) {
+ handle_texture_brush(
+ data, vd, brush_size_pressure, brush_alpha_pressure,
+ &tex_alpha, &color_final);
+ }
+ /* For each poly owning this vert, paint each loop belonging to this vert. */
+ for (int j = 0; j < ss->modes.vwpaint.vert_to_poly[v_index].count; j++) {
+ const int p_index = ss->modes.vwpaint.vert_to_poly[v_index].indices[j];
+ const int l_index = ss->modes.vwpaint.vert_to_loop[v_index].indices[j];
+ BLI_assert(data->me->mloop[l_index].v == v_index);
+ const MPoly *mp = &data->me->mpoly[p_index];
+ if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ /* Get the previous loop color */
+ if (ss->modes.vwpaint.previous_color[l_index] == 0) {
+ ss->modes.vwpaint.previous_color[l_index] = lcol[l_index];
+ }
+ const float final_alpha =
+ 255 * brush_fade * brush_strength * view_dot *
+ tex_alpha * brush_alpha_pressure * grid_alpha;
+ /* Mix the new color with the original based on final_alpha. */
+ lcol[l_index] = vpaint_blend(
+ data->vp, lcol[l_index],
+ ss->modes.vwpaint.previous_color[l_index], color_final,
+ final_alpha, 255 * brush_strength);
+ }
+ }
+ }
+ }
}
- else
- paintcol = vpd->paintcol;
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_vpaint_brush_blur_task_cb_ex(
+ void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
+
+ Brush *brush = data->brush;
+ StrokeCache *cache = ss->cache;
+ const float brush_strength = cache->bstrength;
+ uint *lcol = dat
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list