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>2011-08-03 22:31:48 +0400
committerMiika Hamalainen <blender@miikah.org>2011-08-03 22:31:48 +0400
commit8394f65d4a6019ae623fe32268a769463a189b9e (patch)
tree4338758f689e63d7fdd4752685e16eae42d1401e
parent35720a4c075c2a0782af173519097a094b5c0165 (diff)
Dynamic Paint:
* Object velocity can now be used to determine brush influence and color. * Brushes can now be set to "smudge" existing paint. * Added new operators to easily add and remove surface output mesh data layers from Dynamic Paint ui. * Fixed drip effect algorithm to work properly on forces pointing towards surface. * Adjusted drip effect speed. * Drip effect can now use canvas velocity and acceleration to influence drip direction. * Fixed texture mapping for material enabled brushes. * "Object Center" type brushes can now use "material color" as well. * Improved surface partitioning grid generation algorithm. * Fixed possible invalid brush collision detection when OpenMP enabled. * Fixed incorrect random sized particle displace/wave influence. * Fixed "Object Center" brush color ramp falloff. * Fixed invalid zero alpha sampling when rendering vertex colors. * Lots of smaller tweaking.
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py45
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h3
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c1397
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/editors/include/ED_mesh.h1
-rw-r--r--source/blender/editors/mesh/mesh_data.c19
-rw-r--r--source/blender/editors/physics/physics_intern.h1
-rw-r--r--source/blender/editors/physics/physics_ops.c1
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c66
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c14
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h1
-rw-r--r--source/blender/render/intern/source/render_texture.c2
-rw-r--r--source/blender/render/intern/source/shadeinput.c15
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c2
16 files changed, 1182 insertions, 403 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 6aac537de12..15326b51172 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -119,6 +119,19 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, bpy.types.Panel):
if (brush.wave_type != "REFLECT"):
split = layout.split(percentage=0.6)
split.prop(brush, "wave_factor")
+ elif (brush.brush_settings_context == "VELOCITY"):
+ col = layout.row().column()
+ col.prop(brush, "velocity_alpha")
+ col.prop(brush, "velocity_color")
+ col.prop(brush, "velocity_depth")
+ col = layout.row().column()
+ sub = col.column()
+ sub.active = (brush.velocity_alpha or brush.velocity_color)
+ sub.prop(brush, "max_velocity")
+ sub.template_color_ramp(brush, "velocity_ramp", expand=True)
+ layout.separator()
+ layout.prop(brush, "do_smudge")
+ layout.prop(brush, "smudge_strength")
else:
layout.label(text="-WIP-")
@@ -199,17 +212,31 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
# vertex format outputs
if (surface.surface_format == "VERTEX"):
if (surface.surface_type == "PAINT"):
+ # paintmap output
row = layout.row()
row.prop_search(surface, "output_name", ob.data, "vertex_colors", text="Paintmap layer: ")
- #col = row.column(align=True)
- #col.operator("dpaint.output_add", icon='ZOOMIN', text="")
+ ic = 'ZOOMIN'
+ if (surface.output_exists(object=ob, index=0)):
+ ic = 'ZOOMOUT'
+ col = row.column(align=True)
+ col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
+ # wetmap output
row = layout.row()
row.prop_search(surface, "output_name2", ob.data, "vertex_colors", text="Wetmap layer: ")
- #col = row.column(align=True)
- #col.operator("dpaint.output_add", icon='ZOOMIN', text="")
+ ic = 'ZOOMIN'
+ if (surface.output_exists(object=ob, index=1)):
+ ic = 'ZOOMOUT'
+ col = row.column(align=True)
+ col.operator("dpaint.output_toggle", icon=ic, text="").index = 1
if (surface.surface_type == "WEIGHT"):
- layout.prop_search(surface, "output_name", ob, "vertex_groups", text="Vertex Group: ")
+ row = layout.row()
+ row.prop_search(surface, "output_name", ob, "vertex_groups", text="Vertex Group: ")
+ ic = 'ZOOMIN'
+ if (surface.output_exists(object=ob, index=0)):
+ ic = 'ZOOMOUT'
+ col = row.column(align=True)
+ col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
# image format outputs
if (surface.surface_format == "IMAGE"):
@@ -280,6 +307,14 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, bpy.types.Panel):
col = layout.column()
col.active = surface.use_drip
effector_weights_ui(self, context, surface.effector_weights)
+ split = layout.split()
+
+ layout.label(text="Surface Movement:")
+ split = layout.split()
+ col = split.column()
+ col.prop(surface, "drip_velocity", slider=True)
+ col = split.column()
+ col.prop(surface, "drip_acceleration", slider=True)
elif surface.effect_ui == "SHRINK":
layout.prop(surface, "use_shrink")
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index c49a13f7d0e..0079e086df2 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -58,8 +58,6 @@ typedef struct PaintWavePoint {
short state; /* 0 = neutral
* 1 = obstacle
* 2 = reflect only */
- float foam;
-
} PaintWavePoint;
struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
@@ -70,6 +68,7 @@ void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
void dynamicPaint_clearSurface(DynamicPaintSurface *surface);
int dynamicPaint_resetSurface(struct DynamicPaintSurface *surface);
int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface);
+int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, struct Object *ob, int index);
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, char *basename);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 824ea009a0c..d78170fa73e 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -58,12 +58,14 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h" /* to get temp file path */
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
/* for bake operator */
-#include "ED_screen.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -154,17 +156,27 @@ typedef struct PaintBakeNormal {
/* Temp surface data used to process a frame */
typedef struct PaintBakeData {
+ /* point space data */
PaintBakeNormal *bNormal;
unsigned int *s_pos; /* index to start reading point sample realCoord */
unsigned int *s_num; /* num of samples for each point */
Vec3f *realCoord; /* current pixel center world-space coordinates * numOfSamples
* ordered as (s_pos+sample_num)*/
+ /* adjacency */
BakeNeighPoint *bNeighs; /* current frame neighbour distances, if required */
+ double average_dist;
+ /* space partitioning */
VolumeGrid *grid; /* space partitioning grid to optimize brush checks */
- MVert *prev_verts; /* copy of previous frame vertices. used observe surface movement */
+ /* velocity and movement */
+ Vec3f *velocity; /* speed vector in global space, if required */
+ Vec3f *prev_velocity;
+ float *brush_velocity; /* special temp data for post-p velocity based brushes like smear
+ * 3 float dir vec + 1 float str */
+ MVert *prev_verts; /* copy of previous frame vertices. used to observe surface movement */
float prev_obmat[4][4]; /* previous frame object matrix */
+ int clear;
} PaintBakeData;
@@ -322,6 +334,29 @@ void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface) {
dynamicPaint_resetPreview(surface->canvas);
}
+int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *ob, int index)
+{
+ char *name;
+
+ if (index == 0)
+ name = surface->output_name;
+ else if (index == 1)
+ name = surface->output_name2;
+ else
+ return 0;
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ Mesh *me = ob->data;
+ return (CustomData_get_named_layer_index(&me->fdata, CD_MCOL, name) != -1);
+ }
+ else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
+ return (defgroup_name_index(ob, surface->output_name) != -1);
+ }
+
+ return 0;
+}
+
static int surfaceDublicateNameExists(void *arg, const char *name)
{
DynamicPaintSurface *t_surface = (DynamicPaintSurface*)arg;
@@ -370,6 +405,108 @@ static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alp
t_color[2] = t_color[2]*invFact + s_color[2]*factor;
}
+#define UPDATE_PARENTS (1<<0)
+#define UPDATE_MESH (1<<1)
+#define UPDATE_EVERYTHING (UPDATE_PARENTS|UPDATE_MESH)
+
+static void subframe_updateObject(Scene *scene, Object *ob, int flags, float frame)
+{
+ int oflags;
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
+
+ /* if other is dynamic paint canvas, dont update */
+ if (pmd && pmd->canvas)
+ return;
+
+ /* if object has parent, update it too */
+ if ((flags & UPDATE_PARENTS) && ob->parent) subframe_updateObject(scene, ob->parent, 0, frame);
+ if ((flags & UPDATE_PARENTS) && ob->track) subframe_updateObject(scene, ob->track, 0, frame);
+
+ /* for curve */
+ if(ob->type==OB_CURVE) {
+ Curve *cu= ob->data;
+ BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM);
+ }
+
+ /* backup object flags */
+ oflags = ob->recalc;
+
+ ob->recalc |= OB_RECALC_ALL;
+ ob->recalc |= OB_RECALC_DATA;
+ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM);
+ if (flags & UPDATE_MESH)
+ object_handle_update(scene, ob);
+ else
+ where_is_object_time(scene, ob, frame);
+
+ /* restore object flags */
+ ob->recalc = oflags;
+}
+
+static void scene_setSubframe(Scene *scene, float subframe)
+{
+ /* dynamic paint subframes must be done on previous frame */
+ scene->r.cfra -= 1;
+ scene->r.subframe = subframe;
+}
+
+#define BRUSH_USES_VELOCITY (1<<0)
+
+static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene, Object *ob)
+{
+ Base *base = NULL;
+ GroupObject *go = NULL;
+ Object *brushObj = NULL;
+ ModifierData *md = NULL;
+
+ int flags = 0;
+
+ if(surface->brush_group)
+ go = surface->brush_group->gobject.first;
+ else
+ base = scene->base.first;
+
+ while (base || go)
+ {
+ brushObj = NULL;
+
+ /* select object */
+ if(surface->brush_group) {
+ if(go->ob) brushObj = go->ob;
+ }
+ else
+ brushObj = base->object;
+
+ if(!brushObj)
+ {
+ if(surface->brush_group) go = go->next;
+ else base= base->next;
+ continue;
+ }
+
+ if(surface->brush_group)
+ go = go->next;
+ else
+ base= base->next;
+
+ md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
+ if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+ {
+ DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
+
+ if (pmd2->brush)
+ {
+ DynamicPaintBrushSettings *brush = pmd2->brush;
+
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY)
+ flags |= BRUSH_USES_VELOCITY;
+ }
+ }
+ }
+
+ return flags;
+}
+
static int boundsIntersect(Bounds3D *b1, Bounds3D *b2)
{
int i=2;
@@ -446,6 +583,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
int index, error = 0;
float dim_factor, volume, dim[3];
float tx,ty,tz;
+ float min_dim;
/* initial values for each thread */
for (index = 0; index<num_of_threads; index++) {
@@ -479,16 +617,17 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
tx = dim[0];
ty = dim[1];
tz = dim[2];
+ min_dim = MAX3(tx,ty,tz) / 1000.f;
/* deactivate zero axises */
- if (!tx) {tx=1.0f; axis-=1;}
- if (!ty) {ty=1.0f; axis-=1;}
- if (!tz) {tz=1.0f; axis-=1;}
+ if (tx<min_dim) {tx=1.0f; axis-=1;}
+ if (ty<min_dim) {ty=1.0f; axis-=1;}
+ if (tz<min_dim) {tz=1.0f; axis-=1;}
- if (axis == 0)
+ if (axis == 0 || MAX3(tx,ty,tz) < 0.0001f)
return;
- /* now with values scaled >= 1.0f, calculate scaled grid volume */
+ /* now calculate grid volume/area/width depending on num of active axis */
volume = tx*ty*tz;
/* determine final grid size by trying to fit average 10.000 points per grid cell */
@@ -496,11 +635,11 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/* define final grid size using dim_factor, use min 3 for active axises */
grid->x = (int)floor(tx / dim_factor);
- CLAMP(grid->x, (dim[0]) ? 3 : 1, 100);
+ CLAMP(grid->x, (dim[0]>=min_dim) ? 3 : 1, 100);
grid->y = (int)floor(ty / dim_factor);
- CLAMP(grid->y, (dim[1]) ? 3 : 1, 100);
+ CLAMP(grid->y, (dim[1]>=min_dim) ? 3 : 1, 100);
grid->z = (int)floor(tz / dim_factor);
- CLAMP(grid->z, (dim[2]) ? 3 : 1, 100);
+ CLAMP(grid->z, (dim[2]>=min_dim) ? 3 : 1, 100);
grid_cells = grid->x*grid->y*grid->z;
@@ -569,16 +708,16 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
for (y=0; y<grid->y; y++) {
int z;
for (z=0; z<grid->z; z++) {
- index = x + y * grid->x + z * grid->x*grid->y;
+ int b_index = x + y * grid->x + z * grid->x*grid->y;
/* set bounds */
- grid->bounds[index].min[0] = grid->grid_bounds.min[0] + dim[0]/grid->x*x;
- grid->bounds[index].min[1] = grid->grid_bounds.min[1] + dim[1]/grid->y*y;
- grid->bounds[index].min[2] = grid->grid_bounds.min[2] + dim[2]/grid->z*z;
+ grid->bounds[b_index].min[0] = grid->grid_bounds.min[0] + dim[0]/grid->x*x;
+ grid->bounds[b_index].min[1] = grid->grid_bounds.min[1] + dim[1]/grid->y*y;
+ grid->bounds[b_index].min[2] = grid->grid_bounds.min[2] + dim[2]/grid->z*z;
- grid->bounds[index].max[0] = grid->grid_bounds.min[0] + dim[0]/grid->x*(x+1);
- grid->bounds[index].max[1] = grid->grid_bounds.min[1] + dim[1]/grid->y*(y+1);
- grid->bounds[index].max[2] = grid->grid_bounds.min[2] + dim[2]/grid->z*(z+1);
+ grid->bounds[b_index].max[0] = grid->grid_bounds.min[0] + dim[0]/grid->x*(x+1);
+ grid->bounds[b_index].max[1] = grid->grid_bounds.min[1] + dim[1]/grid->y*(y+1);
+ grid->bounds[b_index].max[2] = grid->grid_bounds.min[2] + dim[2]/grid->z*(z+1);
}
}
}
@@ -611,6 +750,9 @@ static void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
if(pmd->brush->paint_ramp)
MEM_freeN(pmd->brush->paint_ramp);
pmd->brush->paint_ramp = NULL;
+ if(pmd->brush->vel_ramp)
+ MEM_freeN(pmd->brush->vel_ramp);
+ pmd->brush->vel_ramp = NULL;
MEM_freeN(pmd->brush);
pmd->brush = NULL;
@@ -640,6 +782,8 @@ static void free_bakeData(PaintSurfaceData *data)
if (bData->bNeighs) MEM_freeN(bData->bNeighs);
if (bData->grid) freeGrid(data);
if (bData->prev_verts) MEM_freeN(bData->prev_verts);
+ if (bData->velocity) MEM_freeN(bData->velocity);
+ if (bData->prev_velocity) MEM_freeN(bData->prev_velocity);
MEM_freeN(data->bData);
data->bData = NULL;
@@ -843,12 +987,12 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
pmd->brush->particle_smooth = 0.05f;
pmd->brush->wave_factor = 1.0f;
+ pmd->brush->smudge_strength = 0.3f;
+ pmd->brush->max_velocity = 1.0f;
pmd->brush->dm = NULL;
- /*
- * Paint proximity falloff colorramp.
- */
+ /* Paint proximity falloff colorramp. */
{
CBData *ramp;
@@ -863,6 +1007,19 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
ramp[1].a = 0.0f;
pmd->brush->paint_ramp->tot = 2;
}
+
+ /* Brush velocity ramp. */
+ {
+ CBData *ramp;
+
+ pmd->brush->vel_ramp = add_colorband(0);
+ if (!pmd->brush->vel_ramp)
+ return 0;
+ ramp = pmd->brush->vel_ramp->data;
+ ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
+ ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
+ pmd->brush->paint_ramp->tot = 2;
+ }
}
}
else
@@ -948,13 +1105,13 @@ static int surface_usesAdjData(DynamicPaintSurface *surface) {
}
/* initialize surface adjacency data */
-static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface) {
+static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init) {
PaintSurfaceData *sData = surface->data;
PaintAdjData *ed;
int *temp_data;
int neigh_points = 0;
- if (!surface_usesAdjData(surface)) return;
+ if (!surface_usesAdjData(surface) && !force_init) return;
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
/* For vertex format, neighbours are connected by edges */
@@ -1066,6 +1223,9 @@ void dynamicPaint_clearSurface(DynamicPaintSurface *surface) {
data_size = sizeof(float);
memset(sData->type_data, 0, data_size * sData->total_points);
+
+ if (sData->bData)
+ sData->bData->clear = 1;
}
}
@@ -1086,7 +1246,7 @@ int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
/* allocate data depending on surface type and format */
surface->data->total_points = numOfPoints;
dynamicPaint_allocateSurfaceType(surface);
- dynamicPaint_initAdjacencyData(surface);
+ dynamicPaint_initAdjacencyData(surface, 0);
return 1;
}
@@ -1165,7 +1325,8 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
BKE_ptcache_validate(cache, (int)scene->r.cfra);
}
/* if read failed and we're on surface range do recalculate */
- else if ((int)scene->r.cfra == current_frame) {
+ else if ((int)scene->r.cfra == current_frame
+ && !(cache->flag & PTCACHE_BAKED)) {
/* calculate surface frame */
canvas->flags |= MOD_DPAINT_BAKING;
dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
@@ -1193,8 +1354,9 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
/* loop through surfaces */
for (; surface; surface=surface->next) {
+ PaintSurfaceData *sData = surface->data;
- if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
+ if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) {
if (!(surface->flags & (MOD_DPAINT_ACTIVE))) continue;
/* process vertex surface previews */
@@ -1206,14 +1368,14 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
MFace *mface = result->getFaceArray(result);
int numOfFaces = result->getNumFaces(result);
int i;
- PaintPoint* pPoint = (PaintPoint*)surface->data->type_data;
+ PaintPoint* pPoint = (PaintPoint*)sData->type_data;
MCol *col;
/* paint is stored on dry and wet layers, so mix final color first */
- float *fcolor = MEM_callocN(sizeof(float)*surface->data->total_points*4, "Temp paint color");
+ float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color");
#pragma omp parallel for schedule(static)
- for (i=0; i<surface->data->total_points; i++) {
+ for (i=0; i<sData->total_points; i++) {
int j=i*4;
fcolor[j] = pPoint[i].color[0];
@@ -1313,10 +1475,10 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
MVert *mvert = result->getVertArray(result);
int i;
- float* value = (float*)surface->data->type_data;
+ float* value = (float*)sData->type_data;
#pragma omp parallel for schedule(static)
- for (i=0; i<surface->data->total_points; i++) {
+ for (i=0; i<sData->total_points; i++) {
float normal[3];
normal_short_to_float_v3(normal, mvert[i].no);
normalize_v3(normal);
@@ -1333,7 +1495,7 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
int defgrp_index = defgroup_name_index(ob, surface->output_name);
MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
- float *weight = (float*)surface->data->type_data;
+ float *weight = (float*)sData->type_data;
/* viewport preview */
if (surface->flags & MOD_DPAINT_PREVIEW) {
/* Save preview results to weight layer, to be
@@ -1367,10 +1529,10 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
/* apply weights into a vertex group, if doesnt exists add a new layer */
if (defgrp_index >= 0 && !dvert && strlen(surface->output_name)>0)
dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
- NULL, surface->data->total_points, surface->output_name);
+ NULL, sData->total_points, surface->output_name);
if (defgrp_index >= 0 && dvert) {
int i;
- for(i=0; i<surface->data->total_points; i++) {
+ for(i=0; i<sData->total_points; i++) {
int j;
MDeformVert *dv= &dvert[i];
MDeformWeight *def_weight = NULL;
@@ -1383,6 +1545,10 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
}
}
+ /* skip if weight value is 0 and no existing weight is found */
+ if (!def_weight && !weight[i])
+ continue;
+
/* if not found, add a weight for it */
if (!def_weight) {
MDeformWeight *newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1),
@@ -1406,10 +1572,10 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
MVert *mvert = result->getVertArray(result);
int i;
- PaintWavePoint* wPoint = (PaintWavePoint*)surface->data->type_data;
+ PaintWavePoint* wPoint = (PaintWavePoint*)sData->type_data;
#pragma omp parallel for schedule(static)
- for (i=0; i<surface->data->total_points; i++) {
+ for (i=0; i<sData->total_points; i++) {
float normal[3];
normal_short_to_float_v3(normal, mvert[i].no);
normalize_v3(normal);
@@ -1437,7 +1603,7 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
/* Modifier call. Processes dynamic paint modifier step. */
struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
{
- /* Update derived mesh data to modifier if baking */
+ /* Update canvas data for a new frame */
dynamicPaint_frameUpdate(pmd, scene, ob, dm);
/* Return output mesh */
@@ -1996,7 +2162,7 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
}
/* allocate memory */
sData->total_points = w*h;
- dynamicPaint_initAdjacencyData(surface);
+ dynamicPaint_initAdjacencyData(surface, 0);
if (sData->adj_data) {
PaintAdjData *ed = sData->adj_data;
@@ -2305,7 +2471,7 @@ static void dynamicPaint_updateObjectMaterials(Object *brushOb, Material *ui_mat
}
}
-/* A modified part of shadeinput.c -> shade_input_set_uv() / shade_input_set_shade_texco()
+/* A modified part of shadeinput.c -> shade_input_set_uv()
* Used for sampling UV mapped texture color */
static void textured_face_generate_uv(float *uv, float *normal, float *hit, float *v1, float *v2, float *v3)
{
@@ -2338,7 +2504,7 @@ static void textured_face_generate_uv(float *uv, float *normal, float *hit, floa
CLAMP(uv[1], -2.0f, 1.0f);
}
-/* a modified part of shadeinput.c -> shade_input_set_uv() / shade_input_set_shade_texco()
+/* a modified part of shadeinput.c -> shade_input_set_shade_texco()
* Used for sampling UV mapped texture color */
static void textured_face_get_uv(float *uv_co, float *normal, float *uv, int faceIndex, short quad, MTFace *tface)
{
@@ -2380,13 +2546,6 @@ void dynamicPaint_sampleSolidMaterial(float color[3], float *alpha, Material *ma
MFace *mface;
int v1, v2, v3;
MVert *mvert;
-
- /* Get face data */
- mvert = orcoDm->getVertArray(orcoDm);
- mface = orcoDm->getFaceArray(orcoDm);
- v1=mface[faceIndex].v1, v2=mface[faceIndex].v2, v3=mface[faceIndex].v3;
- if (isQuad) {v2=mface[faceIndex].v3; v3=mface[faceIndex].v4;}
- normal_tri_v3( normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
/* Assign material base values */
color[0] = mat->r;
@@ -2394,6 +2553,15 @@ void dynamicPaint_sampleSolidMaterial(float color[3], float *alpha, Material *ma
color[2] = mat->b;
*alpha = mat->alpha;
+ /* Get face data */
+ mvert = orcoDm->getVertArray(orcoDm);
+ mface = orcoDm->getFaceArray(orcoDm);
+
+ if (!mvert || !mface) return;
+ v1=mface[faceIndex].v1, v2=mface[faceIndex].v2, v3=mface[faceIndex].v3;
+ if (isQuad) {v2=mface[faceIndex].v3; v3=mface[faceIndex].v4;}
+ normal_tri_v3( normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+
VECCOPY(xyz_local, xyz);
mul_m4_v3(brushOb->imat, xyz_local);
@@ -2461,7 +2629,8 @@ void dynamicPaint_sampleSolidMaterial(float color[3], float *alpha, Material *ma
continue;
}
else {
- rgbnor = multitex_ext(mtex->tex, co, 0, 0, 0, &texres);
+ /* cant use multitex_ext because it redoes mapping for image textures */
+ rgbnor = multitex(mtex->tex, texvec, 0, 0, 0, &texres, 0, 0);
}
/* texture output */
@@ -2906,11 +3075,28 @@ static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrush
/*
* add paint results to the surface data depending on surface type
*/
-static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned int index, DynamicPaintBrushSettings *brush, float paint[4], float strength, float depth, float timescale)
+static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned int index, DynamicPaintBrushSettings *brush,
+ float paint[4], float influence, float depth, float vel_factor, float timescale)
{
PaintSurfaceData *sData = surface->data;
- strength *= brush->alpha;
+ float strength = influence * brush->alpha;
+
+ /* Sample velocity colorband if required */
+ if (brush->flags & (MOD_DPAINT_VELOCITY_ALPHA|MOD_DPAINT_VELOCITY_COLOR|MOD_DPAINT_VELOCITY_DEPTH)) {
+ float coba_res[4];
+ if (do_colorband(brush->vel_ramp, vel_factor, coba_res)) {
+ if (brush->flags & MOD_DPAINT_VELOCITY_COLOR) {
+ paint[0] = coba_res[0];
+ paint[1] = coba_res[1];
+ paint[2] = coba_res[2];
+ }
+ if (brush->flags & MOD_DPAINT_VELOCITY_ALPHA)
+ strength *= coba_res[3];
+ if (brush->flags & MOD_DPAINT_VELOCITY_DEPTH)
+ depth *= coba_res[3];
+ }
+ }
/* mix paint surface */
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
@@ -2951,6 +3137,11 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
dynamicPaint_mixWaveHeight(&((PaintWavePoint*)sData->type_data)[index],
brush, 0.0f-depth);
}
+
+ /* doing velocity based painting */
+ if (sData->bData->brush_velocity) {
+ sData->bData->brush_velocity[index*4+3] *= influence;
+ }
}
static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush)
@@ -2962,6 +3153,106 @@ static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBru
else return 1;
}
+/* calculate velocity for mesh vertices */
+static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
+{
+ int i;
+ float prev_obmat[4][4];
+ DerivedMesh *dm_p, *dm_c;
+ MVert *mvert_p, *mvert_c;
+ int numOfVerts_p, numOfVerts_c;
+
+ float cur_sfra = scene->r.subframe;
+ int cur_fra = scene->r.cfra;
+
+ float prev_sfra = cur_sfra - timescale;
+ int prev_fra = cur_fra;
+
+ if (prev_sfra < 0.0f) {
+ prev_sfra += 1.0f;
+ prev_fra = cur_fra - 1;
+ }
+
+ /* previous frame dm */
+ scene->r.cfra = prev_fra;
+ scene->r.subframe = prev_sfra;
+
+ subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene));
+ dm_p = CDDM_copy(brush->dm);
+ numOfVerts_p = dm_p->getNumVerts(dm_p);
+ mvert_p = dm_p->getVertArray(dm_p);
+ copy_m4_m4(prev_obmat, ob->obmat);
+
+ /* current frame dm */
+ scene->r.cfra = cur_fra;
+ scene->r.subframe = cur_sfra;
+
+ subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene));
+ dm_c = brush->dm;
+ numOfVerts_c = dm_c->getNumVerts(dm_c);
+ mvert_c = dm_p->getVertArray(dm_c);
+
+ (*brushVel) = (struct Vec3f *) MEM_mallocN(numOfVerts_c*sizeof(Vec3f), "Dynamic Paint brush velocity");
+ if (!(*brushVel)) return;
+
+ /* if mesh is constructive -> num of verts has changed,
+ * only use current frame derived mesh */
+ if (numOfVerts_p != numOfVerts_c)
+ mvert_p = mvert_c;
+
+ /* calculate speed */
+ #pragma omp parallel for schedule(static)
+ for (i=0; i<numOfVerts_c; i++) {
+ float p1[3], p2[3];
+
+ VECCOPY(p1, mvert_p[i].co);
+ mul_m4_v3(prev_obmat, p1);
+
+ VECCOPY(p2, mvert_c[i].co);
+ mul_m4_v3(ob->obmat, p2);
+
+ VECSUB((*brushVel)[i].v, p2, p1);
+ mul_v3_fl((*brushVel)[i].v, 1.0f/timescale);
+ }
+
+ dm_p->release(dm_p);
+}
+
+/* calculate velocity for object center point */
+static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f *brushVel, float timescale)
+{
+ float prev_obmat[4][4];
+ float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f};
+
+ float cur_sfra = scene->r.subframe;
+ int cur_fra = scene->r.cfra;
+ float prev_sfra = cur_sfra - timescale;
+ int prev_fra = cur_fra;
+
+ if (prev_sfra < 0.0f) {
+ prev_sfra += 1.0f;
+ prev_fra = cur_fra - 1;
+ }
+
+ /* previous frame dm */
+ scene->r.cfra = prev_fra;
+ scene->r.subframe = prev_sfra;
+ subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_curframe(scene));
+ copy_m4_m4(prev_obmat, ob->obmat);
+
+ /* current frame dm */
+ scene->r.cfra = cur_fra;
+ scene->r.subframe = cur_sfra;
+ subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_curframe(scene));
+
+ /* calculate speed */
+ mul_m4_v3(prev_obmat, prev_loc);
+ mul_m4_v3(ob->obmat, cur_loc);
+
+ VECSUB(brushVel->v, cur_loc, prev_loc);
+ mul_v3_fl(brushVel->v, 1.0f/timescale);
+}
+
#define VECADDVAL(v,val) {*(v)+=(val); *(v+1)+=(val); *(v+2)+=(val);}
#define VECMULVAL(v,val) {*(v)*=(val); *(v+1)*=(val); *(v+2)*=(val);}
@@ -2971,16 +3262,19 @@ static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBru
/*
* Paint a brush object mesh to the surface
*/
-static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *canvasOb, Object *brushOb, float timescale)
+static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *canvasOb, Object *brushOb, Scene *scene, float timescale)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
DerivedMesh *dm = NULL;
+ Vec3f *brushVelocity = NULL;
MVert *mvert = NULL;
MFace *mface = NULL;
- if (!brush->dm) return 0;
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY)
+ dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale);
+ if (!brush->dm) return 0;
{
BVHTreeFromMesh treeData = {0};
@@ -3033,247 +3327,291 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
for (id = 0; id < grid->s_num[c_index]; id++)
{
int index = grid->t_index[grid->s_pos[c_index] + id];
+ int ss, samples = bData->s_num[index];
+ float total_sample = (float)samples;
+ float brushStrength = 0.0f; /* brush influence factor */
+ float depth = 0.0f; /* displace depth */
+ float velocity_val = 0.0f;
+
+ float paintColor[3] = {0.0f};
+ int numOfHits = 0;
+
+ //PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
+ //pPoint->color[3] = id / grid->s_num[c_index];
+ //pPoint->alpha = 1.0f;
- /*float color[3] = {1.0f, 0.0f, 0.0f};
- dynamicPaint_updatePointData(surface, index, brush, color, 1.0f, 0.0f, timescale);
- continue;*/
+ /* for image sequence anti-aliasing, use gaussian factors */
+ if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
+ total_sample = gaussianTotal;
+
+ /* Supersampling */
+ for (ss=0; ss<samples; ss++)
{
- int ss, samples = bData->s_num[index];
- float total_sample = (float)samples;
- float brushStrength = 0.0f; /* brush influence factor */
- float depth = 0.0f; /* displace depth */
- float paintColor[3] = {0.0f};
- int numOfHits = 0;
+ float ray_start[3], ray_dir[3] = {0.0f};
+ float colorband[4] = {0.0f};
+ float sample_factor;
+ float sampleStrength = 0.0f;
+ BVHTreeRayHit hit;
+ BVHTreeNearest nearest;
+ short hit_found = 0;
+
+ /* hit data */
+ float hitCoord[3]; /* mid-sample hit coordinate */
+ int hitFace = -1; /* mid-sample hit face */
+ short hitQuad; /* mid-sample hit quad status */
- /* for image sequence anti-aliasing, use gaussian factors */
+ /* Supersampling factor */
if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
- total_sample = gaussianTotal;
+ sample_factor = gaussianFactors[ss];
+ else
+ sample_factor = 1.0f;
+
+ /* Get current sample position in world coordinates */
+ VECCOPY(ray_start, bData->realCoord[bData->s_pos[index]+ss].v);
+ if (!(brush->flags & MOD_DPAINT_ACCEPT_NONCLOSED) || brush->ray_dir == MOD_DPAINT_RAY_CANVAS) {
+ VECCOPY(ray_dir, bData->bNormal[index].invNorm);
+ }
+ else /* MOD_DPAINT_RAY_ZPLUS */
+ ray_dir[2] = 1.0f;
- /* Supersampling */
- for (ss=0; ss<samples; ss++)
+ /* a simple hack to minimize change of ray leaks at identical ray - edge locations */
+ VECADDVAL(ray_start, 0.001f);
+
+ hit.index = -1;
+ hit.dist = 9999;
+ nearest.index = -1;
+ nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest search uses squared distance */
+
+ /* Check volume collision */
+ if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
+ if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
{
+ /* We hit a triangle, now check if collision point normal is facing the point */
- float ray_start[3], ray_dir[3] = {0.0f};
- float colorband[4] = {0.0f};
- float sample_factor;
- float sampleStrength = 0.0f;
- BVHTreeRayHit hit;
- BVHTreeNearest nearest;
- short hit_found = 0;
-
- /* hit data */
- float hitCoord[3]; /* mid-sample hit coordinate */
- int hitFace = -1; /* mid-sample hit face */
- short hitQuad; /* mid-sample hit quad status */
-
- /* Supersampling factor */
- if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
- sample_factor = gaussianFactors[ss];
- else
- sample_factor = 1.0f;
-
- /* Get current sample position in world coordinates */
- VECCOPY(ray_start, bData->realCoord[bData->s_pos[index]+ss].v);
- if (!(brush->flags & MOD_DPAINT_ACCEPT_NONCLOSED) || brush->ray_dir == MOD_DPAINT_RAY_CANVAS) {
- VECCOPY(ray_dir, bData->bNormal[index].invNorm);
- }
- else /* MOD_DPAINT_RAY_ZPLUS */
- ray_dir[2] = 1.0f;
- /* a simple hack to minimize change of ray leaks at identical ray - edge locations */
- VECADDVAL(ray_start, 0.001f);
+ /* For optimization sake, hit point normal isn't calculated in ray cast loop */
+ int v1=mface[hit.index].v1, v2=mface[hit.index].v2, v3=mface[hit.index].v3, quad=(hit.no[0] == 1.0f);
+ float dot;
- hit.index = -1;
- hit.dist = 9999;
- nearest.index = -1;
- nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest search uses squared distance */
+ if (quad) {v2=mface[hit.index].v3; v3=mface[hit.index].v4;}
+
+ /* Get hit normal */
+ normal_tri_v3( hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ dot = ray_dir[0]*hit.no[0] + ray_dir[1]*hit.no[1] + ray_dir[2]*hit.no[2];
- /* Check volume collision */
- if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
- if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
+ /*
+ * If ray and hit normal are facing same direction
+ * hit point is inside a closed mesh.
+ */
+ if (dot>=0)
{
- /* We hit a triangle, now check if collision point normal is facing the point */
-
+ float dist = hit.dist;
+ int f_index = hit.index;
- /* For optimization sake, hit point normal isn't calculated in ray cast loop */
- int v1=mface[hit.index].v1, v2=mface[hit.index].v2, v3=mface[hit.index].v3, quad=(hit.no[0] == 1.0f);
- float dot;
+ /* In case of non-closed volumes, also cast a ray in opposite direction
+ * to make sure point is at least between two brush faces*/
+ if (!(brush->flags & MOD_DPAINT_ACCEPT_NONCLOSED)) {
+ VECMULVAL(ray_dir, -1.0f);
+ hit.index = -1;
+ hit.dist = 9999;
- if (quad) {v2=mface[hit.index].v3; v3=mface[hit.index].v4;}
-
- /* Get hit normal */
- normal_tri_v3( hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co);
- dot = ray_dir[0]*hit.no[0] + ray_dir[1]*hit.no[1] + ray_dir[2]*hit.no[2];
-
- /*
- * If ray and hit normal are facing same direction
- * hit point is inside a closed mesh.
- */
- if (dot>=0)
- {
- float dist = hit.dist;
- int f_index = hit.index;
+ BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData);
+ }
- /* In case of non-closed volumes, also cast a ray in opposite direction
- * to make sure point is at least between two brush faces*/
- if (!(brush->flags & MOD_DPAINT_ACCEPT_NONCLOSED)) {
- VECMULVAL(ray_dir, -1.0f);
- hit.index = -1;
- hit.dist = 9999;
+ if(hit.index != -1) {
+ /* Add factor on supersample filter */
+ sampleStrength += sample_factor;
+ hit_found = HIT_VOLUME;
+
+ /*
+ * Mark hit info
+ */
+ VECADDFAC(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
+ depth += dist*sample_factor;
+ hitFace = f_index;
+ hitQuad = quad;
+ }
+ }
+ } // end of raycast
+
+ /* Check proximity collision */
+ if ((brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) &&
+ (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX)))
+ {
+ float proxDist = -1.0f;
+ float hitCo[3];
+ short hQuad;
+ int face;
- BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData);
- }
+ /* if inverse prox and no hit found, skip this sample */
+ if (brush->flags & MOD_DPAINT_INVERSE_PROX && !hit_found) continue;
- if(hit.index != -1) {
- /* Add factor on supersample filter */
- sampleStrength += sample_factor;
- hit_found = HIT_VOLUME;
-
- /*
- * Mark hit info
- */
- VECADDFAC(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
- depth += dist*sample_factor;
- hitFace = f_index;
- hitQuad = quad;
- }
- }
- } // end of raycast
-
- /* Check proximity collision */
- if ((brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) &&
- (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX)))
- {
- float proxDist = -1.0f;
- float hitCo[3];
- short hQuad;
- int face;
-
- /* if inverse prox and no hit found, skip this sample */
- if (brush->flags & MOD_DPAINT_INVERSE_PROX && !hit_found) continue;
-
- /*
- * If pure distance proximity, find the nearest point on the mesh
- */
- if (!(brush->flags & MOD_DPAINT_PROX_FACEALIGNED)) {
- if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
- proxDist = sqrt(nearest.dist); /* find_nearest returns a squared distance, so gotta change it back to real distance */
- copy_v3_v3(hitCo, nearest.co);
- hQuad = (nearest.no[0] == 1.0f);
- face = nearest.index;
- }
+ /*
+ * If pure distance proximity, find the nearest point on the mesh
+ */
+ if (!(brush->flags & MOD_DPAINT_PROX_FACEALIGNED)) {
+ if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
+ proxDist = sqrt(nearest.dist); /* find_nearest returns a squared distance, so gotta change it back to real distance */
+ copy_v3_v3(hitCo, nearest.co);
+ hQuad = (nearest.no[0] == 1.0f);
+ face = nearest.index;
}
- else { /* else cast a ray in surface normal direction */
- negate_v3(ray_dir);
- hit.index = -1;
- hit.dist = brush->paint_distance;
-
- /* Do a face normal directional raycast, and use that distance */
- if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
- {
- proxDist = hit.dist;
- VECADDFAC(hitCo, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
- hQuad = (hit.no[0] == 1.0f);
- face = hit.index;
- }
+ }
+ else { /* else cast a ray in surface normal direction */
+ negate_v3(ray_dir);
+ hit.index = -1;
+ hit.dist = brush->paint_distance;
+
+ /* Do a face normal directional raycast, and use that distance */
+ if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
+ {
+ proxDist = hit.dist;
+ VECADDFAC(hitCo, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
+ hQuad = (hit.no[0] == 1.0f);
+ face = hit.index;
}
+ }
- /* If a hit was found, calculate required values */
- if (proxDist >= 0.0f && proxDist <= brush->paint_distance) {
- float dist_rate = proxDist / brush->paint_distance;
- float prox_influence = 0.0f;
+ /* If a hit was found, calculate required values */
+ if (proxDist >= 0.0f && proxDist <= brush->paint_distance) {
+ float dist_rate = proxDist / brush->paint_distance;
+ float prox_influence = 0.0f;
- /* in case of inverse prox also undo volume effect */
- if (brush->flags & MOD_DPAINT_INVERSE_PROX) {
- sampleStrength -= sample_factor;
- dist_rate = 1.0f - dist_rate;
- }
+ /* in case of inverse prox also undo volume effect */
+ if (brush->flags & MOD_DPAINT_INVERSE_PROX) {
+ sampleStrength -= sample_factor;
+ dist_rate = 1.0f - dist_rate;
+ }
- /* if using color ramp*/
- if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, dist_rate, colorband))
- prox_influence = colorband[3];
- /* if using smooth falloff, multiply gaussian factor */
- else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH) {
- prox_influence = (1.0f - dist_rate) * sample_factor;
- }
- else prox_influence = (brush->flags & MOD_DPAINT_INVERSE_PROX) ? 0.0f : 1.0f;
+ /* if using color ramp*/
+ if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, dist_rate, colorband))
+ prox_influence = colorband[3];
+ /* if using smooth falloff, multiply gaussian factor */
+ else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH) {
+ prox_influence = (1.0f - dist_rate) * sample_factor;
+ }
+ else prox_influence = (brush->flags & MOD_DPAINT_INVERSE_PROX) ? 0.0f : 1.0f;
- hit_found = HIT_PROXIMITY;
- sampleStrength += prox_influence*sample_factor;
+ hit_found = HIT_PROXIMITY;
+ sampleStrength += prox_influence*sample_factor;
- /* if no volume hit, use prox point face info */
- if (hitFace == -1) {
- copy_v3_v3(hitCoord, hitCo);
- hitQuad = hQuad;
- hitFace = face;
- }
+ /* if no volume hit, use prox point face info */
+ if (hitFace == -1) {
+ copy_v3_v3(hitCoord, hitCo);
+ hitQuad = hQuad;
+ hitFace = face;
}
}
+ }
- if (!hit_found) continue;
+ if (!hit_found) continue;
- /*
- * Process hit color and alpha
- */
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
- {
- float sampleColor[3];
- float alpha_factor = 1.0f;
+ /* velocity brush, only do on main sample */
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss==0 && bData->velocity && brushVelocity) {
+ int v1,v2,v3;
+ float weights[4];
+ float brushPointVelocity[3];
+ float velocity[3];
+
+ if (!hitQuad) {
+ v1 = mface[hitFace].v1;
+ v2 = mface[hitFace].v2;
+ v3 = mface[hitFace].v3;
+ }
+ else {
+ v1 = mface[hitFace].v2;
+ v2 = mface[hitFace].v3;
+ v3 = mface[hitFace].v4;
+ }
+ /* calculate barycentric weights for hit point */
+ interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
- sampleColor[0] = brush->r;
- sampleColor[1] = brush->g;
- sampleColor[2] = brush->b;
+ /* simple check based on brush surface velocity,
+ * todo: perhaps implement something that handles volume movement as well */
- /* Get material+textures color on hit point if required */
- if (brush->flags & MOD_DPAINT_USE_MATERIAL) dynamicPaint_getMaterialColor(sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]+ss].v, hitCoord, hitFace, hitQuad, brush->dm, brush->mat);
-
- /* Sample colorband if required */
- if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
- if (!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
- sampleColor[0] = colorband[0];
- sampleColor[1] = colorband[1];
- sampleColor[2] = colorband[2];
- }
- }
+ /* and now interpolate vertex speed vectors to get hit point velocity */
+ interp_v3_v3v3v3( brushPointVelocity,
+ brushVelocity[v1].v,
+ brushVelocity[v2].v,
+ brushVelocity[v3].v, weights);
+
+ /* substract canvas point velocity */
+ VECSUB(velocity, brushPointVelocity, bData->velocity[index].v);
+
+ velocity_val = len_v3(velocity);
+
+ /* */
+ if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
+ VECCOPY(&bData->brush_velocity[index*4], velocity);
+ mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
+ bData->brush_velocity[index*4+3] = velocity_val;
+ }
- /* Add AA sample */
- paintColor[0] += sampleColor[0];
- paintColor[1] += sampleColor[1];
- paintColor[2] += sampleColor[2];
- sampleStrength *= alpha_factor;
- numOfHits++;
+ velocity_val /= brush->max_velocity;
+ CLAMP(velocity_val, 0.0f, 1.0f);
+ }
+
+ /*
+ * Process hit color and alpha
+ */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
+ {
+ float sampleColor[3];
+ float alpha_factor = 1.0f;
+
+ sampleColor[0] = brush->r;
+ sampleColor[1] = brush->g;
+ sampleColor[2] = brush->b;
+
+ /* Get material+textures color on hit point if required */
+ if (brush->flags & MOD_DPAINT_USE_MATERIAL) dynamicPaint_getMaterialColor(sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]+ss].v, hitCoord, hitFace, hitQuad, brush->dm, brush->mat);
+
+ /* Sample proximity colorband if required */
+ if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
+ if (!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
+ sampleColor[0] = colorband[0];
+ sampleColor[1] = colorband[1];
+ sampleColor[2] = colorband[2];
+ }
}
- /* apply sample strength */
- brushStrength += sampleStrength;
- } // end supersampling
+ /* Add AA sample */
+ paintColor[0] += sampleColor[0];
+ paintColor[1] += sampleColor[1];
+ paintColor[2] += sampleColor[2];
+ sampleStrength *= alpha_factor;
+ numOfHits++;
+ }
+ /* apply sample strength */
+ brushStrength += sampleStrength;
+ } // end supersampling
- /* if any sample was inside paint range */
- if (brushStrength > 0.01f) {
- /* apply supersampling results */
- if (samples > 1) {
- brushStrength /= total_sample;
- }
- CLAMP(brushStrength, 0.0f, 1.0f);
-
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- /* Get final pixel color and alpha */
- paintColor[0] /= numOfHits;
- paintColor[1] /= numOfHits;
- paintColor[2] /= numOfHits;
- paintColor[3] /= total_sample;
- }
- /* get final object space depth */
- else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
- surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
- depth /= bData->bNormal[index].normal_scale * total_sample;
- }
-
- dynamicPaint_updatePointData(surface, index, brush, paintColor, brushStrength, depth, timescale);
+ /* if any sample was inside paint range */
+ if (brushStrength > 0.01f) {
+
+ /* apply supersampling results */
+ if (samples > 1) {
+ brushStrength /= total_sample;
}
+ CLAMP(brushStrength, 0.0f, 1.0f);
+
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ /* Get final pixel color and alpha */
+ paintColor[0] /= numOfHits;
+ paintColor[1] /= numOfHits;
+ paintColor[2] /= numOfHits;
+ paintColor[3] /= total_sample;
+ }
+ /* get final object space depth */
+ else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
+ surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
+ depth /= bData->bNormal[index].normal_scale * total_sample;
+ }
+
+ dynamicPaint_updatePointData(surface, index, brush, paintColor, brushStrength, depth, velocity_val, timescale);
}
}
}
@@ -3284,6 +3622,10 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
}
+ /* free brush velocity data */
+ if (brushVelocity)
+ MEM_freeN(brushVelocity);
+
return 1;
}
@@ -3307,6 +3649,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
float smooth = brush->particle_smooth;
float range = solidradius + smooth;
+ float particle_timestep = 0.04f * part->timetweak;
Bounds3D part_bb;
@@ -3396,6 +3739,8 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
float disp_intersect = 0.0f;
float radius = 0.0f;
float strength = 0.0f;
+ float velocity_val = 0.0f;
+ int part_index;
/*
* With predefined radius, there is no variation between particles.
@@ -3418,6 +3763,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
strength = 1.0f - smooth_range;
disp_intersect = radius - nearest.dist;
+ part_index = nearest.index;
}
/* If using random per particle radius and closest particle didn't give max influence */
if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) {
@@ -3456,6 +3802,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
/* update hit data */
smooth_range = s_range;
dist = nearest[n].dist;
+ part_index = nearest[n].index;
/* If inside solid range and no disp depth required, no need to seek further */
if (s_range < 0.0f)
@@ -3469,7 +3816,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
float rad = radius + smooth, str;
if ((rad-dist) > disp_intersect) {
- disp_intersect = dist;
+ disp_intersect = radius - dist;
radius = rad;
}
@@ -3487,6 +3834,25 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
float paintColor[4] = {0.0f};
float depth = 0.0f;
+ /* apply velocity */
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY)
+ {
+ float velocity[3];
+ ParticleData *pa = psys->particles + part_index;
+
+ mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
+ velocity_val = len_v3(velocity);
+
+ if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
+ VECCOPY(&bData->brush_velocity[index*4], velocity);
+ mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
+ bData->brush_velocity[index*4+3] = velocity_val;
+ }
+
+ velocity_val /= brush->max_velocity;
+ CLAMP(velocity_val, 0.0f, 1.0f);
+ }
+
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
paintColor[0] = brush->r;
paintColor[1] = brush->g;
@@ -3500,7 +3866,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
if (depth<0.0f) depth = 0.0f;
}
- dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, timescale);
+ dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
}
}
}
@@ -3517,11 +3883,19 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
return 1;
}
-static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, Object *canvasOb, float timescale)
+static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
+ Object *canvasOb, Object *brushOb, Scene *scene, float timescale)
{
int index;
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
+ Vec3f brushVel;
+ float velocity_val = 0.0f;
+
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
+ dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, brush, &brushVel, timescale);
+ velocity_val = len_v3(brushVel.v);
+ }
/*
* Loop through every surface point
@@ -3548,21 +3922,43 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
float paintColor[3] = {0.0f};
float depth = 0.0f;
+ /* material */
+ if (brush->flags & MOD_DPAINT_USE_MATERIAL) {
+ float alpha_factor = 1.0f;
+ float hit_coord[3];
+ MVert *mvert = brush->dm->getVertArray(brush->dm);
+ /* use dummy coord on first vertex */
+ VECCOPY(hit_coord, mvert[0].co);
+
+ dynamicPaint_getMaterialColor(paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm, brush->mat);
+ }
+
/* color ramp */
if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, (1.0f-strength), colorband))
strength = colorband[3];
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
+ if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
+ VECCOPY(&bData->brush_velocity[index*4], brushVel.v);
+ mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
+ bData->brush_velocity[index*4+3] = velocity_val;
+ }
+ }
+
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) {
+ if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
+ !(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
paintColor[0] = colorband[0];
paintColor[1] = colorband[1];
paintColor[2] = colorband[2];
}
else {
- paintColor[0] = brush->r;
- paintColor[1] = brush->g;
- paintColor[2] = brush->b;
+ if (!(brush->flags & MOD_DPAINT_USE_MATERIAL)) {
+ paintColor[0] = brush->r;
+ paintColor[1] = brush->g;
+ paintColor[2] = brush->b;
+ }
}
}
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
@@ -3572,7 +3968,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
depth = (brush->paint_distance - disp_intersect) / bData->bNormal[index].normal_scale;
if (depth<0.0f) depth = 0.0f;
}
- dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, timescale);
+ dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
}
}
@@ -3587,7 +3983,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
* Calculate current frame neighbouring point distances
* and direction vectors
*/
-static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface)
+static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int force_init)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -3596,8 +3992,9 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface)
Vec3f *realCoord = bData->realCoord;
int index;
- if (!surface_usesAdjDistance(surface) || !sData->adj_data) return;
+ if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return;
+ if (bData->bNeighs) MEM_freeN(bData->bNeighs);
bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint),"PaintEffectBake");
if (!bNeighs) return;
@@ -3619,6 +4016,129 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface)
if (bNeighs[n_index].dist) mul_v3_fl(bNeighs[n_index].dir, 1.0f/bNeighs[n_index].dist);
}
}
+
+ /* calculate average values (single thread) */
+ bData->average_dist = 0.0f;
+ for (index = 0; index < sData->total_points; index++)
+ {
+ int i;
+ int numOfNeighs = adj_data->n_num[index];
+
+ for (i=0; i<numOfNeighs; i++) {
+ bData->average_dist += bNeighs[adj_data->n_index[index]+i].dist;
+ }
+ }
+ bData->average_dist /= adj_data->total_targets;
+}
+
+static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush)
+{
+ PaintSurfaceData *sData = surface->data;
+ PaintBakeData *bData = sData->bData;
+ BakeNeighPoint *bNeighs = sData->bData->bNeighs;
+ int index, steps, step;
+ float eff_scale, max_velocity = 0.0f;
+
+ if (!sData->adj_data) return;
+
+ /* find max velocity */
+ for (index = 0; index < sData->total_points; index++) {
+ float vel = bData->brush_velocity[index*4+3];
+ if (vel > max_velocity) max_velocity = vel;
+ }
+
+ steps = (int)ceil(max_velocity / bData->average_dist);
+ CLAMP(steps, 0, 12);
+
+ for (step=0; step<steps; step++) {
+
+ eff_scale = brush->smudge_strength/(float)steps;
+
+ for (index = 0; index < sData->total_points; index++) {
+ int i;
+ int numOfNeighs = sData->adj_data->n_num[index];
+ PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
+ float smudge_dir[3];
+ float smudge_str = bData->brush_velocity[index*4+3];
+
+ /* to make dripping happen with as little spread as possible,
+ * only use two closest point dirs "around" the force dir */
+ int closest_id[2] = {-1, -1};
+ float closest_d[2] = {-1.0f, -1.0f};
+
+ if (!smudge_str) continue;
+
+ VECCOPY(smudge_dir, &bData->brush_velocity[index*4]);
+ /* find closest neigh dir */
+ for (i=0; i<numOfNeighs; i++) {
+ int n_index = sData->adj_data->n_index[index]+i;
+ float dir_dot = dot_v3v3(bNeighs[n_index].dir, smudge_dir);
+
+ if (dir_dot>closest_d[0] && dir_dot>0.0f) {closest_d[0]=dir_dot; closest_id[0]=n_index;}
+ }
+
+ /* find other neigh */
+ for (i=0; i<numOfNeighs; i++) {
+ int n_index = sData->adj_data->n_index[index]+i;
+ float dir_dot = dot_v3v3(bNeighs[n_index].dir, smudge_dir);
+ float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
+
+ if (n_index == closest_id[0]) continue;
+
+ /* only accept neighbour at "other side" of the first one in relation to force dir
+ * so make sure angle between this and closest neigh is greater than first angle */
+ if (dir_dot>closest_d[1] && closest_dot<closest_d[0] && dir_dot>0.0f) {closest_d[1]=dir_dot; closest_id[1]=n_index;}
+ }
+
+ /* if two valid neighs found, change closest_d
+ * values to match final paint factors */
+ 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 force_intersect;
+
+ /* project force vector on the plane determined by these two neightbour points
+ * and calculate relative force angle from it*/
+ cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
+ normalize_v3(tangent);
+ force_intersect = dot_v3v3(smudge_dir, tangent);
+ madd_v3_v3v3fl(force_proj, smudge_dir, tangent, (-1.0f)*force_intersect);
+ normalize_v3(force_proj);
+
+ /* get drip factor based on force dir in relation to angle between those neighbours */
+ closest_d[1] = acos(dot_v3v3(bNeighs[closest_id[0]].dir, force_proj))/neigh_diff;
+ closest_d[0] = 1.0f - closest_d[1];
+
+ /* and multiply depending on how deeply force intersects surface */
+ closest_d[0] *= acos(fabs(force_intersect))/1.57079633f;
+ closest_d[1] *= acos(fabs(force_intersect))/1.57079633f;
+ }
+
+
+ /* Apply movement towards those two points */
+ 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 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 */
+ if (dir_dot <= 0.0f) continue;
+
+ dir_factor = dir_dot * speed_scale;
+ 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);
+ ePoint->alpha = ePoint->alpha*(1.0f-dir_factor) + pPoint->alpha*dir_factor;
+ }
+ }
+ }
+ }
}
/* paint effect default movement per frame in global units */
@@ -3630,14 +4150,12 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface)
*/
static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
{
- double average_dist = 0.0f;
double average_force = 0.0f;
float shrink_speed=0.0f, spread_speed=0.0f;
float fastest_effect;
int steps;
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
- BakeNeighPoint *bNeighs = bData->bNeighs;
Vec3f *realCoord = bData->realCoord;
int index;
@@ -3670,31 +4188,36 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
madd_v3_v3fl(forc, scene->physics_settings.gravity,
surface->effector_weights->global_gravity*surface->effector_weights->weight[0] / 10.f);
+ /* add surface point velocity and acceleration if enabled */
+ if (bData->velocity) {
+ if (surface->drip_vel)
+ madd_v3_v3fl(forc, bData->velocity[index].v, surface->drip_vel*(-1.0f));
+
+ /* acceleration */
+ if (bData->prev_velocity && surface->drip_acc) {
+ float acc[3];
+ VECCOPY(acc, bData->velocity[index].v);
+ sub_v3_v3(acc, bData->prev_velocity[index].v);
+ madd_v3_v3fl(forc, acc, surface->drip_acc*(-1.0f));
+ }
+ }
+
/* force strength */
(*force)[index*4+3] = len_v3(forc);
/* normalize and copy */
if ((*force)[index*4+3]) mul_v3_fl(forc, 1.0f/(*force)[index*4+3]);
VECCOPY(&((*force)[index*4]), forc);
}
- }
- pdEndEffectors(&effectors);
- }
-
- /* calculate average values (single thread) */
- for (index = 0; index < sData->total_points; index++)
- {
- int i;
- int numOfNeighs = sData->adj_data->n_num[index];
-
- if (*force)
- average_force += (*force)[index*4+3];
- for (i=0; i<numOfNeighs; i++) {
- average_dist += bNeighs[sData->adj_data->n_index[index]+i].dist;
+ /* calculate average values (single thread) */
+ for (index = 0; index < sData->total_points; index++)
+ {
+ average_force += (*force)[index*4+3];
+ }
+ average_force /= sData->total_points;
}
+ pdEndEffectors(&effectors);
}
- average_force /= sData->total_points;
- average_dist /= sData->adj_data->total_targets;
/* Get number of required steps using averate point distance
* so that just a few ultra close pixels wont up substeps to max */
@@ -3707,8 +4230,8 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
- steps = (int)ceil(EFF_MOVEMENT_PER_FRAME*fastest_effect/average_dist*timescale);
- CLAMP(steps, 1, 8);
+ steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/bData->average_dist*timescale);
+ CLAMP(steps, 1, 14);
//printf("Average distance is %f, avg force %f, num of steps %i\n", average_dist, average_force, steps);
@@ -3718,13 +4241,16 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
/*
* Processes active effect step.
*/
-static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale)
+static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps)
{
PaintSurfaceData *sData = surface->data;
BakeNeighPoint *bNeighs = sData->bData->bNeighs;
int index;
if (!sData->adj_data) return;
+
+ timescale /= steps;
+
/*
* Spread Effect
*/
@@ -3753,9 +4279,13 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
float w_factor, alphaAdd = 0.0f;
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;
totalAlpha += ePoint->e_alpha;
+ /* do color mixing */
+ if (color_mix) 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;
@@ -3839,21 +4369,23 @@ 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/10.0f;
+ float eff_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));
+
for (index = 0; index < sData->total_points; index++) {
int i;
int numOfNeighs = sData->adj_data->n_num[index];
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
+ PaintPoint *pPoint_prev = &prevPoint[index];
- /* to make dripping happen with as little spread as possible,
- * only use two closest point dirs "around" the force dir */
+ /* to make dripping happen with as little spread as possible, */
int closest_id[2] = {-1, -1};
float closest_d[2] = {-1.0f, -1.0f};
/* adjust drip speed depending on wetness */
- float w_factor = pPoint->wetness*0.4 - 0.05f;
+ float w_factor = pPoint_prev->wetness*0.5 - 0.025f;
if (w_factor <= 0) continue;
- w_factor *= w_factor;
/* find closest neigh dir */
for (i=0; i<numOfNeighs; i++) {
@@ -3879,22 +4411,26 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* if two valid neighs found, change closest_d
* values to match final paint factors */
if (closest_id[1] != -1) {
- float neigh_diff = dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
- /* linearize both values */
- neigh_diff *= neigh_diff;
- closest_d[0] *= closest_d[0];
-
- /* get relation to angle between neighs */
- closest_d[0] -= neigh_diff;
- /* and normalize as relative angle within neigh range */
- closest_d[0] /= 1.0f - neigh_diff;
-
- /* simply set other neigh to cover missing half of this factor */
- closest_d[1] = 1.0f - closest_d[0];
- }
- else if (closest_id[0] != -1) {
- /* if only one neigh, still linearize to minimize spread */
- closest_d[0] *= closest_d[0];
+ float force_proj[3];
+ float tangent[3];
+ float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
+ float force_intersect;
+
+ /* project force vector on the plane determined by these two neightbour points
+ * and calculate relative force angle from it*/
+ cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
+ normalize_v3(tangent);
+ force_intersect = dot_v3v3(&force[index*4], tangent);
+ madd_v3_v3v3fl(force_proj, &force[index*4], tangent, (-1.0f)*force_intersect);
+ normalize_v3(force_proj);
+
+ /* get drip factor based on force dir in relation to angle between those neighbours */
+ closest_d[1] = acos(dot_v3v3(bNeighs[closest_id[0]].dir, force_proj))/neigh_diff;
+ closest_d[0] = 1.0f - closest_d[1];
+
+ /* and multiply depending on how deeply force intersects surface */
+ closest_d[0] *= acos(fabs(force_intersect))/1.57079633f;
+ closest_d[1] *= acos(fabs(force_intersect))/1.57079633f;
}
@@ -3910,7 +4446,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
if (dir_dot <= 0.0f) continue;
dir_factor = dir_dot * speed_scale * w_factor;
- if (dir_factor > 1.0f) dir_factor = 1.0f;
+ 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);
@@ -3932,7 +4468,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
PaintPoint *cPoint = &((PaintPoint*)sData->type_data)[index];
if (cPoint->e_alpha > 1.0f) cPoint->e_alpha=1.0f;
- if (cPoint->wetness > 2.5f) cPoint->wetness=2.5f;
+ 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;
@@ -3999,7 +4535,7 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
float dist = bNeighs[n_index].dist;
PaintWavePoint *tPoint = &prevPoint[sData->adj_data->n_target[n_index]];
- if (!dist || tPoint->state) continue;
+ if (!dist || tPoint->state>0) continue;
if (dist<min_dist) dist=min_dist;
avg_dist += dist;
numOfN++;
@@ -4032,7 +4568,6 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
wPoint->velocity += force*dt * wave_speed*wave_speed;
/* damping */
wPoint->velocity *= damp_factor;
-
/* and new height */
wPoint->height += wPoint->velocity*dt;
}
@@ -4040,6 +4575,7 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
}
/* reset d_obs and state */
+ #pragma omp parallel for schedule(static)
for (index = 0; index < sData->total_points; index++) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
wPoint->state = 0;
@@ -4136,26 +4672,60 @@ static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob
return 0;
}
+static int surface_needsVelocityData(DynamicPaintSurface *surface, Scene *scene, Object *ob)
+{
+ if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP)
+ return 1;
+
+ if (surface_getBrushFlags(surface, scene, ob) & BRUSH_USES_VELOCITY)
+ return 1;
+
+ return 0;
+}
+
+static int surface_needsAccelerationData(DynamicPaintSurface *surface)
+{
+ if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP)
+ return 1;
+
+ return 0;
+}
+
/* Prepare for surface step by creating PaintBakeNormal data */
-static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Object *ob)
+static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *scene, Object *ob)
{
PaintSurfaceData *sData = surface->data;
PaintAdjData *adj_data = sData->adj_data;
PaintBakeData *bData = sData->bData;
DerivedMesh *dm = surface->canvas->dm;
- int index;
+ int index, new_bdata = 0;
+ int do_velocity_data = surface_needsVelocityData(surface, scene, ob);
+ int do_accel_data = surface_needsAccelerationData(surface);
int canvasNumOfVerts = dm->getNumVerts(dm);
MVert *mvert = dm->getVertArray(dm);
Vec3f *canvas_verts;
- /* if previous data exists and mesh hasn't moved, no need to recalc */
- if (bData && !dynamicPaint_surfaceHasMoved(surface, ob)) return 1;
+ if (bData) {
+ int surface_moved = dynamicPaint_surfaceHasMoved(surface, ob);
+
+ /* get previous speed for accelertaion */
+ if (do_accel_data && bData->prev_velocity && bData->velocity)
+ memcpy(bData->prev_velocity, bData->velocity, sData->total_points*sizeof(Vec3f));
+
+ /* reset speed vectors */
+ if (do_velocity_data && bData->velocity && (bData->clear || !surface_moved))
+ memset(bData->velocity, 0, sData->total_points*sizeof(Vec3f));
+
+ /* if previous data exists and mesh hasn't moved, no need to recalc */
+ if (!surface_moved)
+ return 1;
+ }
canvas_verts = (struct Vec3f *) MEM_mallocN(canvasNumOfVerts*sizeof(struct Vec3f), "Dynamic Paint transformed canvas verts");
if (!canvas_verts) return 0;
- /* alloc memory if required */
+ /* allocate memory if required */
if (!bData) {
sData->bData = bData = (struct PaintBakeData *) MEM_callocN(sizeof(struct PaintBakeData), "Dynamic Paint bake data");
if (!bData) {
@@ -4180,6 +4750,18 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Object *o
return printError(surface->canvas, "Not enough free memory.");
}
+
+ new_bdata = 1;
+ }
+
+ if (do_velocity_data && !bData->velocity) {
+ bData->velocity = (struct Vec3f *) MEM_callocN(sData->total_points*sizeof(Vec3f), "Dynamic Paint velocity");
+ }
+ if (do_accel_data && !bData->prev_velocity) {
+ bData->prev_velocity = (struct Vec3f *) MEM_mallocN(sData->total_points*sizeof(Vec3f), "Dynamic Paint prev velocity");
+ /* copy previous vel */
+ if (bData->prev_velocity && bData->velocity)
+ memcpy(bData->prev_velocity, bData->velocity, sData->total_points*sizeof(Vec3f));
}
/*
@@ -4198,6 +4780,10 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Object *o
#pragma omp parallel for schedule(static)
for (index=0; index<sData->total_points; index++)
{
+ float prev_point[3];
+ if (do_velocity_data && !new_bdata) {
+ VECCOPY(prev_point, bData->realCoord[bData->s_pos[index]].v);
+ }
/*
* Calculate current 3D-position of each surface pixel
*/
@@ -4270,14 +4856,25 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Object *o
normalize_v3(temp_nor);
}
else {
- temp_nor[0]=0.0f;
- temp_nor[1]=0.0f;
- temp_nor[2]=1.0f;
+ float n1[3], n2[3], n3[3];
+ ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
+ PaintUVPoint *tPoint = &((PaintUVPoint*)f_data->uv_p)[index];
+
+ normal_short_to_float_v3(n1, mvert[tPoint->v1].no);
+ normal_short_to_float_v3(n2, mvert[tPoint->v2].no);
+ normal_short_to_float_v3(n3, mvert[tPoint->v3].no);
+ interp_v3_v3v3v3(temp_nor,
+ n1, n2, n3, f_data->barycentricWeights[index*bData->s_num[index]].v);
}
- mul_v3_v3 (temp_nor, ob->size);
+ mul_v3_v3(temp_nor, ob->size);
bData->bNormal[index].normal_scale = len_v3(temp_nor);
}
+
+ /* calculate speed vector */
+ if (do_velocity_data && !new_bdata && !bData->clear) {
+ VECSUB(bData->velocity[index].v, bData->realCoord[bData->s_pos[index]].v, prev_point);
+ }
}
MEM_freeN(canvas_verts);
@@ -4286,51 +4883,15 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Object *o
surfaceGenerateGrid(surface);
/* calculate current frame neighbouring point distances and global dirs */
- dynamicPaint_prepareNeighbourData(surface);
+ dynamicPaint_prepareNeighbourData(surface, 0);
/* Copy current frame position to check against in next frame */
copy_m4_m4(bData->prev_obmat, ob->obmat);
memcpy(bData->prev_verts, mvert, canvasNumOfVerts*sizeof(MVert));
- return 1;
-}
-
-static void subframe_updateObject(Scene *scene, Object *ob, int update_parents, float frame)
-{
- int oflags;
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
-
- /* if other is dynamic paint canvas, dont update */
- if (pmd && pmd->canvas)
- return;
-
- /* if object has parent, update it too */
- if (update_parents && ob->parent) subframe_updateObject(scene, ob->parent, 0, frame);
- if (update_parents && ob->track) subframe_updateObject(scene, ob->track, 0, frame);
-
- /* for curve */
- if(ob->type==OB_CURVE) {
- Curve *cu= ob->data;
- BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM);
- }
-
- /* backup object flags */
- oflags = ob->recalc;
-
- ob->recalc |= OB_RECALC_ALL;
- ob->recalc |= OB_RECALC_DATA;
- BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM);
- object_handle_update(scene, ob);
-
- /* restore flags */
- ob->recalc = oflags;
-}
+ bData->clear = 0;
-static void scene_setSubframe(Scene *scene, float subframe)
-{
- /* dynamic paint subframes must be done on previous frame */
- scene->r.cfra -= 1;
- scene->r.subframe = subframe;
+ return 1;
}
/*
@@ -4398,23 +4959,35 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
{
DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
- /* Make sure we're dealing with a painter */
+ /* Make sure we're dealing with a brush */
if (pmd2->brush)
{
DynamicPaintBrushSettings *brush = pmd2->brush;
+ /* calculate brush speed vectors if required */
+ if (brush->flags & MOD_DPAINT_DO_SMUDGE) {
+ bData->brush_velocity = MEM_callocN(sData->total_points*sizeof(float)*4, "Dynamic Paint brush velocity");
+ /* init adjacency data if not already */
+ if (!sData->adj_data)
+ dynamicPaint_initAdjacencyData(surface, 1);
+ if (!bData->bNeighs)
+ dynamicPaint_prepareNeighbourData(surface, 1);
+ }
+
/* update object position on this subframe */
if (subframe) {
scene_setSubframe(scene, subframe);
- subframe_updateObject(scene, brushObj, 1, BKE_curframe(scene));
+ subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
}
/* If using material color, update anim data to current (sub)frame */
if (brush->flags & MOD_DPAINT_USE_MATERIAL)
dynamicPaint_updateObjectMaterials(brushObj, brush->mat, scene);
- /* Check if painter has a particle system selected
- * -> if so, do particle painting */
+ /*
+ * Paint brush on surface depending on it's collision type
+ */
+ /* Particle brush */
if (brush->collision == MOD_DPAINT_COL_PSYS)
{
if (brush && brush->psys && brush->psys->part && brush->psys->part->type==PART_EMITTER)
@@ -4425,21 +4998,30 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_paintParticles(surface, brush->psys, brush, ob, timescale);
}
}
+ /* Object center distance */
else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
- dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, ob, timescale);
+ dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, ob, brushObj, scene, timescale);
}
+ /* Mesh volume/proximity */
else if (brushObj != ob){
- /* Paint a mesh */
- dynamicPaint_paintMesh(surface, brush, ob, brushObj, timescale);
+ dynamicPaint_paintMesh(surface, brush, ob, brushObj, scene, timescale);
}
- /* return object to it's original state */
+ /* reset object to it's original state */
if (subframe) {
scene->r.cfra = scene_frame;
scene->r.subframe = scene_subframe;
- subframe_updateObject(scene, brushObj, 1, BKE_curframe(scene));
+ subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
dynamicPaint_updateObjectMaterials(brushObj, brush->mat, scene);
}
+
+ /* process special brush effects, like smudge */
+ if (bData->brush_velocity) {
+ if (brush->flags & MOD_DPAINT_DO_SMUDGE)
+ dynamicPaint_doSmudge(surface, brush);
+ MEM_freeN(bData->brush_velocity);
+ bData->brush_velocity = NULL;
+ }
} /* end of collision check (Is valid paint modifier) */
}
}
@@ -4462,10 +5044,8 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* Allocate memory for surface previous points to read unchanged values from */
prevPoint = MEM_mallocN(sData->total_points*sizeof(struct PaintPoint), "PaintSurfaceDataCopy");
- if (!prevPoint) {
- if (prevPoint) MEM_freeN(prevPoint);
+ if (!prevPoint)
return printError(canvas, "Not enough free memory.");
- }
/* Prepare effects and get number of required steps */
steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale);
@@ -4475,7 +5055,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
*/
for (s = 0; s < steps; s++)
{
- dynamicPaint_doEffectStep(surface, force, prevPoint, timescale/(float)steps);
+ dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
}
/* Free temporary effect data */
@@ -4493,10 +5073,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
static int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame)
{
float timescale = 1.0f;
- int ret;
/* update bake data */
- dynamicPaint_generateBakeData(surface, cObject);
+ dynamicPaint_generateBakeData(surface, scene, cObject);
/* dont do substeps for first frame */
if (surface->substeps && (frame != surface->start_frame)) {
@@ -4511,9 +5090,7 @@ static int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scen
}
}
- ret = dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f);
-
- return ret;
+ return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f);
}
/***************************** Image Sequence Baking ******************************/
@@ -4866,3 +5443,69 @@ void DPAINT_OT_type_toggle(wmOperatorType *ot)
ot->prop= prop;
}
+static int output_toggle_exec(bContext *C, wmOperator *op) {
+
+ Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ Scene *scene = CTX_data_scene(C);
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
+ int index= RNA_int_get(op->ptr, "index");
+
+ if (!pmd) return OPERATOR_CANCELLED;
+
+
+ /* if type is already enabled, toggle it off */
+ if (pmd->canvas) {
+ DynamicPaintSurface *surface = get_activeSurface(pmd->canvas);
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ int exists = dynamicPaint_outputLayerExists(surface, ob, index);
+ char *name;
+
+ if (index == 0)
+ name = surface->output_name;
+ else if (index == 1)
+ name = surface->output_name2;
+
+ /* Vertex Color Layer */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ if (!exists)
+ ED_mesh_color_add(C, scene, ob, ob->data, name, 1);
+ else
+ ED_mesh_color_remove_named(C, ob, ob->data, name);
+ }
+ /* Vertex Weight Layer */
+ else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
+ if (!exists)
+ ED_vgroup_add_name(ob, name);
+ else {
+ bDeformGroup *defgroup = defgroup_find_name(ob, name);
+ if (defgroup) ED_vgroup_delete(ob, defgroup);
+ }
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void DPAINT_OT_output_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Toggle Output Layer";
+ ot->idname= "DPAINT_OT_output_toggle";
+ ot->description = "Adds or removes Dynamic Paint output data layer.";
+
+ /* api callbacks */
+ ot->exec= output_toggle_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_int(ot->srna, "index", 0, 0, 1, "Index", "", 0, 1);
+ ot->prop= prop;
+}
+
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5c71915f7fe..43c1defdb96 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4089,6 +4089,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
pmd->brush->pmd = pmd;
pmd->brush->psys = newdataadr(fd, pmd->brush->psys);
pmd->brush->paint_ramp = newdataadr(fd, pmd->brush->paint_ramp);
+ pmd->brush->vel_ramp = newdataadr(fd, pmd->brush->vel_ramp);
pmd->brush->dm = NULL;
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 832d4442455..5285a1a0c74 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1288,6 +1288,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
{
writestruct(wd, DATA, "DynamicPaintBrushSettings", 1, pmd->brush);
writestruct(wd, DATA, "ColorBand", 1, pmd->brush->paint_ramp);
+ writestruct(wd, DATA, "ColorBand", 1, pmd->brush->vel_ramp);
}
}
else if (md->type==eModifierType_Collision) {
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 8bb77ad43a0..cb730c7ad4b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -240,6 +240,7 @@ int ED_mesh_uv_texture_add(struct bContext *C, struct Mesh *me, const char *name
int ED_mesh_uv_texture_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me, const char *name, int active_set);
int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
+int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index c4a302d4d18..c9e580fbe4b 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -299,6 +299,25 @@ int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
return 1;
}
+int ED_mesh_color_remove_named(bContext *C, Object *ob, Mesh *me, const char *name)
+{
+ CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ CustomDataLayer *cdl;
+ int index;
+
+ index= CustomData_get_named_layer_index(data, CD_MCOL, name);
+ cdl= (index == -1)? NULL: &data->layers[index];
+
+ if(!cdl)
+ return 0;
+
+ delete_customdata_layer(C, ob, cdl);
+ DAG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
+
+ return 1;
+}
+
/*********************** UV texture operators ************************/
static int layers_poll(bContext *C)
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index a0b9dde99c3..f5ddbd65a3c 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -100,6 +100,7 @@ void DPAINT_OT_bake(struct wmOperatorType *ot);
void DPAINT_OT_surface_slot_add(struct wmOperatorType *ot);
void DPAINT_OT_surface_slot_remove(struct wmOperatorType *ot);
void DPAINT_OT_type_toggle(struct wmOperatorType *ot);
+void DPAINT_OT_output_toggle(struct wmOperatorType *ot);
/* physics_pointcache.c */
void PTCACHE_OT_bake_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index da64775b83b..0235ccd5c89 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -174,6 +174,7 @@ static void operatortypes_dynamicpaint(void)
WM_operatortype_append(DPAINT_OT_surface_slot_add);
WM_operatortype_append(DPAINT_OT_surface_slot_remove);
WM_operatortype_append(DPAINT_OT_type_toggle);
+ WM_operatortype_append(DPAINT_OT_output_toggle);
}
//static void keymap_pointcache(wmWindowManager *wm)
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index d2c6e91904b..7793a0b34d8 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -85,6 +85,7 @@ typedef struct DynamicPaintSurface {
float disp_depth;
float spread_speed, shrink_speed;
+ float drip_vel, drip_acc;
/* wave settings */
float wave_damping, wave_speed, wave_timescale, wave_spring;
@@ -129,6 +130,13 @@ typedef struct DynamicPaintCanvasSettings {
#define MOD_DPAINT_INVERSE_PROX (1<<6) /* inverse proximity painting */
#define MOD_DPAINT_ACCEPT_NONCLOSED (1<<7) /* allows volume brushes to work with non-closed volumes */
+#define MOD_DPAINT_DO_SMUDGE (1<<8) /* brush smudges existing paint */
+#define MOD_DPAINT_VELOCITY_ALPHA (1<<9) /* multiply brush influence by velocity */
+#define MOD_DPAINT_VELOCITY_COLOR (1<<10) /* replace brush color by velocity color ramp */
+#define MOD_DPAINT_VELOCITY_DEPTH (1<<11) /* multiply brush intersection depth by velocity */
+
+#define MOD_DPAINT_USES_VELOCITY ((1<<8)|(1<<9)|(1<<10)|(1<<11))
+
/* collision type */
#define MOD_DPAINT_COL_VOLUME 0 /* paint with mesh volume */
#define MOD_DPAINT_COL_DIST 1 /* paint using distance to mesh surface */
@@ -151,7 +159,7 @@ typedef struct DynamicPaintCanvasSettings {
#define MOD_DPAINT_RAY_ZPLUS 1
-/* Painter settings */
+/* Brush settings */
typedef struct DynamicPaintBrushSettings {
struct DynamicPaintModifierData *pmd; /* for fast RNA access */
struct DerivedMesh *dm;
@@ -168,8 +176,9 @@ typedef struct DynamicPaintBrushSettings {
float paint_distance;
float displace_distance, prox_displace_strength;
- // Falloff curves
+ /* color ramps */
struct ColorBand *paint_ramp; /* Proximity paint falloff */
+ struct ColorBand *vel_ramp; /* Velocity paint ramp */
short proximity_falloff;
short brush_settings_context; /* ui settings display */
@@ -177,7 +186,8 @@ typedef struct DynamicPaintBrushSettings {
short ray_dir;
float wave_factor;
- float pad_f;
+ float max_velocity, smudge_strength;
+ float pad;
} DynamicPaintBrushSettings;
#endif
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 90275db503c..12aed3c8aac 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -199,6 +199,12 @@ static void rna_DynamicPaint_uses_cache_set(PointerRNA *ptr, int value)
{
}
+/* does output layer exist*/
+static int rna_DynamicPaint_is_output_exists(DynamicPaintSurface *surface, Object *ob, int index)
+{
+ return dynamicPaint_outputLayerExists(surface, ob, index);
+}
+
static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
{
@@ -279,6 +285,8 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
/* Surface format */
static EnumPropertyItem prop_dynamicpaint_surface_format[] = {
@@ -476,6 +484,18 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Effector Weights", "");
+ prop= RNA_def_property(srna, "drip_velocity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "drip_vel");
+ RNA_def_property_range(prop, -200.0f, 200.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Velocity", "Defines how much surface velocity affects dripping.");
+
+ prop= RNA_def_property(srna, "drip_acceleration", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "drip_acc");
+ RNA_def_property_range(prop, -200.0f, 200.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Acceleration", "Defines how much surface acceleration affects dripping.");
+
/*
* Output settings
*/
@@ -505,6 +525,17 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
prop= RNA_def_property(srna, "do_output2", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_OUT2);
RNA_def_property_ui_text(prop, "Save layer", "");
+
+ /* to check if output name exists */
+ func = RNA_def_function(srna, "output_exists", "rna_DynamicPaint_is_output_exists");
+ RNA_def_function_ui_description(func, "Checks if surface output layer of given name exists");
+ parm= RNA_def_pointer(func, "object", "Object", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
+ parm= RNA_def_int(func, "index", 0, 0, 1, "Index", "", 0, 1);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm= RNA_def_boolean(func, "exists", 0, "", "");
+ RNA_def_function_return(func, parm);
prop= RNA_def_property(srna, "displacement", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -626,7 +657,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
static EnumPropertyItem buttons_dynamicpaint_settings_menu[] = {
{0, "GENERAL", ICON_MOD_DYNAMICPAINT, "", "Show general settings"},
- //{1, "DISPLACE", ICON_MOD_DISPLACE, "", "Show displace related settings"},
+ {1, "VELOCITY", ICON_CURVE_PATH, "", "Show velocity related settings"},
{2, "WAVE", ICON_MOD_WAVE, "", "Show wave related settings"},
{0, NULL, 0, NULL, NULL}};
@@ -689,6 +720,34 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
RNA_def_property_range(prop, -2.0, 2.0);
RNA_def_property_ui_range(prop, -1.0, 1.0, 5, 2);
RNA_def_property_ui_text(prop, "Factor", "Multiplier for wave strenght of this brush.");
+
+ prop= RNA_def_property(srna, "do_smudge", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_DO_SMUDGE);
+ RNA_def_property_ui_text(prop, "Do Smudge", "");
+
+ prop= RNA_def_property(srna, "smudge_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "smudge_strength");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 2);
+ RNA_def_property_ui_text(prop, "Smudge Strength", "");
+
+ prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_velocity");
+ RNA_def_property_range(prop, 0.0001, 10.0);
+ RNA_def_property_ui_range(prop, 0.1, 2.0, 5, 2);
+ RNA_def_property_ui_text(prop, "Max Velocity", "");
+
+ prop= RNA_def_property(srna, "velocity_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_VELOCITY_ALPHA);
+ RNA_def_property_ui_text(prop, "Multiply Alpha", "Multiply brush influence by velocity color ramp alpha.");
+
+ prop= RNA_def_property(srna, "velocity_depth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_VELOCITY_DEPTH);
+ RNA_def_property_ui_text(prop, "Multiply Depth", "Multiply brush intersection depth (displace, waves) by velocity color ramp alpha.");
+
+ prop= RNA_def_property(srna, "velocity_color", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_VELOCITY_COLOR);
+ RNA_def_property_ui_text(prop, "Replace Color", "Replace brush color by velocity color ramp.");
/*
* Paint Area / Collision
@@ -780,6 +839,11 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "paint_ramp");
RNA_def_property_struct_type(prop, "ColorRamp");
RNA_def_property_ui_text(prop, "Paint Color Ramp", "Color ramp used to define proximity falloff.");
+
+ prop= RNA_def_property(srna, "velocity_ramp", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "vel_ramp");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Velocity Color Ramp", "");
}
void RNA_def_dynamic_paint(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index ba01b1f36ba..58d7890b0ce 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -63,26 +63,14 @@ static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
return dataMask;
}
-/*static void deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
- float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)*/
-
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm,
int useRenderParams,
int isFinalCalc)
{
DynamicPaintModifierData *pmd = (DynamicPaintModifierData*) md;
- //DerivedMesh *dm = get_cddm(ob, NULL, derivedData, vertexCos);
- DerivedMesh *result;
-
-
- result = dynamicPaint_Modifier_do(pmd, md->scene, ob, dm);
-
- /*if(dm != derivedData)
- dm->release(dm);*/
- return result;
+ return dynamicPaint_Modifier_do(pmd, md->scene, ob, dm);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 13c9706ddc0..78f0407943f 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -195,6 +195,7 @@ struct Tex;
struct MTex;
struct ImBuf;
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, short thread, short which_output);
/* this one uses nodes */
int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres);
/* nodes disabled */
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 71f939bbc71..63cc87915aa 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -1164,7 +1164,7 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *n, float *d
/* ************************************** */
-static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output)
+int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output)
{
float tmpvec[3];
int retval=0; /* return value, int:0, col:1, nor:2, everything:3 */
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 5ef340be89b..301d5ba5568 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1112,11 +1112,24 @@ void shade_input_set_shade_texco(ShadeInput *shi)
cp1= (char *)(mcol+j1);
cp2= (char *)(mcol+j2);
cp3= (char *)(mcol+j3);
+
+ /* alpha value */
+ scol->col[3]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f;
+ /* try to prevent invalid color sampling of zero alpha points */
+ if (!cp1[3]) cp1 = cp2;
+ if (!cp1[3]) cp1 = cp3;
+
+ if (!cp2[3]) cp2 = cp1;
+ if (!cp2[3]) cp1 = cp3;
+
+ if (!cp3[3]) cp3 = cp1;
+ if (!cp3[3]) cp3 = cp2;
+
+ /* sample color value */
scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f;
scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f;
scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f;
- scol->col[3]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f;
}
if(shi->totcol) {
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 00c993bb9f8..017c74a8edb 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -118,6 +118,7 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize,
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) {}
/* texture.c */
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, short thread, short which_output) {return 0;}
int multitex_thread(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, short thread, short which_output) {return 0;}
int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres){return 0;}
int multitex_ext_safe(struct Tex *tex, float *texvec, struct TexResult *texres){return 0;}
@@ -285,6 +286,7 @@ void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count)
void ED_mesh_faces_add(struct Mesh *mesh, struct ReportList *reports, int count){}
void ED_mesh_material_link(struct Mesh *mesh, struct Material *ma){}
int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me){return 0;}
+int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name){return 0;}
int ED_mesh_uv_texture_add(struct bContext *C, struct Mesh *me){return 0;}
void ED_object_constraint_dependency_update(struct Scene *scene, struct Object *ob){}
void ED_object_constraint_update(struct Object *ob){}