Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Hamalainen <blender@miikah.org>2012-01-16 21:18:07 +0400
committerMiika Hamalainen <blender@miikah.org>2012-01-16 21:18:07 +0400
commit4d9197866b40fec9884236c05053d85fe6d0255f (patch)
tree5a7c1bbf49712f9315861eb9b8d35160b5128b10 /source/blender/blenkernel/intern/dynamicpaint.c
parente81f2853c8785b0a84ecebf7c4db433af434c5c8 (diff)
Dynamic Paint:
* Added per surface options "influence scale" and "radius scale" for tweaking brush settings individually for each surface. * Added option to completely disable drying. This should be nice for indefinitely spreading paint etc. * Improved paint mixing algorithm. * "Paint effects" now work in relative mesh space instead of global. This means that effect speed remains same for identical shapes regardless of their size. * Complete rewrite of "spread effect" algorithm. It now works much better in all test cases done. Old algo sometimes produced artifacts and stopped spreading too early. * Adjustments / rewrite on some parts of dripping algorithm to make it work better with transparent paint. * Added a new "color dry" setting. It can be used to define wetness level when paint colors start to shift to surface "background". Lower values can be useful to prevent spreading paint from becoming transparent as it dries, while higher (default) values give better results in general. * Fix: If multiple displace/wave surfaces were used simultaneously, displace was applied using wrong normal. Please note that due to these changes in "paint effects" system older save files may require some tweaking to match results from previous versions.
Diffstat (limited to 'source/blender/blenkernel/intern/dynamicpaint.c')
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c303
1 files changed, 160 insertions, 143 deletions
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index f93aee80ab8..a9e612b08e0 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -101,9 +101,10 @@ static int neighY[8] = {0,1,1, 1, 0,-1,-1,-1};
#define EFF_MOVEMENT_PER_FRAME 0.05f
/* initial wave time factor */
#define WAVE_TIME_FAC (1.0f/24.f)
-#define WAVE_INIT_SIZE 5.0f
+#define CANVAS_REL_SIZE 5.0f
/* drying limits */
#define MIN_WETNESS 0.001f
+#define MAX_WETNESS 5.0f
/* dissolve macro */
#define VALUE_DISSOLVE(VALUE, TIME, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) * (pow(MIN_WETNESS,1.0f/(1.2f*((float)(TIME))/(SCALE)))) : (VALUE) - 1.0f/(TIME)*(SCALE)
@@ -422,15 +423,31 @@ static void blendColors(float t_color[3], float t_alpha, float s_color[3], float
result[3] = f_alpha;
}
-/* assumes source alpha > 0.0f or results NaN colors */
-static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alpha)
+/* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */
+static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio)
{
- float factor = (s_alpha<t_alpha) ? 1.0f : t_alpha/s_alpha;
+ float weight_ratio, factor;
+ if (b_weight) {
+ /* if first value has no weight just use b_color */
+ if (!a_weight) {
+ copy_v3_v3(a_color, b_color);
+ return b_weight*ratio;
+ }
+ weight_ratio = b_weight/(a_weight+b_weight);
+ }
+ else return a_weight*(1.0f-ratio);
- /* set initial color depending on existing alpha */
- interp_v3_v3v3(t_color, s_color, t_color, factor);
+ /* calculate final interpolation factor */
+ if (ratio<=0.5f) {
+ factor = weight_ratio*(ratio*2.0f);
+ }
+ else {
+ ratio = (ratio*2.0f - 1.0f);
+ factor = weight_ratio*(1.0f-ratio) + ratio;
+ }
/* mix final color */
- interp_v3_v3v3(t_color, t_color, s_color, s_alpha);
+ interp_v3_v3v3(a_color, a_color, b_color, factor);
+ return (1.0f-factor)*a_weight + factor*b_weight;
}
/* set "ignore cache" flag for all caches on this object */
@@ -617,6 +634,12 @@ static void boundInsert(Bounds3D *b, float point[3])
}
}
+float getSurfaceDimension(PaintSurfaceData *sData)
+{
+ Bounds3D *mb = &sData->bData->mesh_bounds;
+ return MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
+}
+
static void freeGrid(PaintSurfaceData *data)
{
PaintBakeData *bData = data->bData;
@@ -959,17 +982,21 @@ struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSett
/* Set initial values */
surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG |
- MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1;
+ MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING;
surface->effect = 0;
surface->effect_ui = 1;
surface->diss_speed = 250;
surface->dry_speed = 500;
+ surface->color_dry_threshold = 1.0f;
surface->depth_clamp = 0.0f;
surface->disp_factor = 1.0f;
surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
+ surface->influence_scale = 1.0f;
+ surface->radius_scale = 1.0f;
+
surface->init_color[0] = 1.0f;
surface->init_color[1] = 1.0f;
surface->init_color[2] = 1.0f;
@@ -1508,7 +1535,7 @@ static int dynamicPaint_checkSurfaceData(DynamicPaintSurface *surface)
/* apply displacing vertex surface to the derived mesh */
-static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result, int update_normals)
+static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result)
{
PaintSurfaceData *sData = surface->data;
@@ -1531,10 +1558,6 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Deri
mvert[i].co[2] -= normal[2]*val;
}
}
- else return;
-
- if (update_normals)
- CDDM_calc_normals(result);
}
/*
@@ -1549,6 +1572,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
+ int update_normals = 0;
pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY;
/* loop through surfaces */
@@ -1748,14 +1772,20 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
normal_short_to_float_v3(normal, mvert[i].no);
madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height);
}
- CDDM_calc_normals(result);
+ update_normals = 1;
}
/* displace */
- dynamicPaint_applySurfaceDisplace(surface, result, 1);
+ if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
+ dynamicPaint_applySurfaceDisplace(surface, result);
+ update_normals = 1;
+ }
}
}
}
+
+ if (update_normals)
+ CDDM_calc_normals(result);
}
/* make a copy of dm to use as brush data */
if (pmd->brush) {
@@ -2574,14 +2604,8 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char* filenam
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
- ibuf->rect_float[pos] = point->color[0];
- ibuf->rect_float[pos+1] = point->color[1];
- ibuf->rect_float[pos+2] = point->color[2];
- /* mix wet layer */
- if (point->e_alpha) mixColors(&ibuf->rect_float[pos], point->alpha, point->e_color, point->e_alpha);
-
- /* use highest alpha */
- ibuf->rect_float[pos+3] = (point->e_alpha > point->alpha) ? point->e_alpha : point->alpha;
+ /* blend wet and dry layers */
+ blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]);
/* Multiply color by alpha if enabled */
if (surface->flags & MOD_DPAINT_MULALPHA) {
@@ -2912,7 +2936,13 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
float paint[3], float influence, float depth, float vel_factor, float timescale)
{
PaintSurfaceData *sData = surface->data;
- float strength = influence * brush->alpha;
+ float strength;
+
+ /* apply influence scale */
+ influence *= surface->influence_scale;
+ depth *= surface->influence_scale;
+
+ strength = influence * brush->alpha;
CLAMP(strength, 0.0f, 1.0f);
/* Sample velocity colorband if required */
@@ -2991,12 +3021,12 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
}
/* checks whether surface and brush bounds intersect depending on brush type */
-static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush)
+static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush, float brush_radius)
{
if (brush->collision == MOD_DPAINT_COL_VOLUME)
return boundsIntersect(b1, b2);
else if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST)
- return boundsIntersectDist(b1, b2, brush->paint_distance);
+ return boundsIntersectDist(b1, b2, brush_radius);
else return 1;
}
@@ -3123,6 +3153,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
{
BVHTreeFromMesh treeData = {0};
float avg_brushNor[3] = {0.0f};
+ float brush_radius = brush->paint_distance * surface->radius_scale;
int numOfVerts;
int ii;
Bounds3D mesh_bb = {0};
@@ -3161,7 +3192,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
}
/* check bounding box collision */
- if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush))
+ if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius))
/* Build a bvh tree from transformed vertices */
if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8))
{
@@ -3173,7 +3204,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
int id;
/* check grid cell bounding box */
- if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush))
+ if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius))
continue;
/* loop through cell points and process brush */
@@ -3234,7 +3265,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
hit.index = -1;
hit.dist = 9999;
nearest.index = -1;
- nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest uses squared distance */
+ nearest.dist = brush_radius * brush_radius; /* find_nearest uses squared distance */
/* Check volume collision */
if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
@@ -3294,7 +3325,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
/* If pure distance proximity, find the nearest point on the mesh */
if (brush->collision != MOD_DPAINT_COL_DIST || !(brush->flags & MOD_DPAINT_PROX_PROJECT)) {
if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
- proxDist = sqrt(nearest.dist);
+ proxDist = sqrtf(nearest.dist);
copy_v3_v3(hitCo, nearest.co);
hQuad = (nearest.no[0] == 1.0f);
face = nearest.index;
@@ -3314,7 +3345,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
proj_ray[2] = 1.0f;
}
hit.index = -1;
- hit.dist = brush->paint_distance;
+ hit.dist = brush_radius;
/* Do a face normal directional raycast, and use that distance */
if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
@@ -3327,8 +3358,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
}
/* If a hit was found, calculate required values */
- if (proxDist >= 0.0f && proxDist <= brush->paint_distance) {
- proximity_factor = proxDist / brush->paint_distance;
+ if (proxDist >= 0.0f && proxDist <= brush_radius) {
+ proximity_factor = proxDist / brush_radius;
CLAMP(proximity_factor, 0.0f, 1.0f);
if (!inner_proximity)
proximity_factor = 1.0f - proximity_factor;
@@ -3514,8 +3545,8 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
int invalidParticles = 0;
int p = 0;
- float solidradius = (brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius;
- float smooth = brush->particle_smooth;
+ float solidradius = surface->radius_scale*((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius);
+ float smooth = brush->particle_smooth*surface->radius_scale;
float range = solidradius + smooth;
float particle_timestep = 0.04f * part->timetweak;
@@ -3744,6 +3775,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
{
int index;
+ float brush_radius = brush->paint_distance * surface->radius_scale;
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
Vec3f brushVel;
@@ -3761,13 +3793,13 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
float colorband[4] = {0.0f};
float strength;
- if (distance>brush->paint_distance) continue;
+ if (distance > brush_radius) continue;
/* Smooth range or color ramp */
if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH ||
brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) {
- strength = 1.0f - distance / brush->paint_distance;
+ strength = 1.0f - distance / brush_radius;
CLAMP(strength, 0.0f, 1.0f);
}
else strength = 1.0f;
@@ -3832,8 +3864,8 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
/* get displace depth */
- float disp_intersect = (1.0f - sqrtf((brush->paint_distance-distance) / brush->paint_distance)) * brush->paint_distance;
- depth = (brush->paint_distance - disp_intersect) / bData->bNormal[index].normal_scale;
+ float disp_intersect = (1.0f - sqrtf((brush_radius-distance) / brush_radius)) * brush_radius;
+ depth = (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale;
if (depth<0.0f) depth = 0.0f;
}
dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
@@ -3936,7 +3968,7 @@ void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, floa
if (closest_id[1] != -1) {
float force_proj[3];
float tangent[3];
- float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
+ float neigh_diff = acosf(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
float force_intersect;
float temp;
@@ -4008,7 +4040,6 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
if (n_index != -1 && closest_d[i]>0.0f) {
float dir_dot = closest_d[i], dir_factor;
float speed_scale = eff_scale*smudge_str/bNeighs[n_index].dist;
- float mix;
PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
/* just skip if angle is too extreme */
@@ -4018,13 +4049,11 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength;
/* mix new color and alpha */
- mix = dir_factor*pPoint->alpha;
- if (mix) mixColors(ePoint->color, ePoint->alpha, pPoint->color, mix);
+ mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor);
ePoint->alpha = ePoint->alpha*(1.0f-dir_factor) + pPoint->alpha*dir_factor;
/* smudge "wet layer" */
- mix = dir_factor*pPoint->e_alpha;
- if (mix) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, mix);
+ mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor);
ePoint->e_alpha = ePoint->e_alpha*(1.0f-dir_factor) + pPoint->e_alpha*dir_factor;
pPoint->wetness *= (1.0f-dir_factor);
}
@@ -4041,7 +4070,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
{
double average_force = 0.0f;
float shrink_speed=0.0f, spread_speed=0.0f;
- float fastest_effect;
+ float fastest_effect, avg_dist;
int steps;
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -4118,9 +4147,10 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
shrink_speed = surface->shrink_speed;
fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
+ avg_dist = bData->average_dist*CANVAS_REL_SIZE/getSurfaceDimension(sData);
- steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/bData->average_dist*timescale);
- CLAMP(steps, 1, 14);
+ steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/avg_dist*timescale);
+ CLAMP(steps, 1, 20);
return steps;
}
@@ -4132,6 +4162,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
{
PaintSurfaceData *sData = surface->data;
BakeNeighPoint *bNeighs = sData->bData->bNeighs;
+ float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE;
int index;
timescale /= steps;
@@ -4141,7 +4172,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
* Spread Effect
*/
if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) {
- float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale;
+ float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale;
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
@@ -4151,7 +4182,6 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
{
int i;
int numOfNeighs = sData->adj_data->n_num[index];
- float totalAlpha = 0.0f;
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
/* Only reads values from the surface copy (prevPoint[]),
@@ -4160,39 +4190,23 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* Loop through neighbouring points */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i;
- float w_factor, alphaAdd = 0.0f;
+ float w_factor, p_alpha = pPoint->e_alpha;
PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
- float color_mix = (MIN2(ePoint->wetness, pPoint->wetness))*0.25f*surface->color_spread_speed;
-
- totalAlpha += ePoint->e_alpha;
+ float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed;
/* do color mixing */
- if (color_mix > MIN_WETNESS) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, color_mix);
-
- /* Check if neighbouring point has higher wetness,
- * if so, add it's wetness to this point as well*/
- if (ePoint->wetness <= pPoint->wetness) continue;
- w_factor = ePoint->wetness/numOfNeighs * (ePoint->wetness - pPoint->wetness) * speed_scale;
- if (w_factor <= MIN_WETNESS) continue;
-
- if (ePoint->e_alpha > pPoint->e_alpha) {
- alphaAdd = ePoint->e_alpha/numOfNeighs * (ePoint->wetness*ePoint->e_alpha - pPoint->wetness*pPoint->e_alpha) * speed_scale;
- }
-
- /* mix new color */
- mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, w_factor);
+ if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix);
- pPoint->e_alpha += alphaAdd;
- pPoint->wetness += w_factor;
+ /* Only continue if surrounding point has higher wetness */
+ if (ePoint->wetness<pPoint->wetness || ePoint->wetness<MIN_WETNESS) continue;
- if (pPoint->e_alpha > 1.0f) pPoint->e_alpha = 1.0f;
- }
+ w_factor = 1.0f/numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale;
+ CLAMP(w_factor, 0.0f, 1.0f);
- /* For antialiasing sake, don't let alpha go much higher than average alpha of neighbours */
- if (pPoint->e_alpha > (totalAlpha/numOfNeighs+0.25f)) {
- pPoint->e_alpha = (totalAlpha/numOfNeighs+0.25f);
- if (pPoint->e_alpha>1.0f) pPoint->e_alpha = 1.0f;
+ /* mix new wetness and color */
+ pPoint->wetness = (1.0f-w_factor)*pPoint->wetness + w_factor*ePoint->wetness;
+ pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor);
}
}
}
@@ -4201,7 +4215,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
* Shrink Effect
*/
if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) {
- float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale;
+ float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale;
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
@@ -4251,7 +4265,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
*/
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force)
{
- float eff_scale = EFF_MOVEMENT_PER_FRAME*timescale/2.0f;
+ float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*timescale/2.0f;
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
@@ -4264,8 +4278,9 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
float closest_d[2];
/* adjust drip speed depending on wetness */
- float w_factor = pPoint_prev->wetness*0.5f - 0.025f;
+ float w_factor = pPoint_prev->wetness - 0.025f;
if (w_factor <= 0) continue;
+ CLAMP(w_factor, 0.0f, 1.0f);
/* get force affect points */
surface_determineForceTargetPoints(sData, index, &force[index*4], closest_d, closest_id);
@@ -4274,41 +4289,38 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
for (i=0; i<2; i++) {
int n_index = closest_id[i];
if (n_index != -1 && closest_d[i]>0.0f) {
- float dir_dot = closest_d[i], dir_factor;
+ float dir_dot = closest_d[i], dir_factor, a_factor;
float speed_scale = eff_scale*force[index*4+3]/bNeighs[n_index].dist;
PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
+ float e_wet = ePoint->wetness;
/* just skip if angle is too extreme */
if (dir_dot <= 0.0f) continue;
- dir_factor = dir_dot * speed_scale * w_factor;
- if (dir_factor > (0.5f/steps)) dir_factor = (0.5f/steps);
-
- /* mix new color */
- if (dir_factor) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, dir_factor);
+ dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor;
+ if (dir_factor > 0.5f) dir_factor = 0.5f;
- ePoint->e_alpha += dir_factor;
+ /* mix new wetness*/
ePoint->wetness += dir_factor;
- if (ePoint->e_alpha > 1.0f) ePoint->e_alpha = 1.0f;
+ CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS);
+
+ /* mix new color */
+ a_factor = dir_factor / pPoint_prev->wetness;
+ CLAMP(a_factor, 0.0f, 1.0f);
+ mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor);
+ /* dripping is supposed to preserve alpha level */
+ if (pPoint_prev->e_alpha > ePoint->e_alpha) {
+ ePoint->e_alpha += a_factor * pPoint_prev->e_alpha;
+ if (ePoint->e_alpha > pPoint_prev->e_alpha)
+ ePoint->e_alpha = pPoint_prev->e_alpha;
+ }
- /* and decrease paint wetness on current point */
- pPoint->wetness -= dir_factor;
+ /* decrease paint wetness on current point */
+ pPoint->wetness -= (ePoint->wetness - e_wet);
+ CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
}
}
}
-
- /* Keep values within acceptable range */
- #pragma omp parallel for schedule(static)
- for (index = 0; index < sData->total_points; index++)
- {
- PaintPoint *cPoint = &((PaintPoint*)sData->type_data)[index];
-
- if (cPoint->e_alpha > 1.0f) cPoint->e_alpha=1.0f;
- if (cPoint->wetness > 2.0f) cPoint->wetness=2.0f;
-
- if (cPoint->e_alpha < 0.0f) cPoint->e_alpha=0.0f;
- if (cPoint->wetness < 0.0f) cPoint->wetness=0.0f;
- }
}
}
@@ -4323,7 +4335,7 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
double average_dist = 0.0f;
Bounds3D *mb = &sData->bData->mesh_bounds;
float canvas_size = MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
- float wave_scale = WAVE_INIT_SIZE/canvas_size;
+ float wave_scale = CANVAS_REL_SIZE/canvas_size;
/* allocate memory */
PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points*sizeof(PaintWavePoint), "Temp previous points for wave simulation");
@@ -4436,48 +4448,53 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
/* drying */
- if (pPoint->wetness >= MIN_WETNESS) {
- int i;
- float dry_ratio, f_color[4];
- float p_wetness = pPoint->wetness;
- VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG));
- if (pPoint->wetness<0.0f) pPoint->wetness=0.0f;
- dry_ratio = pPoint->wetness/p_wetness;
+ if (surface->flags & MOD_DPAINT_USE_DRYING) {
+ if (pPoint->wetness >= MIN_WETNESS) {
+ int i;
+ float dry_ratio, f_color[4];
+ float p_wetness = pPoint->wetness;
+ VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG));
+ if (pPoint->wetness<0.0f) pPoint->wetness=0.0f;
- /*
- * Slowly "shift" paint from wet layer to dry layer as it drys:
- */
- /* make sure alpha values are within proper range */
- CLAMP(pPoint->alpha, 0.0f, 1.0f);
- CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
-
- /* get current final blended color of these layers */
- blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
- /* reduce wet layer alpha by dry factor */
- pPoint->e_alpha *= dry_ratio;
-
- /* now calculate new alpha for dry layer that keeps final blended color unchanged */
- pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha);
- /* for each rgb component, calculate a new dry layer color that keeps the final blend color
- * with these new alpha values. (wet layer color doesnt change)*/
- if (pPoint->alpha) {
- for (i=0; i<3; i++) {
- pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha));
+ if (pPoint->wetness < surface->color_dry_threshold) {
+ dry_ratio = pPoint->wetness/p_wetness;
+
+ /*
+ * Slowly "shift" paint from wet layer to dry layer as it drys:
+ */
+ /* make sure alpha values are within proper range */
+ CLAMP(pPoint->alpha, 0.0f, 1.0f);
+ CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
+
+ /* get current final blended color of these layers */
+ blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
+ /* reduce wet layer alpha by dry factor */
+ pPoint->e_alpha *= dry_ratio;
+
+ /* now calculate new alpha for dry layer that keeps final blended color unchanged */
+ pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha);
+ /* for each rgb component, calculate a new dry layer color that keeps the final blend color
+ * with these new alpha values. (wet layer color doesnt change)*/
+ if (pPoint->alpha) {
+ for (i=0; i<3; i++) {
+ pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha));
+ }
+ }
}
- }
- pPoint->state = DPAINT_PAINT_WET;
- }
- /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
- else if (pPoint->state > 0) {
- float f_color[4];
- blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
- copy_v3_v3(pPoint->color, f_color);
- pPoint->alpha = f_color[3];
- /* clear wet layer */
- pPoint->wetness = 0.0f;
- pPoint->e_alpha = 0.0f;
- pPoint->state = DPAINT_PAINT_DRY;
+ pPoint->state = DPAINT_PAINT_WET;
+ }
+ /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
+ else if (pPoint->state > 0) {
+ float f_color[4];
+ blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
+ copy_v3_v3(pPoint->color, f_color);
+ pPoint->alpha = f_color[3];
+ /* clear wet layer */
+ pPoint->wetness = 0.0f;
+ pPoint->e_alpha = 0.0f;
+ pPoint->state = DPAINT_PAINT_DRY;
+ }
}
if (surface->flags & MOD_DPAINT_DISSOLVE) {
@@ -4925,7 +4942,7 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje
/* apply previous displace on derivedmesh if incremental surface */
if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL)
- dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm, 0);
+ dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm);
/* update bake data */
dynamicPaint_generateBakeData(surface, scene, cObject);