Blender V2.61 - r43446

dynamicpaint.c

Go to the documentation of this file.
00001 
00015 #include "MEM_guardedalloc.h"
00016 
00017 #include <math.h>
00018 #include <stdio.h>
00019 
00020 #include "BLI_blenlib.h"
00021 #include "BLI_math.h"
00022 #include "BLI_kdtree.h"
00023 #include "BLI_threads.h"
00024 #include "BLI_utildefines.h"
00025 
00026 #include "DNA_anim_types.h"
00027 #include "DNA_constraint_types.h"
00028 #include "DNA_dynamicpaint_types.h"
00029 #include "DNA_group_types.h" /*GroupObject*/
00030 #include "DNA_material_types.h"
00031 #include "DNA_mesh_types.h"
00032 #include "DNA_meshdata_types.h"
00033 #include "DNA_modifier_types.h"
00034 #include "DNA_object_types.h"
00035 #include "DNA_scene_types.h"
00036 #include "DNA_space_types.h"
00037 #include "DNA_texture_types.h"
00038 
00039 #include "BKE_animsys.h"
00040 #include "BKE_bvhutils.h"   /* bvh tree */
00041 #include "BKE_blender.h"
00042 #include "BKE_cdderivedmesh.h"
00043 #include "BKE_constraint.h"
00044 #include "BKE_context.h"
00045 #include "BKE_customdata.h"
00046 #include "BKE_colortools.h"
00047 #include "BKE_deform.h"
00048 #include "BKE_depsgraph.h"
00049 #include "BKE_DerivedMesh.h"
00050 #include "BKE_dynamicpaint.h"
00051 #include "BKE_effect.h"
00052 #include "BKE_global.h"
00053 #include "BKE_image.h"
00054 #include "BKE_main.h"
00055 #include "BKE_material.h"
00056 #include "BKE_modifier.h"
00057 #include "BKE_object.h"
00058 #include "BKE_particle.h"
00059 #include "BKE_pointcache.h"
00060 #include "BKE_scene.h"
00061 #include "BKE_texture.h"
00062 
00063 #include "RNA_access.h"
00064 #include "RNA_define.h"
00065 #include "RNA_enum_types.h"
00066 
00067 /* for image output */
00068 #include "IMB_imbuf_types.h"
00069 #include "IMB_imbuf.h"
00070 
00071 /* to read material/texture color   */
00072 #include "RE_render_ext.h"
00073 #include "RE_shader_ext.h"
00074 
00075 #ifdef _OPENMP
00076 #include <omp.h>
00077 #endif
00078 
00079 /* precalculated gaussian factors for 5x super sampling */
00080 static float gaussianFactors[5] = { 0.996849f,
00081                                 0.596145f,
00082                                 0.596145f,
00083                                 0.596145f,
00084                                 0.524141f};
00085 static float gaussianTotal = 3.309425f;
00086 
00087 /* UV Image neighbouring pixel table x and y list */
00088 static int neighX[8] = {1,1,0,-1,-1,-1, 0, 1};
00089 static int neighY[8] = {0,1,1, 1, 0,-1,-1,-1};
00090 
00091 /* subframe_updateObject() flags */
00092 #define UPDATE_PARENTS (1<<0)
00093 #define UPDATE_MESH (1<<1)
00094 #define UPDATE_EVERYTHING (UPDATE_PARENTS|UPDATE_MESH)
00095 /* surface_getBrushFlags() return vals */
00096 #define BRUSH_USES_VELOCITY (1<<0)
00097 /* brush mesh raycast status */
00098 #define HIT_VOLUME 1
00099 #define HIT_PROXIMITY 2
00100 /* paint effect default movement per frame in global units */
00101 #define EFF_MOVEMENT_PER_FRAME 0.05f
00102 /* initial wave time factor */
00103 #define WAVE_TIME_FAC (1.0f/24.f)
00104 #define CANVAS_REL_SIZE 5.0f
00105 /* drying limits */
00106 #define MIN_WETNESS 0.001f
00107 #define MAX_WETNESS 5.0f
00108 /* dissolve macro */
00109 #define VALUE_DISSOLVE(VALUE, TIME, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) * (pow(MIN_WETNESS,1.0f/(1.2f*((float)(TIME))/(SCALE)))) : (VALUE) - 1.0f/(TIME)*(SCALE)
00110 
00111 /***************************** Internal Structs ***************************/
00112 
00113 typedef struct Bounds2D {
00114     float min[2], max[2];
00115 } Bounds2D;
00116 
00117 typedef struct Bounds3D {
00118     int valid;
00119     float min[3], max[3];
00120 } Bounds3D;
00121 
00122 typedef struct VolumeGrid {
00123     int dim[3];
00124     Bounds3D grid_bounds; /* whole grid bounds */
00125 
00126     Bounds3D *bounds;   /* (x*y*z) precalculated grid cell bounds */
00127     int *s_pos; /* (x*y*z) t_index begin id */
00128     int *s_num; /* (x*y*z) number of t_index points */
00129     int *t_index; /* actual surface point index,
00130                            access: (s_pos+s_num) */
00131 } VolumeGrid;
00132 
00133 typedef struct Vec3f {
00134     float v[3];
00135 } Vec3f;
00136 
00137 typedef struct BakeNeighPoint {
00138     float dir[3];   /* vector pointing towards this neighbour */
00139     float dist;     /* distance to */
00140 } BakeNeighPoint;
00141 
00142 /* Surface data used while processing a frame   */
00143 typedef struct PaintBakeNormal {
00144     float invNorm[3];  /* current pixel world-space inverted normal */
00145     float normal_scale; /* normal directional scale for displace mapping */
00146 } PaintBakeNormal;
00147 
00148 /* Temp surface data used to process a frame */
00149 typedef struct PaintBakeData {
00150     /* point space data */
00151     PaintBakeNormal *bNormal;
00152     int *s_pos; /* index to start reading point sample realCoord */
00153     int *s_num; /* num of realCoord samples */
00154     Vec3f *realCoord;  /* current pixel center world-space coordinates for each sample
00155                        *  ordered as (s_pos+s_num)*/
00156     Bounds3D mesh_bounds;
00157 
00158     /* adjacency info */
00159     BakeNeighPoint *bNeighs; /* current global neighbour distances and directions, if required */
00160     double average_dist;
00161     /* space partitioning */
00162     VolumeGrid *grid;       /* space partitioning grid to optimize brush checks */
00163 
00164     /* velocity and movement */
00165     Vec3f *velocity;        /* speed vector in global space movement per frame, if required */
00166     Vec3f *prev_velocity;
00167     float *brush_velocity;  /* special temp data for post-p velocity based brushes like smudge
00168                             *  3 float dir vec + 1 float str */
00169     MVert *prev_verts;      /* copy of previous frame vertices. used to observe surface movement */
00170     float prev_obmat[4][4]; /* previous frame object matrix */
00171     int clear;              /* flag to check if surface was cleared/reset -> have to redo velocity etc. */
00172 
00173 } PaintBakeData;
00174 
00175 /* UV Image sequence format point   */
00176 typedef struct PaintUVPoint {
00177     /* Pixel / mesh data */
00178     unsigned int face_index, pixel_index;   /* face index on domain derived mesh */
00179     unsigned int v1, v2, v3;                /* vertex indexes */
00180 
00181     unsigned int neighbour_pixel;   /* If this pixel isn't uv mapped to any face,
00182                                        but it's neighbouring pixel is */
00183     short quad;
00184 } PaintUVPoint;
00185 
00186 typedef struct ImgSeqFormatData {
00187     PaintUVPoint *uv_p;
00188     Vec3f *barycentricWeights;      /* b-weights for all pixel samples */
00189 } ImgSeqFormatData;
00190 
00191 typedef struct EffVelPoint {
00192     float previous_pos[3];
00193     float previous_vel[3];
00194 } EffVelPoint;
00195 
00196 
00197 /* adjacency data flags */
00198 #define ADJ_ON_MESH_EDGE (1<<0)
00199 
00200 typedef struct PaintAdjData {
00201     int *n_target;      /* array of neighbouring point indexes,
00202                                    for single sample use (n_index+neigh_num) */
00203     int *n_index;       /* index to start reading n_target for each point */
00204     int *n_num;     /* num of neighs for each point */
00205     int *flags;     /* vertex adjacency flags */
00206     int total_targets; /* size of n_target */
00207 } PaintAdjData;
00208 
00209 /***************************** General Utils ******************************/
00210 
00211 /* Set canvas error string to display at the bake report */
00212 static int setError(DynamicPaintCanvasSettings *canvas, const char *string)
00213 {
00214     /* Add error to canvas ui info label */
00215     BLI_strncpy(canvas->error, string, sizeof(canvas->error));
00216     return 0;
00217 }
00218 
00219 /* Get number of surface points for cached types */
00220 static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
00221 {
00222     if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
00223         return 0; /* not supported atm */
00224     }
00225     else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
00226         if (!surface->canvas->dm) return 0; /* invalid derived mesh */
00227         return surface->canvas->dm->getNumVerts(surface->canvas->dm);
00228     }
00229     else
00230         return 0;
00231 }
00232 
00233 /* checks whether surface's format/type has realtime preview */
00234 int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface)
00235 {
00236     if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 0;
00237     else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
00238         if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
00239             surface->type == MOD_DPAINT_SURFACE_T_WAVE) return 0;
00240         else return 1;
00241     }
00242     else return 1;
00243 }
00244 
00245 /* get currently active surface (in user interface) */
00246 struct DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
00247 {
00248     DynamicPaintSurface *surface = canvas->surfaces.first;
00249     int i;
00250 
00251     for(i=0; surface; surface=surface->next) {
00252         if(i == canvas->active_sur)
00253             return surface;
00254         i++;
00255     }
00256     return NULL;
00257 }
00258 
00259 /* set preview to first previewable surface */
00260 void dynamicPaint_resetPreview(DynamicPaintCanvasSettings *canvas)
00261 {
00262     DynamicPaintSurface *surface = canvas->surfaces.first;
00263     int done=0;
00264 
00265     for(; surface; surface=surface->next) {
00266         if (!done && dynamicPaint_surfaceHasColorPreview(surface)) {
00267             surface->flags |= MOD_DPAINT_PREVIEW;
00268             done=1;
00269         }
00270         else
00271             surface->flags &= ~MOD_DPAINT_PREVIEW;
00272     }
00273 }
00274 
00275 /* set preview to defined surface */
00276 static void dynamicPaint_setPreview(DynamicPaintSurface *t_surface)
00277 {
00278     DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
00279     for(; surface; surface=surface->next) {
00280         if (surface == t_surface)
00281             surface->flags |= MOD_DPAINT_PREVIEW;
00282         else
00283             surface->flags &= ~MOD_DPAINT_PREVIEW;
00284     }
00285 }
00286 
00287 int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *ob, int output)
00288 {
00289     char *name;
00290 
00291     if (output == 0)
00292         name = surface->output_name;
00293     else if (output == 1)
00294         name = surface->output_name2;
00295     else
00296         return 0;
00297 
00298     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
00299         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
00300             Mesh *me = ob->data;
00301             return (CustomData_get_named_layer_index(&me->fdata, CD_MCOL, name) != -1);
00302         }
00303         else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
00304             return (defgroup_name_index(ob, surface->output_name) != -1);
00305     }
00306 
00307     return 0;
00308 }
00309 
00310 static int surface_duplicateOutputExists(void *arg, const char *name)
00311 {
00312     DynamicPaintSurface *t_surface = (DynamicPaintSurface*)arg;
00313     DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
00314 
00315     for(; surface; surface=surface->next) {
00316         if (surface!=t_surface && surface->type==t_surface->type &&
00317             surface->format==t_surface->format) {
00318             if (surface->output_name[0]!='\0' && !strcmp(name, surface->output_name)) return 1;
00319             if (surface->output_name2[0]!='\0' && !strcmp(name, surface->output_name2)) return 1;
00320         }
00321     }
00322     return 0;
00323 }
00324 
00325 static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output)
00326 {
00327     char name[64];
00328     BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
00329     if (!output)
00330         BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name, sizeof(surface->output_name));
00331     if (output)
00332         BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name2, sizeof(surface->output_name2));
00333 }
00334 
00335 
00336 static int surface_duplicateNameExists(void *arg, const char *name)
00337 {
00338     DynamicPaintSurface *t_surface = (DynamicPaintSurface*)arg;
00339     DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
00340 
00341     for(; surface; surface=surface->next) {
00342         if (surface!=t_surface && !strcmp(name, surface->name)) return 1;
00343     }
00344     return 0;
00345 }
00346 
00347 void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename)
00348 {
00349     char name[64];
00350     BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
00351     BLI_uniquename_cb(surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
00352 }
00353 
00354 
00355 /* change surface data to defaults on new type */
00356 void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
00357 {
00358     if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
00359         surface->output_name[0]='\0';
00360         surface->output_name2[0]='\0';
00361         surface->flags |= MOD_DPAINT_ANTIALIAS;
00362         surface->depth_clamp = 1.0f;
00363     }
00364     else {
00365         strcpy(surface->output_name, "dp_");
00366         strcpy(surface->output_name2, surface->output_name);
00367         surface->flags &= ~MOD_DPAINT_ANTIALIAS;
00368         surface->depth_clamp = 0.0f;
00369     }
00370 
00371     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
00372         strcat(surface->output_name,"paintmap");
00373         strcat(surface->output_name2,"wetmap");
00374         surface_setUniqueOutputName(surface, surface->output_name2, 1);
00375     }
00376     else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
00377         strcat(surface->output_name,"displace");
00378     }
00379     else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
00380         strcat(surface->output_name,"weight");
00381     }
00382     else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
00383         strcat(surface->output_name,"wave");
00384     }
00385 
00386     surface_setUniqueOutputName(surface, surface->output_name, 0);
00387 
00388     /* update preview */
00389     if (dynamicPaint_surfaceHasColorPreview(surface))
00390         dynamicPaint_setPreview(surface);
00391     else
00392         dynamicPaint_resetPreview(surface->canvas);
00393 }
00394 
00395 static int surface_totalSamples(DynamicPaintSurface *surface)
00396 {
00397     if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ &&
00398         surface->flags & MOD_DPAINT_ANTIALIAS)
00399         return (surface->data->total_points*5);
00400     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
00401         surface->flags & MOD_DPAINT_ANTIALIAS && surface->data->adj_data)
00402         return (surface->data->total_points+surface->data->adj_data->total_targets);
00403 
00404     return surface->data->total_points;
00405 }
00406 
00407 static void blendColors(float t_color[3], float t_alpha, float s_color[3], float s_alpha, float result[4])
00408 {
00409     int i;
00410     float i_alpha = 1.0f - s_alpha;
00411     float f_alpha = t_alpha*i_alpha + s_alpha;
00412 
00413     /* blend colors */
00414     if (f_alpha) {
00415         for (i=0; i<3; i++) {
00416             result[i] = (t_color[i]*t_alpha*i_alpha + s_color[i]*s_alpha)/f_alpha;
00417         }
00418     }
00419     else {
00420         copy_v3_v3(result, t_color);
00421     }
00422     /* return final alpha */
00423     result[3] = f_alpha;
00424 }
00425 
00426 /* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */
00427 static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio)
00428 {
00429     float weight_ratio, factor;
00430     if (b_weight) {
00431         /* if first value has no weight just use b_color */
00432         if (!a_weight) {
00433             copy_v3_v3(a_color, b_color);
00434             return b_weight*ratio;
00435         }
00436         weight_ratio = b_weight/(a_weight+b_weight);
00437     }
00438     else return a_weight*(1.0f-ratio);
00439 
00440     /* calculate final interpolation factor */
00441     if (ratio<=0.5f) {
00442         factor = weight_ratio*(ratio*2.0f);
00443     }
00444     else {
00445         ratio = (ratio*2.0f - 1.0f);
00446         factor = weight_ratio*(1.0f-ratio) + ratio;
00447     }
00448     /* mix final color */
00449     interp_v3_v3v3(a_color, a_color, b_color, factor);
00450     return (1.0f-factor)*a_weight + factor*b_weight;
00451 }
00452 
00453 /* set "ignore cache" flag for all caches on this object */
00454 static void object_cacheIgnoreClear(Object *ob, int state)
00455 {
00456     ListBase pidlist;
00457     PTCacheID *pid;
00458     BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
00459 
00460     for(pid=pidlist.first; pid; pid=pid->next) {
00461         if(pid->cache) {
00462             if (state)
00463                 pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
00464             else
00465                 pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
00466         }
00467     }
00468 
00469     BLI_freelistN(&pidlist);
00470 }
00471 
00472 static void subframe_updateObject(Scene *scene, Object *ob, int flags, float frame)
00473 {
00474     DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
00475     bConstraint *con;
00476 
00477     /* if other is dynamic paint canvas, dont update */
00478     if (pmd && pmd->canvas)
00479         return;
00480 
00481     /* if object has parents, update them too */
00482     if (flags & UPDATE_PARENTS) {
00483         if (ob->parent) subframe_updateObject(scene, ob->parent, 0, frame);
00484         if (ob->track) subframe_updateObject(scene, ob->track, 0, frame);
00485 
00486         /* also update constraint targets */
00487         for (con = ob->constraints.first; con; con=con->next) {
00488             bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00489             ListBase targets = {NULL, NULL};
00490 
00491             if (cti && cti->get_constraint_targets) {
00492                 bConstraintTarget *ct;
00493                 cti->get_constraint_targets(con, &targets);
00494                 for (ct= targets.first; ct; ct= ct->next) {
00495                     if (ct->tar)
00496                         subframe_updateObject(scene, ct->tar, 0, frame);
00497                 }
00498                 /* free temp targets */
00499                 if (cti->flush_constraint_targets)
00500                     cti->flush_constraint_targets(con, &targets, 0);
00501             }
00502         }
00503     }
00504     /* for curve following objects, parented curve has to be updated too */
00505     if(ob->type==OB_CURVE) {
00506         Curve *cu= ob->data;
00507         BKE_animsys_evaluate_animdata(scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM);
00508     }
00509 
00510     ob->recalc |= OB_RECALC_ALL;
00511     BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
00512     if (flags & UPDATE_MESH) {
00513         /* ignore cache clear during subframe updates
00514         *  to not mess up cache validity */
00515         object_cacheIgnoreClear(ob, 1);
00516         object_handle_update(scene, ob);
00517         object_cacheIgnoreClear(ob, 0);
00518     }
00519     else
00520         where_is_object_time(scene, ob, frame);
00521 }
00522 
00523 static void scene_setSubframe(Scene *scene, float subframe)
00524 {
00525     /* dynamic paint subframes must be done on previous frame */
00526     scene->r.cfra -= 1;
00527     scene->r.subframe = subframe;
00528 }
00529 
00530 static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene)
00531 {
00532     Base *base = NULL;
00533     GroupObject *go = NULL; 
00534     Object *brushObj = NULL;
00535     ModifierData *md = NULL;
00536 
00537     int flags = 0;
00538 
00539     if(surface->brush_group)
00540         go = surface->brush_group->gobject.first;
00541     else
00542         base = scene->base.first;
00543 
00544     while (base || go)
00545     {
00546         brushObj = NULL;
00547 
00548         /* select object */
00549         if(surface->brush_group) {                      
00550             if(go->ob)  brushObj = go->ob;                  
00551         }                   
00552         else                        
00553             brushObj = base->object;
00554 
00555         if(!brushObj)                   
00556         {
00557             if(surface->brush_group) go = go->next;
00558             else base= base->next;                  
00559             continue;           
00560         }
00561 
00562         if(surface->brush_group)
00563             go = go->next;
00564         else
00565             base= base->next;
00566 
00567         md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
00568         if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))                    
00569         {
00570             DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
00571 
00572             if (pmd2->brush)
00573             {
00574                 DynamicPaintBrushSettings *brush = pmd2->brush;
00575 
00576                 if (brush->flags & MOD_DPAINT_USES_VELOCITY)
00577                     flags |= BRUSH_USES_VELOCITY;
00578             }
00579         }
00580     }
00581 
00582     return flags;
00583 }
00584 
00585 static int brush_usesMaterial(DynamicPaintBrushSettings *brush, Scene *scene)
00586 {
00587     return ((brush->flags & MOD_DPAINT_USE_MATERIAL) && (!strcmp(scene->r.engine, "BLENDER_RENDER")));
00588 }
00589 
00590 /* check whether two bounds intersect */
00591 static int boundsIntersect(Bounds3D *b1, Bounds3D *b2)
00592 {
00593     int i=2;
00594     if (!b1->valid || !b2->valid) return 0;
00595     for (; i>=0; i-=1)
00596         if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) return 0;
00597     return 1;
00598 }
00599 
00600 /* check whether two bounds intersect inside defined proximity */
00601 static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist)
00602 {
00603     int i=2;
00604     if (!b1->valid || !b2->valid) return 0;
00605     for (; i>=0; i-=1)
00606         if (!(b1->min[i] <= (b2->max[i]+dist) && b1->max[i] >= (b2->min[i]-dist))) return 0;
00607     return 1;
00608 }
00609 
00610 /* check whether bounds intersects a point with given radius */
00611 static int boundIntersectPoint(Bounds3D *b, float point[3], float radius)
00612 {
00613     int i=2;
00614     if (!b->valid) return 0;
00615     for (; i>=0; i-=1)
00616         if (!(b->min[i] <= (point[i]+radius) && b->max[i] >= (point[i]-radius))) return 0;
00617     return 1;
00618 }
00619 
00620 /* expand bounds by a new point */
00621 static void boundInsert(Bounds3D *b, float point[3])
00622 {
00623     int i=2;
00624     if (!b->valid) {
00625         copy_v3_v3(b->min, point);
00626         copy_v3_v3(b->max, point);
00627         b->valid = 1;
00628     }
00629     else {
00630         for (; i>=0; i-=1) {
00631             if (point[i] < b->min[i]) b->min[i]=point[i];
00632             if (point[i] > b->max[i]) b->max[i]=point[i];
00633         }
00634     }
00635 }
00636 
00637 float getSurfaceDimension(PaintSurfaceData *sData)
00638 {
00639     Bounds3D *mb = &sData->bData->mesh_bounds;
00640     return MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
00641 }
00642 
00643 static void freeGrid(PaintSurfaceData *data)
00644 {
00645     PaintBakeData *bData = data->bData;
00646     VolumeGrid *grid = bData->grid;
00647 
00648     if (grid->bounds) MEM_freeN(grid->bounds);
00649     if (grid->s_pos) MEM_freeN(grid->s_pos);
00650     if (grid->s_num) MEM_freeN(grid->s_num);
00651     if (grid->t_index) MEM_freeN(grid->t_index);
00652 
00653     MEM_freeN(bData->grid);
00654     bData->grid = NULL;
00655 }
00656 
00657 static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
00658 {
00659     PaintSurfaceData *sData = surface->data;
00660     PaintBakeData *bData = sData->bData;
00661     Bounds3D *grid_bounds;
00662     VolumeGrid *grid;
00663     int grid_cells, axis = 3;
00664     int *temp_t_index = NULL;
00665     int *temp_s_num = NULL;
00666 
00667 #ifdef _OPENMP
00668     int num_of_threads = omp_get_max_threads();
00669 #else
00670     int num_of_threads = 1;
00671 #endif
00672 
00673     if (bData->grid)
00674         freeGrid(sData);
00675 
00676     /* allocate separate bounds for each thread */
00677     grid_bounds = MEM_callocN(sizeof(Bounds3D)*num_of_threads, "Grid Bounds");
00678     bData->grid = MEM_callocN(sizeof(VolumeGrid), "Surface Grid");
00679     grid = bData->grid;
00680 
00681     if (grid && grid_bounds) {
00682         int i, error = 0;
00683         float dim_factor, volume, dim[3];
00684         float td[3];
00685         float min_dim;
00686 
00687         /* calculate canvas dimensions */
00688         #pragma omp parallel for schedule(static)
00689         for (i=0; i<sData->total_points; i++) {
00690             #ifdef _OPENMP
00691             int id = omp_get_thread_num();
00692             boundInsert(&grid_bounds[id], (bData->realCoord[bData->s_pos[i]].v));
00693             #else
00694             boundInsert(&grid_bounds[0], (bData->realCoord[bData->s_pos[i]].v));
00695             #endif
00696         }
00697 
00698         /* get final dimensions */
00699         for (i=0; i<num_of_threads; i++) {
00700             boundInsert(&grid->grid_bounds, grid_bounds[i].min);
00701             boundInsert(&grid->grid_bounds, grid_bounds[i].max);
00702         }
00703 
00704         /* get dimensions */
00705         sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min);
00706         copy_v3_v3(td, dim);
00707         min_dim = MAX3(td[0],td[1],td[2]) / 1000.f;
00708 
00709         /* deactivate zero axises */
00710         for (i=0; i<3; i++) {
00711             if (td[i]<min_dim) {td[i]=1.0f; axis-=1;}
00712         }
00713 
00714         if (axis == 0 || MAX3(td[0],td[1],td[2]) < 0.0001f) {
00715             MEM_freeN(grid_bounds);
00716             MEM_freeN(bData->grid);
00717             bData->grid = NULL;
00718             return;
00719         }
00720 
00721         /* now calculate grid volume/area/width depending on num of active axis */
00722         volume = td[0]*td[1]*td[2];
00723 
00724         /* determine final grid size by trying to fit average 10.000 points per grid cell */
00725         dim_factor = (float)pow(volume / ((double)sData->total_points / 10000.0), 1.0/(double)axis);
00726 
00727         /* define final grid size using dim_factor, use min 3 for active axises */
00728         for (i=0; i<3; i++) {
00729             grid->dim[i] = (int)floor(td[i] / dim_factor);
00730             CLAMP(grid->dim[i], (dim[i]>=min_dim) ? 3 : 1, 100);
00731         }
00732         grid_cells = grid->dim[0]*grid->dim[1]*grid->dim[2];
00733 
00734         /* allocate memory for grids */
00735         grid->bounds = MEM_callocN(sizeof(Bounds3D) * grid_cells, "Surface Grid Bounds");
00736         grid->s_pos = MEM_callocN(sizeof(int) * grid_cells, "Surface Grid Position");
00737         grid->s_num = MEM_callocN(sizeof(int) * grid_cells*num_of_threads, "Surface Grid Points");
00738         temp_s_num = MEM_callocN(sizeof(int) * grid_cells, "Temp Surface Grid Points");
00739         grid->t_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Grid Target Ids");
00740         temp_t_index = MEM_callocN(sizeof(int) * sData->total_points, "Temp Surface Grid Target Ids");
00741 
00742         /* in case of an allocation failture abort here */
00743         if (!grid->bounds || !grid->s_pos || !grid->s_num || !grid->t_index || !temp_s_num || !temp_t_index)
00744             error = 1;
00745 
00746         if (!error) {
00747             /* calculate number of points withing each cell */
00748             #pragma omp parallel for schedule(static)
00749             for (i=0; i<sData->total_points; i++) {
00750                 int co[3], j;
00751                 for (j=0; j<3; j++) {
00752                     co[j] = (int)floor((bData->realCoord[bData->s_pos[i]].v[j] - grid->grid_bounds.min[j])/dim[j]*grid->dim[j]);
00753                     CLAMP(co[j], 0, grid->dim[j]-1);
00754                 }
00755 
00756                 temp_t_index[i] = co[0] + co[1] * grid->dim[0] + co[2] * grid->dim[0]*grid->dim[1];
00757                 #ifdef _OPENMP
00758                 grid->s_num[temp_t_index[i]+omp_get_thread_num()*grid_cells]++;
00759                 #else
00760                 grid->s_num[temp_t_index[i]]++;
00761                 #endif
00762             }
00763 
00764             /* for first cell only calc s_num */
00765             for (i=1; i<num_of_threads; i++) {
00766                 grid->s_num[0] += grid->s_num[i*grid_cells];
00767             }
00768 
00769             /* calculate grid indexes */
00770             for (i=1; i<grid_cells; i++) {
00771                 int id;
00772                 for (id=1; id<num_of_threads; id++) {
00773                     grid->s_num[i] += grid->s_num[i+id*grid_cells];
00774                 }
00775                 grid->s_pos[i] = grid->s_pos[i-1] + grid->s_num[i-1];
00776             }
00777 
00778             /* save point indexes to final array */
00779             for (i=0; i<sData->total_points; i++) {
00780                 int pos = grid->s_pos[temp_t_index[i]] + temp_s_num[temp_t_index[i]];
00781                 grid->t_index[pos] = i;
00782 
00783                 temp_s_num[temp_t_index[i]]++;
00784             }
00785 
00786             /* calculate cell bounds */
00787             {
00788                 int x;
00789                 #pragma omp parallel for schedule(static)
00790                 for (x=0; x<grid->dim[0]; x++) {
00791                     int y;
00792                     for (y=0; y<grid->dim[1]; y++) {
00793                         int z;
00794                         for (z=0; z<grid->dim[2]; z++) {
00795                             int j, b_index = x + y * grid->dim[0] + z * grid->dim[0]*grid->dim[1];
00796                             /* set bounds */
00797                             for (j=0; j<3; j++) {
00798                                 int s = (j==0) ? x : ((j==1) ? y : z);
00799                                 grid->bounds[b_index].min[j] = grid->grid_bounds.min[j] + dim[j]/grid->dim[j]*s;
00800                                 grid->bounds[b_index].max[j] = grid->grid_bounds.min[j] + dim[j]/grid->dim[j]*(s+1);
00801                             }
00802                             grid->bounds[b_index].valid = 1;
00803                         }
00804                     }
00805                 }
00806             }
00807         }
00808 
00809         if (temp_s_num) MEM_freeN(temp_s_num);
00810         if (temp_t_index) MEM_freeN(temp_t_index);
00811 
00812         /* free per thread s_num values */
00813         grid->s_num = MEM_reallocN(grid->s_num, sizeof(int) * grid_cells);
00814 
00815         if (error || !grid->s_num) {
00816             setError(surface->canvas, "Not enough free memory.");
00817             freeGrid(sData);
00818         }
00819     }
00820 
00821     if (grid_bounds) MEM_freeN(grid_bounds);
00822 }
00823 
00824 /***************************** Freeing data ******************************/
00825 
00826 /* Free brush data */
00827 void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
00828 {
00829     if(pmd->brush) {
00830         if(pmd->brush->dm)
00831             pmd->brush->dm->release(pmd->brush->dm);
00832         pmd->brush->dm = NULL;
00833 
00834         if(pmd->brush->paint_ramp)
00835              MEM_freeN(pmd->brush->paint_ramp);
00836         pmd->brush->paint_ramp = NULL;
00837         if(pmd->brush->vel_ramp)
00838              MEM_freeN(pmd->brush->vel_ramp);
00839         pmd->brush->vel_ramp = NULL;
00840 
00841         MEM_freeN(pmd->brush);
00842         pmd->brush = NULL;
00843     }
00844 }
00845 
00846 static void dynamicPaint_freeAdjData(PaintSurfaceData *data)
00847 {
00848     if (data->adj_data) {
00849         if (data->adj_data->n_index) MEM_freeN(data->adj_data->n_index);
00850         if (data->adj_data->n_num) MEM_freeN(data->adj_data->n_num);
00851         if (data->adj_data->n_target) MEM_freeN(data->adj_data->n_target);
00852         if (data->adj_data->flags) MEM_freeN(data->adj_data->flags);
00853         MEM_freeN(data->adj_data);
00854         data->adj_data = NULL;
00855     }
00856 }
00857 
00858 static void free_bakeData(PaintSurfaceData *data)
00859 {
00860     PaintBakeData *bData = data->bData;
00861     if (bData) {
00862         if (bData->bNormal) MEM_freeN(bData->bNormal);
00863         if (bData->s_pos) MEM_freeN(bData->s_pos);
00864         if (bData->s_num) MEM_freeN(bData->s_num);
00865         if (bData->realCoord) MEM_freeN(bData->realCoord);
00866         if (bData->bNeighs) MEM_freeN(bData->bNeighs);
00867         if (bData->grid) freeGrid(data);
00868         if (bData->prev_verts) MEM_freeN(bData->prev_verts);
00869         if (bData->velocity) MEM_freeN(bData->velocity);
00870         if (bData->prev_velocity) MEM_freeN(bData->prev_velocity);
00871 
00872         MEM_freeN(data->bData);
00873         data->bData = NULL;
00874     }
00875 }
00876 
00877 /* free surface data if it's not used anymore */
00878 void surface_freeUnusedData(DynamicPaintSurface *surface)
00879 {
00880     if (!surface->data) return;
00881 
00882     /* free bakedata if not active or surface is baked */
00883     if (!(surface->flags & MOD_DPAINT_ACTIVE) ||
00884         (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED))
00885         free_bakeData(surface->data);
00886 }
00887 
00888 void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface)
00889 {
00890     PaintSurfaceData *data = surface->data;
00891     if (!data) return;
00892     if (data->format_data) {
00893         /* format specific free */
00894         if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
00895             ImgSeqFormatData *format_data = (ImgSeqFormatData*)data->format_data;
00896             if (format_data->uv_p)
00897                 MEM_freeN(format_data->uv_p);
00898             if (format_data->barycentricWeights)
00899                 MEM_freeN(format_data->barycentricWeights);
00900         }
00901         MEM_freeN(data->format_data);
00902     }
00903     /* type data */
00904     if (data->type_data) MEM_freeN(data->type_data);
00905     dynamicPaint_freeAdjData(data);
00906     /* bake data */
00907     free_bakeData(data);
00908 
00909     MEM_freeN(surface->data);
00910     surface->data = NULL;
00911 }
00912 
00913 void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
00914 {
00915     /* point cache */
00916     BKE_ptcache_free_list(&(surface->ptcaches));
00917     surface->pointcache = NULL;
00918 
00919     if(surface->effector_weights)
00920         MEM_freeN(surface->effector_weights);
00921     surface->effector_weights = NULL;
00922 
00923     BLI_remlink(&(surface->canvas->surfaces), surface);
00924     dynamicPaint_freeSurfaceData(surface);
00925     MEM_freeN(surface);
00926 }
00927 
00928 /* Free canvas data */
00929 void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
00930 {
00931     if(pmd->canvas) {
00932         /* Free surface data */
00933         DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
00934         DynamicPaintSurface *next_surface = NULL;
00935 
00936         while (surface) {
00937             next_surface = surface->next;
00938             dynamicPaint_freeSurface(surface);
00939             surface = next_surface;
00940         }
00941 
00942         /* free dm copy */
00943         if (pmd->canvas->dm)
00944             pmd->canvas->dm->release(pmd->canvas->dm);
00945         pmd->canvas->dm = NULL;
00946 
00947         MEM_freeN(pmd->canvas);
00948         pmd->canvas = NULL;
00949     }
00950 }
00951 
00952 /* Free whole dp modifier */
00953 void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd)
00954 {
00955     if(pmd) {
00956         dynamicPaint_freeCanvas(pmd);
00957         dynamicPaint_freeBrush(pmd);
00958     }
00959 }
00960 
00961 
00962 /***************************** Initialize and reset ******************************/
00963 
00964 /*
00965 *   Creates a new surface and adds it to the list
00966 *   If scene is null, frame range of 1-250 is used
00967 *   A pointer to this surface is returned
00968 */
00969 struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene)
00970 {
00971     DynamicPaintSurface *surface= MEM_callocN(sizeof(DynamicPaintSurface), "DynamicPaintSurface");
00972     if (!surface) return NULL;
00973 
00974     surface->canvas = canvas;
00975     surface->format = MOD_DPAINT_SURFACE_F_VERTEX;
00976     surface->type = MOD_DPAINT_SURFACE_T_PAINT;
00977 
00978     /* cache */
00979     surface->pointcache = BKE_ptcache_add(&(surface->ptcaches));
00980     surface->pointcache->flag |= PTCACHE_DISK_CACHE;
00981     surface->pointcache->step = 1;
00982 
00983     /* Set initial values */
00984     surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG |
00985                      MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING;
00986     surface->effect = 0;
00987     surface->effect_ui = 1;
00988 
00989     surface->diss_speed = 250;
00990     surface->dry_speed = 500;
00991     surface->color_dry_threshold = 1.0f;
00992     surface->depth_clamp = 0.0f;
00993     surface->disp_factor = 1.0f;
00994     surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
00995     surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
00996 
00997     surface->influence_scale = 1.0f;
00998     surface->radius_scale = 1.0f;
00999 
01000     surface->init_color[0] = 1.0f;
01001     surface->init_color[1] = 1.0f;
01002     surface->init_color[2] = 1.0f;
01003     surface->init_color[3] = 1.0f;
01004 
01005     surface->image_resolution = 256;
01006     surface->substeps = 0;
01007 
01008     if (scene) {
01009         surface->start_frame = scene->r.sfra;
01010         surface->end_frame = scene->r.efra;
01011     }
01012     else {
01013         surface->start_frame = 1;
01014         surface->end_frame = 250;
01015     }
01016 
01017     surface->spread_speed = 1.0f;
01018     surface->color_spread_speed = 1.0f;
01019     surface->shrink_speed = 1.0f;
01020 
01021     surface->wave_damping = 0.04f;
01022     surface->wave_speed = 1.0f;
01023     surface->wave_timescale = 1.0f;
01024     surface->wave_spring = 0.20f;
01025 
01026     modifier_path_init(surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint");
01027 
01028     dynamicPaintSurface_setUniqueName(surface, "Surface");
01029 
01030     surface->effector_weights = BKE_add_effector_weights(NULL);
01031 
01032     dynamicPaintSurface_updateType(surface);
01033 
01034     BLI_addtail(&canvas->surfaces, surface);
01035 
01036     return surface;
01037 }
01038 
01039 /*
01040 *   Initialize modifier data
01041 */
01042 int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene)
01043 {
01044     if(pmd) {
01045         if(type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
01046             DynamicPaintCanvasSettings *canvas;
01047             if(pmd->canvas)
01048                 dynamicPaint_freeCanvas(pmd);
01049 
01050             canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas");
01051             if (!canvas)
01052                 return 0;
01053             canvas->pmd = pmd;
01054             canvas->dm = NULL;
01055 
01056             /* Create one surface */
01057             if (!dynamicPaint_createNewSurface(canvas, scene))
01058                 return 0;
01059 
01060         }
01061         else if(type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
01062             DynamicPaintBrushSettings *brush;
01063             if(pmd->brush)
01064                 dynamicPaint_freeBrush(pmd);
01065 
01066             brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint");
01067             if (!brush)
01068                 return 0;
01069             brush->pmd = pmd;
01070 
01071             brush->psys = NULL;
01072 
01073             brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA;
01074             brush->collision = MOD_DPAINT_COL_VOLUME;
01075             
01076             brush->mat = NULL;
01077             brush->r = 0.15f;
01078             brush->g = 0.4f;
01079             brush->b = 0.8f;
01080             brush->alpha = 1.0f;
01081             brush->wetness = 1.0f;
01082 
01083             brush->paint_distance = 1.0f;
01084             brush->proximity_falloff = MOD_DPAINT_PRFALL_SMOOTH;
01085 
01086             brush->particle_radius = 0.2f;
01087             brush->particle_smooth = 0.05f;
01088 
01089             brush->wave_type = MOD_DPAINT_WAVEB_CHANGE;
01090             brush->wave_factor = 1.0f;
01091             brush->wave_clamp = 0.0f;
01092             brush->smudge_strength = 0.3f;
01093             brush->max_velocity = 1.0f;
01094 
01095             brush->dm = NULL;
01096 
01097             /* Paint proximity falloff colorramp. */
01098             {
01099                 CBData *ramp;
01100 
01101                 brush->paint_ramp = add_colorband(0);
01102                 if (!brush->paint_ramp)
01103                     return 0;
01104                 ramp = brush->paint_ramp->data;
01105                 /* Add default smooth-falloff ramp. */
01106                 ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
01107                 ramp[0].pos = 0.0f;
01108                 ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].pos = 1.0f;
01109                 ramp[1].a = 0.0f;
01110                 pmd->brush->paint_ramp->tot = 2;
01111             }
01112 
01113             /* Brush velocity ramp. */
01114             {
01115                 CBData *ramp;
01116 
01117                 brush->vel_ramp = add_colorband(0);
01118                 if (!brush->vel_ramp)
01119                     return 0;
01120                 ramp = brush->vel_ramp->data;
01121                 ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
01122                 ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
01123                 brush->paint_ramp->tot = 2;
01124             }
01125         }
01126     }
01127     else
01128         return 0;
01129 
01130     return 1;
01131 }
01132 
01133 void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd)
01134 {
01135     /* Init modifier    */
01136     tpmd->type = pmd->type;
01137     if (pmd->canvas)
01138         dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_CANVAS, NULL);
01139     if (pmd->brush)
01140         dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_BRUSH, NULL);
01141 
01142     /* Copy data    */
01143     if (tpmd->canvas) {
01144         tpmd->canvas->pmd = tpmd;
01145 
01146     } else if (tpmd->brush) {
01147         DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
01148         t_brush->pmd = tpmd;
01149 
01150         t_brush->flags = brush->flags;
01151         t_brush->collision = brush->collision;
01152 
01153         t_brush->mat = brush->mat;
01154         t_brush->r = brush->r;
01155         t_brush->g = brush->g;
01156         t_brush->b = brush->b;
01157         t_brush->alpha = brush->alpha;
01158         t_brush->wetness = brush->wetness;
01159 
01160         t_brush->particle_radius = brush->particle_radius;
01161         t_brush->particle_smooth = brush->particle_smooth;
01162         t_brush->paint_distance = brush->paint_distance;
01163         t_brush->psys = brush->psys;
01164 
01165         if (brush->paint_ramp)
01166             memcpy(t_brush->paint_ramp, brush->paint_ramp, sizeof(ColorBand));
01167         if (brush->vel_ramp)
01168             memcpy(t_brush->vel_ramp, brush->vel_ramp, sizeof(ColorBand));
01169 
01170         t_brush->proximity_falloff = brush->proximity_falloff;
01171         t_brush->wave_type = brush->wave_type;
01172         t_brush->ray_dir = brush->ray_dir;
01173 
01174         t_brush->wave_factor = brush->wave_factor;
01175         t_brush->wave_clamp = brush->wave_clamp;
01176         t_brush->max_velocity = brush->max_velocity;
01177         t_brush->smudge_strength = brush->smudge_strength;
01178     }
01179 }
01180 
01181 /* allocates surface data depending on surface type */
01182 static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface)
01183 {
01184     PaintSurfaceData *sData = surface->data;
01185 
01186     switch (surface->type) {
01187         case MOD_DPAINT_SURFACE_T_PAINT:
01188             sData->type_data = MEM_callocN(sizeof(PaintPoint)*sData->total_points, "DynamicPaintSurface Data");
01189             break;
01190         case MOD_DPAINT_SURFACE_T_DISPLACE:
01191             sData->type_data = MEM_callocN(sizeof(float)*sData->total_points, "DynamicPaintSurface DepthData");
01192             break;
01193         case MOD_DPAINT_SURFACE_T_WEIGHT:
01194             sData->type_data = MEM_callocN(sizeof(float)*sData->total_points, "DynamicPaintSurface WeightData");
01195             break;
01196         case MOD_DPAINT_SURFACE_T_WAVE:
01197             sData->type_data = MEM_callocN(sizeof(PaintWavePoint)*sData->total_points, "DynamicPaintSurface WaveData");
01198             break;
01199     }
01200 
01201     if (sData->type_data == NULL) setError(surface->canvas, "Not enough free memory!");
01202 }
01203 
01204 static int surface_usesAdjDistance(DynamicPaintSurface *surface)
01205 {
01206     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && surface->effect) return 1;
01207     if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) return 1;
01208     return 0;
01209 }
01210 
01211 static int surface_usesAdjData(DynamicPaintSurface *surface)
01212 {
01213     if (surface_usesAdjDistance(surface)) return 1;
01214     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
01215         surface->flags & MOD_DPAINT_ANTIALIAS) return 1;
01216 
01217     return 0;
01218 }
01219 
01220 /* initialize surface adjacency data */
01221 static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init)
01222 {
01223     PaintSurfaceData *sData = surface->data;
01224     PaintAdjData *ed;
01225     int *temp_data;
01226     int neigh_points = 0;
01227 
01228     if (!surface_usesAdjData(surface) && !force_init) return;
01229 
01230     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
01231         /* For vertex format, neighbours are connected by edges */
01232         neigh_points = 2*surface->canvas->dm->getNumEdges(surface->canvas->dm);
01233     }
01234     else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
01235         neigh_points = sData->total_points*8;
01236 
01237     if (!neigh_points) return;
01238 
01239     /* allocate memory */
01240     ed = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data");
01241     if (!ed) return;
01242     ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index");
01243     ed->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts");
01244     temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data");
01245     ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets");
01246     ed->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags");
01247     ed->total_targets = neigh_points;
01248 
01249     /* in case of allocation error, free memory */
01250     if (!ed->n_index || !ed->n_num || !ed->n_target || !temp_data) {
01251         dynamicPaint_freeAdjData(sData);
01252         if (temp_data) MEM_freeN(temp_data);
01253         setError(surface->canvas, "Not enough free memory.");
01254         return;
01255     }
01256 
01257     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
01258         int i;
01259         int n_pos;
01260 
01261         /* For vertex format, count every vertex that is connected by an edge */
01262         int numOfEdges = surface->canvas->dm->getNumEdges(surface->canvas->dm);
01263         int numOfFaces = surface->canvas->dm->getNumFaces(surface->canvas->dm);
01264         struct MEdge *edge =  surface->canvas->dm->getEdgeArray(surface->canvas->dm);
01265         struct MFace *face =  surface->canvas->dm->getFaceArray(surface->canvas->dm);
01266 
01267         /* count number of edges per vertex */
01268         for (i=0; i<numOfEdges; i++) {
01269             ed->n_num[edge[i].v1]++;
01270             ed->n_num[edge[i].v2]++;
01271 
01272             temp_data[edge[i].v1]++;
01273             temp_data[edge[i].v2]++;
01274         }
01275 
01276         /* to locate points on "mesh edge" */
01277         for (i=0; i<numOfFaces; i++) {
01278             temp_data[face[i].v1]++;
01279             temp_data[face[i].v2]++;
01280             temp_data[face[i].v3]++;
01281             if (face[i].v4)
01282                 temp_data[face[i].v4]++;
01283         }
01284 
01285         /* now check if total number of edges+faces for
01286         *  each vertex is even, if not -> vertex is on mesh edge */
01287         for (i=0; i<sData->total_points; i++) {
01288             if ((temp_data[i]%2) ||
01289                 temp_data[i] < 4)
01290                 ed->flags[i] |= ADJ_ON_MESH_EDGE;
01291                 
01292             /* reset temp data */ 
01293             temp_data[i] = 0;
01294         }
01295 
01296         /* order n_index array */
01297         n_pos = 0;
01298         for (i=0; i<sData->total_points; i++) {
01299             ed->n_index[i] = n_pos;
01300             n_pos += ed->n_num[i];
01301         }
01302 
01303         /* and now add neighbour data using that info */
01304         for (i=0; i<numOfEdges; i++) {
01305             /* first vertex */
01306             int index = edge[i].v1;
01307             n_pos = ed->n_index[index]+temp_data[index];
01308             ed->n_target[n_pos] = edge[i].v2;
01309             temp_data[index]++;
01310 
01311             /* second vertex */
01312             index = edge[i].v2;
01313             n_pos = ed->n_index[index]+temp_data[index];
01314             ed->n_target[n_pos] = edge[i].v1;
01315             temp_data[index]++;
01316         }
01317     }
01318     else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
01319         /* for image sequences, only allocate memory.
01320         *  bake initialization takes care of rest */
01321     }
01322 
01323     MEM_freeN(temp_data);
01324 }
01325 
01326 void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
01327 {
01328     PaintSurfaceData *sData = surface->data;
01329     PaintPoint* pPoint = (PaintPoint*)sData->type_data;
01330     DerivedMesh *dm = surface->canvas->dm;
01331     int i;
01332 
01333     if (surface->type != MOD_DPAINT_SURFACE_T_PAINT)
01334         return;
01335 
01336     if (surface->init_color_type == MOD_DPAINT_INITIAL_NONE)
01337         return;
01338     /* Single color */
01339     else if (surface->init_color_type == MOD_DPAINT_INITIAL_COLOR) {
01340         /* apply color to every surface point */
01341         #pragma omp parallel for schedule(static)
01342         for (i=0; i<sData->total_points; i++) {
01343             copy_v3_v3(pPoint[i].color, surface->init_color);
01344             pPoint[i].alpha = surface->init_color[3];
01345         }
01346     }
01347     /* UV mapped texture */
01348     else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
01349         Tex *tex = surface->init_texture;
01350         MTFace *tface;
01351         MFace *mface = dm->getFaceArray(dm);
01352         int numOfFaces = dm->getNumFaces(dm);
01353         char uvname[MAX_CUSTOMDATA_LAYER_NAME];
01354 
01355         if (!tex) return;
01356 
01357         /* get uv map */
01358         CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname);
01359         tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
01360         if (!tface) return;
01361 
01362         /* for vertex surface loop through tfaces and find uv color
01363         *  that provides highest alpha */
01364         if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
01365             #pragma omp parallel for schedule(static)
01366             for (i=0; i<numOfFaces; i++) {
01367                 int numOfVert = (mface[i].v4) ? 4 : 3;
01368                 float uv[3] = {0.0f};
01369                 int j;
01370                 for (j=0; j<numOfVert; j++) {
01371                     TexResult texres = {0};
01372                     unsigned int *vert = (&mface[i].v1)+j;
01373 
01374                     /* remap to -1.0 to 1.0 */
01375                     uv[0] = tface[i].uv[j][0]*2.0f - 1.0f;
01376                     uv[1] = tface[i].uv[j][1]*2.0f - 1.0f;
01377 
01378                     multitex_ext_safe(tex, uv, &texres);
01379 
01380                     if (texres.tin > pPoint[*vert].alpha) {
01381                         copy_v3_v3(pPoint[*vert].color, &texres.tr);
01382                         pPoint[*vert].alpha = texres.tin;
01383                     }
01384                 }
01385             }
01386         }
01387         else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
01388             ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
01389             int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
01390 
01391             #pragma omp parallel for schedule(static)
01392             for (i=0; i<sData->total_points; i++) {
01393                 float uv[9] = {0.0f};
01394                 float uv_final[3] = {0.0f};
01395                 int j;
01396                 TexResult texres = {0};
01397 
01398                 /* collect all uvs */
01399                 for (j=0; j<3; j++) {
01400                     int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
01401                     copy_v2_v2(&uv[j*3], tface[f_data->uv_p[i].face_index].uv[v]);
01402                 }
01403 
01404                 /* interpolate final uv pos */
01405                 interp_v3_v3v3v3(   uv_final, &uv[0], &uv[3], &uv[6],
01406                     f_data->barycentricWeights[i*samples].v);
01407                 /* remap to -1.0 to 1.0 */
01408                 uv_final[0] = uv_final[0]*2.0f - 1.0f;
01409                 uv_final[1] = uv_final[1]*2.0f - 1.0f;
01410                     
01411                 multitex_ext_safe(tex, uv_final, &texres);
01412 
01413                 /* apply color */
01414                 copy_v3_v3(pPoint[i].color, &texres.tr);
01415                 pPoint[i].alpha = texres.tin;
01416             }
01417         }
01418     }
01419     /* vertex color layer */
01420     else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) {
01421         MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername);
01422         if (!col) return;
01423 
01424         /* for vertex surface, just copy colors from mcol */
01425         if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
01426             MFace *mface = dm->getFaceArray(dm);
01427             int numOfFaces = dm->getNumFaces(dm);
01428 
01429             #pragma omp parallel for schedule(static)
01430             for (i=0; i<numOfFaces; i++) {
01431                 int numOfVert = (mface[i].v4) ? 4 : 3;
01432                 int j;
01433                 for (j=0; j<numOfVert; j++) {
01434                     unsigned int *vert = ((&mface[i].v1)+j);
01435 
01436                     pPoint[*vert].color[0] = 1.0f/255.f*(float)col[i*4+j].b;
01437                     pPoint[*vert].color[1] = 1.0f/255.f*(float)col[i*4+j].g;
01438                     pPoint[*vert].color[2] = 1.0f/255.f*(float)col[i*4+j].r;
01439                     pPoint[*vert].alpha = 1.0f/255.f*(float)col[i*4+j].a;
01440                 }
01441             }
01442         }
01443         else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
01444             ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
01445             int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
01446 
01447             #pragma omp parallel for schedule(static)
01448             for (i=0; i<sData->total_points; i++) {
01449                 int face_ind = f_data->uv_p[i].face_index;
01450                 float colors[3][4] = {{0.0f,0.0f,0.0f,0.0f}};
01451                 float final_color[4];
01452                 int j;
01453                 /* collect color values */
01454                 for (j=0; j<3; j++) {
01455                     int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
01456                     colors[j][0] = 1.0f/255.f*(float)col[face_ind*4+v].b;
01457                     colors[j][1] = 1.0f/255.f*(float)col[face_ind*4+v].g;
01458                     colors[j][2] = 1.0f/255.f*(float)col[face_ind*4+v].r;
01459                     colors[j][3] = 1.0f/255.f*(float)col[face_ind*4+v].a;
01460                 }
01461                 
01462                 /* interpolate final color */
01463                 interp_v4_v4v4v4(   final_color, colors[0], colors[1], colors[2],
01464                         f_data->barycentricWeights[i*samples].v);
01465 
01466                 copy_v3_v3(pPoint[i].color, final_color);
01467                 pPoint[i].alpha = final_color[3];
01468             }
01469         }
01470     }
01471 }
01472 
01473 /* clears surface data back to zero */
01474 void dynamicPaint_clearSurface(DynamicPaintSurface *surface)
01475 {
01476     PaintSurfaceData *sData = surface->data;
01477     if (sData && sData->type_data) {
01478         unsigned int data_size;
01479 
01480         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
01481             data_size = sizeof(PaintPoint);
01482         else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
01483             data_size = sizeof(PaintWavePoint);
01484         else
01485             data_size = sizeof(float);
01486 
01487         memset(sData->type_data, 0, data_size * sData->total_points);
01488 
01489         /* set initial color */
01490         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
01491             dynamicPaint_setInitialColor(surface);
01492 
01493         if (sData->bData)
01494             sData->bData->clear = 1;
01495     }
01496 }
01497 
01498 /* completely (re)initializes surface (only for point cache types)*/
01499 int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
01500 {
01501     int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
01502     /* dont touch image sequence types. they get handled only on bake */
01503     if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
01504 
01505     if (surface->data) dynamicPaint_freeSurfaceData(surface);
01506     if (numOfPoints < 1) return 0;
01507 
01508     /* allocate memory */
01509     surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
01510     if (!surface->data) return 0;
01511 
01512     /* allocate data depending on surface type and format */
01513     surface->data->total_points = numOfPoints;
01514     dynamicPaint_allocateSurfaceType(surface);
01515     dynamicPaint_initAdjacencyData(surface, 0);
01516 
01517     /* set initial color */
01518     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
01519         dynamicPaint_setInitialColor(surface);
01520 
01521     return 1;
01522 }
01523 
01524 /* make sure allocated surface size matches current requirements */
01525 static int dynamicPaint_checkSurfaceData(DynamicPaintSurface *surface)
01526 {
01527     if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) {
01528         return dynamicPaint_resetSurface(surface);
01529     }
01530     return 1;
01531 }
01532 
01533 
01534 /***************************** Modifier processing ******************************/
01535 
01536 
01537 /* apply displacing vertex surface to the derived mesh */
01538 static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result)
01539 {
01540     PaintSurfaceData *sData = surface->data;
01541 
01542     if (!sData || surface->format != MOD_DPAINT_SURFACE_F_VERTEX) return;
01543 
01544     /* displace paint */
01545     if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
01546         MVert *mvert = result->getVertArray(result);
01547         int i;
01548         float* value = (float*)sData->type_data;
01549 
01550         #pragma omp parallel for schedule(static)
01551         for (i=0; i<sData->total_points; i++) {
01552             float normal[3], val=value[i]*surface->disp_factor;
01553             normal_short_to_float_v3(normal, mvert[i].no);
01554             normalize_v3(normal);
01555 
01556             mvert[i].co[0] -= normal[0]*val;
01557             mvert[i].co[1] -= normal[1]*val;
01558             mvert[i].co[2] -= normal[2]*val;
01559         }
01560     }
01561 }
01562 
01563 /*
01564 *   Apply canvas data to the object derived mesh
01565 */
01566 static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd,
01567                                                        Object *ob,
01568                                                        DerivedMesh *dm)
01569 {   
01570     DerivedMesh *result = CDDM_copy(dm);
01571 
01572     if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
01573 
01574         DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
01575         int update_normals = 0;
01576         pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY;
01577 
01578         /* loop through surfaces */
01579         for (; surface; surface=surface->next) {
01580             PaintSurfaceData *sData = surface->data;
01581 
01582             if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) {
01583                 if (!(surface->flags & (MOD_DPAINT_ACTIVE))) continue;
01584 
01585                 /* process vertex surface previews */
01586                 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
01587 
01588                     /* vertex color paint */
01589                     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
01590 
01591                         MFace *mface = result->getFaceArray(result);
01592                         int numOfFaces = result->getNumFaces(result);
01593                         int i;
01594                         PaintPoint* pPoint = (PaintPoint*)sData->type_data;
01595                         MCol *col;
01596 
01597                         /* paint is stored on dry and wet layers, so mix final color first */
01598                         float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color");
01599 
01600                         #pragma omp parallel for schedule(static)
01601                         for (i=0; i<sData->total_points; i++) {
01602                             /* blend dry and wet layer */
01603                             blendColors(pPoint[i].color, pPoint[i].alpha, pPoint[i].e_color, pPoint[i].e_alpha, &fcolor[i*4]);
01604                         }
01605 
01606                         /* viewport preview */
01607                         if (surface->flags & MOD_DPAINT_PREVIEW) {
01608                             /* Save preview results to weight layer, to be
01609                             *   able to share same drawing methods */
01610                             col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
01611                             if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
01612 
01613                             if (col) {
01614                                 #pragma omp parallel for schedule(static)
01615                                 for (i=0; i<numOfFaces; i++) {
01616                                     int j=0;
01617                                     Material *material = give_current_material(ob, mface[i].mat_nr+1);
01618 
01619                                     for (; j<((mface[i].v4)?4:3); j++) {
01620                                         int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
01621 
01622                                         if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) {
01623                                             float c[3];
01624                                             index *= 4;
01625 
01626                                             /* Apply material color as base vertex color for preview */
01627                                             col[i*4+j].a = 255;
01628                                             if (material) {
01629                                                 c[0] = material->r;
01630                                                 c[1] = material->g;
01631                                                 c[2] = material->b;
01632                                             }
01633                                             else { /* default grey */
01634                                                 c[0] = 0.65f;
01635                                                 c[1] = 0.65f;
01636                                                 c[2] = 0.65f;
01637                                             }
01638                                             /* mix surface color */
01639                                             interp_v3_v3v3(c, c, &fcolor[index], fcolor[index+3]);
01640 
01641                                             col[i*4+j].r = FTOCHAR(c[2]);
01642                                             col[i*4+j].g = FTOCHAR(c[1]);
01643                                             col[i*4+j].b = FTOCHAR(c[0]);
01644                                         }
01645                                         else {
01646                                             col[i*4+j].a = 255;
01647                                             col[i*4+j].r =
01648                                             col[i*4+j].g =
01649                                             col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
01650                                         }
01651                                     }
01652                                 }
01653                                 pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
01654                             }
01655                         }
01656 
01657 
01658                         /* save layer data to output layer */
01659 
01660                         /* paint layer */
01661                         col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name);
01662                         /* if output layer is lost from a constructive modifier, re-add it */
01663                         if (!col && dynamicPaint_outputLayerExists(surface, ob, 0))
01664                             col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name);
01665                         /* apply color */
01666                         if (col) {
01667                             #pragma omp parallel for schedule(static)
01668                             for (i=0; i<numOfFaces; i++) {
01669                                 int j=0;
01670                                 for (; j<((mface[i].v4)?4:3); j++) {
01671                                     int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
01672                                     index *= 4;
01673 
01674                                     col[i*4+j].a = FTOCHAR(fcolor[index+3]);
01675                                     col[i*4+j].r = FTOCHAR(fcolor[index+2]);
01676                                     col[i*4+j].g = FTOCHAR(fcolor[index+1]);
01677                                     col[i*4+j].b = FTOCHAR(fcolor[index]);
01678                                 }
01679                             }
01680                         }
01681                         
01682                         MEM_freeN(fcolor);
01683 
01684                         /* wet layer */
01685                         col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name2);
01686                         /* if output layer is lost from a constructive modifier, re-add it */
01687                         if (!col && dynamicPaint_outputLayerExists(surface, ob, 1))
01688                             col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name2);
01689                         /* apply color */
01690                         if (col) {
01691                             #pragma omp parallel for schedule(static)
01692                             for (i=0; i<numOfFaces; i++) {
01693                                 int j=0;
01694 
01695                                 for (; j<((mface[i].v4)?4:3); j++) {
01696                                     int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
01697                                     col[i*4+j].a = 255;
01698                                     col[i*4+j].r =
01699                                     col[i*4+j].g =
01700                                     col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
01701                                 }
01702                             }
01703                         }
01704                     }
01705                     /* vertex group paint */
01706                     else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
01707                         int defgrp_index = defgroup_name_index(ob, surface->output_name);
01708                         MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
01709                         float *weight = (float*)sData->type_data;
01710                         /* viewport preview */
01711                         if (surface->flags & MOD_DPAINT_PREVIEW) {
01712                             /* Save preview results to weight layer, to be
01713                             *   able to share same drawing methods */
01714                             MFace *mface = result->getFaceArray(result);
01715                             int numOfFaces = result->getNumFaces(result);
01716                             int i;
01717                             MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
01718                             if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
01719 
01720                             if (col) {
01721                                 #pragma omp parallel for schedule(static)
01722                                 for (i=0; i<numOfFaces; i++) {
01723                                     float temp_color[3];
01724                                     int j=0;
01725                                     for (; j<((mface[i].v4)?4:3); j++) {
01726                                         int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
01727 
01728                                         weight_to_rgb(temp_color, weight[index]);
01729                                         col[i*4+j].r = FTOCHAR(temp_color[2]);
01730                                         col[i*4+j].g = FTOCHAR(temp_color[1]);
01731                                         col[i*4+j].b = FTOCHAR(temp_color[0]);
01732                                         col[i*4+j].a = 255;
01733                                     }
01734                                 }
01735                                 pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
01736                             }
01737                         }
01738 
01739                         /* apply weights into a vertex group, if doesnt exists add a new layer */
01740                         if (defgrp_index >= 0 && !dvert && (surface->output_name[0] != '\0'))
01741                             dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
01742                                                                 NULL, sData->total_points, surface->output_name);
01743                         if (defgrp_index >= 0 && dvert) {
01744                             int i;
01745                             for(i=0; i<sData->total_points; i++) {
01746                                 MDeformVert *dv= &dvert[i];
01747                                 MDeformWeight *def_weight = defvert_find_index(dv, defgrp_index);
01748 
01749                                 /* skip if weight value is 0 and no existing weight is found */
01750                                 if ((def_weight != NULL) || (weight[i] != 0.0f)) {
01751 
01752                                     /* if not found, add a weight for it */
01753                                     if (def_weight == NULL) {
01754                                         def_weight= defvert_verify_index(dv, defgrp_index);
01755                                     }
01756 
01757                                     /* set weight value */
01758                                     def_weight->weight = weight[i];
01759                                 }
01760                             }
01761                         }
01762                     }
01763                     /* wave simulation */
01764                     else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
01765                         MVert *mvert = result->getVertArray(result);
01766                         int i;
01767                         PaintWavePoint* wPoint = (PaintWavePoint*)sData->type_data;
01768 
01769                         #pragma omp parallel for schedule(static)
01770                         for (i=0; i<sData->total_points; i++) {
01771                             float normal[3];
01772                             normal_short_to_float_v3(normal, mvert[i].no);
01773                             madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height);
01774                         }
01775                         update_normals = 1;
01776                     }
01777 
01778                     /* displace */
01779                     if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
01780                         dynamicPaint_applySurfaceDisplace(surface, result);
01781                         update_normals = 1;
01782                     }
01783                 }
01784             }
01785         }
01786 
01787         if (update_normals)
01788             CDDM_calc_normals(result);
01789     }
01790     /* make a copy of dm to use as brush data */
01791     if (pmd->brush) {
01792         if (pmd->brush->dm) pmd->brush->dm->release(pmd->brush->dm);
01793         pmd->brush->dm = CDDM_copy(result);
01794     }
01795 
01796     return result;
01797 }
01798 
01799 /* update cache frame range */
01800 void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface)
01801 {
01802     if (surface->pointcache) {
01803         surface->pointcache->startframe = surface->start_frame;
01804         surface->pointcache->endframe = surface->end_frame;
01805     }
01806 }
01807 
01808 void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm)
01809 {
01810     if (canvas->dm) canvas->dm->release(canvas->dm);
01811     canvas->dm = CDDM_copy(dm);
01812 }
01813 
01814 /*
01815 *   Updates derived mesh copy and processes dynamic paint step / caches.
01816 */
01817 static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
01818 {
01819     if(pmd->canvas) {
01820         DynamicPaintCanvasSettings *canvas = pmd->canvas;
01821         DynamicPaintSurface *surface = canvas->surfaces.first;
01822 
01823         /* update derived mesh copy */
01824         canvas_copyDerivedMesh(canvas, dm);
01825 
01826         /* in case image sequence baking, stop here */
01827         if (canvas->flags & MOD_DPAINT_BAKING) return;
01828 
01829         /* loop through surfaces */
01830         for (; surface; surface=surface->next) {
01831             int current_frame = (int)scene->r.cfra;
01832 
01833             /* free bake data if not required anymore */
01834             surface_freeUnusedData(surface);
01835 
01836             /* image sequences are handled by bake operator */
01837             if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) continue;
01838             if (!(surface->flags & MOD_DPAINT_ACTIVE)) continue;
01839 
01840             /* make sure surface is valid */
01841             if (!dynamicPaint_checkSurfaceData(surface)) continue;
01842 
01843             /* limit frame range */
01844             CLAMP(current_frame, surface->start_frame, surface->end_frame);
01845 
01846             if (current_frame != surface->current_frame || (int)scene->r.cfra == surface->start_frame) {
01847                 PointCache *cache = surface->pointcache;
01848                 PTCacheID pid;
01849                 surface->current_frame = current_frame;
01850 
01851                 /* read point cache */
01852                 BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
01853                 pid.cache->startframe = surface->start_frame;
01854                 pid.cache->endframe = surface->end_frame;
01855                 BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL);
01856 
01857                 /* reset non-baked cache at first frame */
01858                 if((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED))
01859                 {
01860                     cache->flag |= PTCACHE_REDO_NEEDED;
01861                     BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
01862                     cache->flag &= ~PTCACHE_REDO_NEEDED;
01863                 }
01864 
01865                 /* try to read from cache */
01866                 if(BKE_ptcache_read(&pid, (float)scene->r.cfra)) {
01867                     BKE_ptcache_validate(cache, (int)scene->r.cfra);
01868                 }
01869                 /* if read failed and we're on surface range do recalculate */
01870                 else if ((int)scene->r.cfra == current_frame
01871                     && !(cache->flag & PTCACHE_BAKED)) {
01872                     /* calculate surface frame */
01873                     canvas->flags |= MOD_DPAINT_BAKING;
01874                     dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
01875                     canvas->flags &= ~MOD_DPAINT_BAKING;
01876 
01877                     /* restore canvas derivedmesh if required */
01878                     if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE &&
01879                         surface->flags & MOD_DPAINT_DISP_INCREMENTAL && surface->next)
01880                         canvas_copyDerivedMesh(canvas, dm);
01881 
01882                     BKE_ptcache_validate(cache, surface->current_frame);
01883                     BKE_ptcache_write(&pid, surface->current_frame);
01884                 }
01885             }
01886         }
01887     }
01888 }
01889 
01890 /* Modifier call. Processes dynamic paint modifier step. */
01891 struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
01892 {   
01893     /* Update canvas data for a new frame */
01894     dynamicPaint_frameUpdate(pmd, scene, ob, dm);
01895 
01896     /* Return output mesh */
01897     return dynamicPaint_Modifier_apply(pmd, ob, dm);
01898 }
01899 
01900 
01901 /***************************** Image Sequence / UV Image Surface Calls ******************************/
01902 
01903 /*
01904 *   Tries to find the neighbouring pixel in given (uv space) direction.
01905 *   Result is used by effect system to move paint on the surface.
01906 *
01907 *   px,py : origin pixel x and y
01908 *   n_index : lookup direction index (use neighX,neighY to get final index)
01909 */
01910 static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh *dm,
01911                                            const char *uvname, int w, int h, int px, int py, int n_index)
01912 {
01913     /* Note: Current method only uses polygon edges to detect neighbouring pixels.
01914     *  -> It doesn't always lead to the optimum pixel but is accurate enough
01915     *  and faster/simplier than including possible face tip point links)
01916     */
01917 
01918     int x,y;
01919     PaintUVPoint *tPoint = NULL;
01920     PaintUVPoint *cPoint = NULL;
01921 
01922     /* shift position by given n_index */
01923     x = px + neighX[n_index];
01924     y = py + neighY[n_index];
01925 
01926     if (x<0 || x>=w) return -1;
01927     if (y<0 || y>=h) return -1;
01928 
01929     tPoint = &tempPoints[x+w*y];        /* UV neighbour */
01930     cPoint = &tempPoints[px+w*py];      /* Origin point */
01931 
01932     /*
01933     *   Check if shifted point is on same face -> it's a correct neighbour
01934     *   (and if it isn't marked as an "edge pixel")
01935     */
01936     if ((tPoint->face_index == cPoint->face_index) && (tPoint->neighbour_pixel == -1))
01937         return (x+w*y);
01938 
01939     /*
01940     *   Even if shifted point is on another face
01941     *   -> use this point.
01942     *   
01943     *   !! Replace with "is uv faces linked" check !!
01944     *   This should work fine as long as uv island
01945     *   margin is > 1 pixel.
01946     */
01947     if ((tPoint->face_index != -1) && (tPoint->neighbour_pixel == -1)) {
01948         return (x+w*y);
01949     }
01950 
01951     /*
01952     *   If we get here, the actual neighbouring pixel
01953     *   is located on a non-linked uv face, and we have to find
01954     *   it's "real" position.
01955     *
01956     *   Simple neighbouring face finding algorithm:
01957     *   - find closest uv edge to shifted pixel and get
01958     *     the another face that shares that edge
01959     *   - find corresponding position of that new face edge
01960     *     in uv space
01961     *
01962     *   TODO: Implement something more accurate / optimized?
01963     */
01964     {
01965         int numOfFaces = dm->getNumFaces(dm);
01966         MFace *mface = dm->getFaceArray(dm);
01967         MTFace *tface =  CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
01968 
01969         /* Get closest edge to that subpixel on UV map  */
01970         {
01971             float pixel[2], dist, t_dist;
01972             int i, uindex[3], edge1_index, edge2_index,
01973                 e1_index, e2_index, target_face;
01974             float closest_point[2], lambda, dir_vec[2];
01975             int target_uv1, target_uv2, final_pixel[2], final_index;
01976 
01977             float *s_uv1, *s_uv2, *t_uv1, *t_uv2;
01978 
01979             pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w;
01980             pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h;
01981 
01982             /* Get uv indexes for current face part */
01983             if (cPoint->quad) {
01984                 uindex[0] = 0; uindex[1] = 2; uindex[2] = 3;
01985             }
01986             else {
01987                 uindex[0] = 0; uindex[1] = 1; uindex[2] = 2;
01988             }
01989 
01990             /*
01991             *   Find closest edge to that pixel
01992             */
01993             /* Dist to first edge   */
01994             e1_index = cPoint->v1; e2_index = cPoint->v2; edge1_index = uindex[0]; edge2_index = uindex[1];
01995             dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
01996 
01997             /* Dist to second edge  */
01998             t_dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[1]], tface[cPoint->face_index].uv[uindex[2]]);
01999             if (t_dist < dist) {e1_index = cPoint->v2; e2_index = cPoint->v3; edge1_index = uindex[1]; edge2_index = uindex[2]; dist = t_dist;}
02000 
02001             /* Dist to third edge   */
02002             t_dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[2]], tface[cPoint->face_index].uv[uindex[0]]);
02003             if (t_dist < dist) {e1_index = cPoint->v3; e2_index = cPoint->v1;  edge1_index = uindex[2]; edge2_index = uindex[0]; dist = t_dist;}
02004 
02005 
02006             /*
02007             *   Now find another face that is linked to that edge
02008             */
02009             target_face = -1;
02010 
02011             for (i=0; i<numOfFaces; i++) {
02012                 /*
02013                 *   Check if both edge vertices share this face
02014                 */
02015                 int v4 = (mface[i].v4) ? mface[i].v4 : -1;
02016 
02017                 if ((e1_index == mface[i].v1 || e1_index == mface[i].v2 || e1_index == mface[i].v3 || e1_index == v4) &&
02018                     (e2_index == mface[i].v1 || e2_index == mface[i].v2 || e2_index == mface[i].v3 || e2_index == v4)) {
02019                     if (i == cPoint->face_index) continue;
02020 
02021                     target_face = i;
02022 
02023                     /*
02024                     *   Get edge UV index
02025                     */
02026                     if (e1_index == mface[i].v1) target_uv1 = 0;
02027                     else if (e1_index == mface[i].v2) target_uv1 = 1;
02028                     else if (e1_index == mface[i].v3) target_uv1 = 2;
02029                     else target_uv1 = 3;
02030 
02031                     if (e2_index == mface[i].v1) target_uv2 = 0;
02032                     else if (e2_index == mface[i].v2) target_uv2 = 1;
02033                     else if (e2_index == mface[i].v3) target_uv2 = 2;
02034                     else target_uv2 = 3;
02035 
02036                     break;
02037                 }
02038             }
02039 
02040             /* If none found return -1  */
02041             if (target_face == -1) return -1;
02042 
02043             /*
02044             *   If target face is connected in UV space as well, just use original index
02045             */
02046             s_uv1 = (float *)tface[cPoint->face_index].uv[edge1_index];
02047             s_uv2 = (float *)tface[cPoint->face_index].uv[edge2_index];
02048             t_uv1 = (float *)tface[target_face].uv[target_uv1];
02049             t_uv2 = (float *)tface[target_face].uv[target_uv2];
02050 
02051             //printf("connected UV : %f,%f & %f,%f - %f,%f & %f,%f\n", s_uv1[0], s_uv1[1], s_uv2[0], s_uv2[1], t_uv1[0], t_uv1[1], t_uv2[0], t_uv2[1]);
02052 
02053             if (((s_uv1[0] == t_uv1[0] && s_uv1[1] == t_uv1[1]) &&
02054                  (s_uv2[0] == t_uv2[0] && s_uv2[1] == t_uv2[1]) ) ||
02055                 ((s_uv2[0] == t_uv1[0] && s_uv2[1] == t_uv1[1]) &&
02056                  (s_uv1[0] == t_uv2[0] && s_uv1[1] == t_uv2[1]) )) return ((px+neighX[n_index]) + w*(py+neighY[n_index]));
02057 
02058             /*
02059             *   Find a point that is relatively at same edge position
02060             *   on this other face UV
02061             */
02062             lambda = closest_to_line_v2(closest_point, pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
02063             if (lambda < 0.0f) lambda = 0.0f;
02064             if (lambda > 1.0f) lambda = 1.0f;
02065 
02066             sub_v2_v2v2(dir_vec, tface[target_face].uv[target_uv2], tface[target_face].uv[target_uv1]);
02067 
02068             mul_v2_fl(dir_vec, lambda);
02069 
02070             copy_v2_v2(pixel, tface[target_face].uv[target_uv1]);
02071             add_v2_v2(pixel, dir_vec);
02072             pixel[0] = (pixel[0] * (float)w) - 0.5f;
02073             pixel[1] = (pixel[1] * (float)h) - 0.5f;
02074 
02075             final_pixel[0] = (int)floor(pixel[0]);
02076             final_pixel[1] = (int)floor(pixel[1]);
02077 
02078             /* If current pixel uv is outside of texture    */
02079             if (final_pixel[0] < 0 || final_pixel[0] >= w) return -1;
02080             if (final_pixel[1] < 0 || final_pixel[1] >= h) return -1;
02081 
02082             final_index = final_pixel[0] + w * final_pixel[1];
02083 
02084             /* If we ended up to our origin point ( mesh has smaller than pixel sized faces)    */
02085             if (final_index == (px+w*py)) return -1;
02086             /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces)   */
02087             if (tempPoints[final_index].face_index != target_face) return -1;
02088 
02089             /*
02090             *   If final point is an "edge pixel", use it's "real" neighbour instead
02091             */
02092             if (tempPoints[final_index].neighbour_pixel != -1) final_index = cPoint->neighbour_pixel;
02093 
02094             return final_index;
02095         }
02096     }
02097 }
02098 
02099 /*
02100 *   Create a surface for uv image sequence format
02101 */
02102 int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
02103 {
02104     /* Antialias jitter point relative coords   */
02105     float jitter5sample[10] =  {0.0f, 0.0f,
02106                             -0.2f, -0.4f,
02107                             0.2f, 0.4f,
02108                             0.4f, -0.2f,
02109                             -0.4f, 0.3f};
02110     int ty;
02111     int w,h;
02112     int numOfFaces;
02113     char uvname[MAX_CUSTOMDATA_LAYER_NAME];
02114     int active_points = 0;
02115     int error = 0;
02116 
02117     PaintSurfaceData *sData;
02118     DynamicPaintCanvasSettings *canvas = surface->canvas;
02119     DerivedMesh *dm = canvas->dm;
02120 
02121     PaintUVPoint *tempPoints = NULL;
02122     Vec3f *tempWeights = NULL;
02123     MFace *mface = NULL;
02124     MTFace *tface = NULL;
02125     Bounds2D *faceBB = NULL;
02126     int *final_index;
02127     int aa_samples;
02128 
02129     if (!dm) return setError(canvas, "Canvas mesh not updated.");
02130     if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) return setError(canvas, "Can't bake non-\"image sequence\" formats.");
02131 
02132     numOfFaces = dm->getNumFaces(dm);
02133     mface = dm->getFaceArray(dm);
02134 
02135     /* get uv map */
02136     CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname);
02137     tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
02138 
02139     /* Check for validity   */
02140     if (!tface) return setError(canvas, "No UV data on canvas.");
02141     if (surface->image_resolution < 16 || surface->image_resolution > 8192) return setError(canvas, "Invalid resolution.");
02142 
02143     w = h = surface->image_resolution;
02144 
02145     /*
02146     *   Start generating the surface
02147     */
02148     printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i faces.\n", w, h, numOfFaces);
02149 
02150     /* Init data struct */
02151     if (surface->data) dynamicPaint_freeSurfaceData(surface);
02152     sData = surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
02153     if (!surface->data) return setError(canvas, "Not enough free memory.");
02154 
02155     aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
02156     tempPoints = (struct PaintUVPoint *) MEM_callocN(w*h*sizeof(struct PaintUVPoint), "Temp PaintUVPoint");
02157     if (!tempPoints) error=1;
02158 
02159     final_index = (int *) MEM_callocN(w*h*sizeof(int), "Temp UV Final Indexes");
02160     if (!final_index) error=1;
02161 
02162     tempWeights = (struct Vec3f *) MEM_mallocN(w*h*aa_samples*sizeof(struct Vec3f), "Temp bWeights");
02163     if (!tempWeights) error=1;
02164 
02165     /*
02166     *   Generate a temporary bounding box array for UV faces to optimize
02167     *   the pixel-inside-a-face search.
02168     */
02169     if (!error) {
02170         faceBB = (struct Bounds2D *) MEM_mallocN(numOfFaces*sizeof(struct Bounds2D), "MPCanvasFaceBB");
02171         if (!faceBB) error=1;
02172     }
02173 
02174     if (!error)
02175     for (ty=0; ty<numOfFaces; ty++) {
02176         int numOfVert = (mface[ty].v4) ? 4 : 3;
02177         int i;
02178 
02179         copy_v2_v2(faceBB[ty].min, tface[ty].uv[0]);
02180         copy_v2_v2(faceBB[ty].max, tface[ty].uv[0]);
02181 
02182         for (i = 1; i<numOfVert; i++) {
02183             if (tface[ty].uv[i][0] < faceBB[ty].min[0]) faceBB[ty].min[0] = tface[ty].uv[i][0];
02184             if (tface[ty].uv[i][1] < faceBB[ty].min[1]) faceBB[ty].min[1] = tface[ty].uv[i][1];
02185             if (tface[ty].uv[i][0] > faceBB[ty].max[0]) faceBB[ty].max[0] = tface[ty].uv[i][0];
02186             if (tface[ty].uv[i][1] > faceBB[ty].max[1]) faceBB[ty].max[1] = tface[ty].uv[i][1];
02187 
02188         }
02189     }
02190 
02191     /*
02192     *   Loop through every pixel and check
02193     *   if pixel is uv-mapped on a canvas face.
02194     */
02195     if (!error) {
02196         #pragma omp parallel for schedule(static)
02197         for (ty = 0; ty < h; ty++)
02198         {
02199             int tx;
02200             for (tx = 0; tx < w; tx++)
02201             {
02202                 int i, sample;
02203                 int index = tx+w*ty;
02204                 PaintUVPoint *tPoint = (&tempPoints[index]);
02205 
02206                 short isInside = 0; /* if point is inside a uv face */
02207 
02208                 float d1[2], d2[2], d3[2], point[5][2];
02209                 float dot00,dot01,dot02,dot11,dot12, invDenom, u,v;
02210 
02211                 /* Init per pixel settings */
02212                 tPoint->face_index = -1;
02213                 tPoint->neighbour_pixel = -1;
02214                 tPoint->pixel_index = index;
02215 
02216                 /* Actual pixel center, used when collision is found    */
02217                 point[0][0] = ((float)tx + 0.5f) / w;
02218                 point[0][1] = ((float)ty + 0.5f) / h;
02219 
02220                 /*
02221                 * A pixel middle sample isn't enough to find very narrow polygons
02222                 * So using 4 samples of each corner too
02223                 */
02224                 point[1][0] = ((float)tx) / w;
02225                 point[1][1] = ((float)ty) / h;
02226 
02227                 point[2][0] = ((float)tx+1) / w;
02228                 point[2][1] = ((float)ty) / h;
02229 
02230                 point[3][0] = ((float)tx) / w;
02231                 point[3][1] = ((float)ty+1) / h;
02232 
02233                 point[4][0] = ((float)tx+1) / w;
02234                 point[4][1] = ((float)ty+1) / h;
02235 
02236 
02237                 /* Loop through samples, starting from middle point */
02238                 for (sample=0; sample<5; sample++) {
02239                     
02240                     /* Loop through every face in the mesh  */
02241                     for (i=0; i<numOfFaces; i++) {
02242 
02243                         /* Check uv bb  */
02244                         if (faceBB[i].min[0] > (point[sample][0])) continue;
02245                         if (faceBB[i].min[1] > (point[sample][1])) continue;
02246                         if (faceBB[i].max[0] < (point[sample][0])) continue;
02247                         if (faceBB[i].max[1] < (point[sample][1])) continue;
02248 
02249                         /*  Calculate point inside a triangle check
02250                         *   for uv0,1,2 */
02251                         sub_v2_v2v2(d1,  tface[i].uv[2], tface[i].uv[0]);   // uv2 - uv0
02252                         sub_v2_v2v2(d2,  tface[i].uv[1], tface[i].uv[0]);   // uv1 - uv0
02253                         sub_v2_v2v2(d3,  point[sample], tface[i].uv[0]);    // point - uv0
02254 
02255                         dot00 = d1[0]*d1[0] + d1[1]*d1[1];
02256                         dot01 = d1[0]*d2[0] + d1[1]*d2[1];
02257                         dot02 = d1[0]*d3[0] + d1[1]*d3[1];
02258                         dot11 = d2[0]*d2[0] + d2[1]*d2[1];
02259                         dot12 = d2[0]*d3[0] + d2[1]*d3[1];
02260 
02261                         invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
02262                         u = (dot11 * dot02 - dot01 * dot12) * invDenom;
02263                         v = (dot00 * dot12 - dot01 * dot02) * invDenom;
02264 
02265                         if ((u > 0) && (v > 0) && (u + v < 1)) {isInside=1;} /* is inside a triangle */
02266 
02267                         /*  If collision wasn't found but the face is a quad
02268                         *   do another check for the second half */
02269                         if ((!isInside) && mface[i].v4)
02270                         {
02271 
02272                             /* change d2 to test the other half */
02273                             sub_v2_v2v2(d2,  tface[i].uv[3], tface[i].uv[0]);   // uv3 - uv0
02274 
02275                             /* test again   */
02276                             dot00 = d1[0]*d1[0] + d1[1]*d1[1];
02277                             dot01 = d1[0]*d2[0] + d1[1]*d2[1];
02278                             dot02 = d1[0]*d3[0] + d1[1]*d3[1];
02279                             dot11 = d2[0]*d2[0] + d2[1]*d2[1];
02280                             dot12 = d2[0]*d3[0] + d2[1]*d3[1];
02281 
02282                             invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
02283                             u = (dot11 * dot02 - dot01 * dot12) * invDenom;
02284                             v = (dot00 * dot12 - dot01 * dot02) * invDenom;
02285 
02286                             if ((u > 0) && (v > 0) && (u + v < 1)) {isInside=2;} /* is inside the second half of the quad */
02287 
02288                         }
02289 
02290                         /*
02291                         *   If point was inside the face
02292                         */
02293                         if (isInside != 0) {
02294 
02295                             float uv1co[2], uv2co[2], uv3co[2], uv[2];
02296                             int j;
02297 
02298                             /* Get triagnle uvs */
02299                             if (isInside==1) {
02300                                 copy_v2_v2(uv1co, tface[i].uv[0]);
02301                                 copy_v2_v2(uv2co, tface[i].uv[1]);
02302                                 copy_v2_v2(uv3co, tface[i].uv[2]);
02303                             }
02304                             else {
02305                                 copy_v2_v2(uv1co, tface[i].uv[0]);
02306                                 copy_v2_v2(uv2co, tface[i].uv[2]);
02307                                 copy_v2_v2(uv3co, tface[i].uv[3]);
02308                             }
02309 
02310                             /* Add b-weights per anti-aliasing sample   */
02311                             for (j=0; j<aa_samples; j++) {
02312                                 uv[0] = point[0][0] + jitter5sample[j*2] / w;
02313                                 uv[1] = point[0][1] + jitter5sample[j*2+1] / h;
02314 
02315                                 barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index*aa_samples+j].v);
02316                             }
02317 
02318                             /* Set surface point face values    */
02319                             tPoint->face_index = i;                         /* face index */
02320                             tPoint->quad = (isInside == 2) ? 1 : 0;     /* quad or tri part*/
02321 
02322                             /* save vertex indexes  */
02323                             tPoint->v1 = mface[i].v1;
02324                             tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2;
02325                             tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3;
02326 
02327                             sample = 5; /* make sure we exit sample loop as well */
02328                             break;
02329                         }
02330                     }
02331                 } /* sample loop */
02332             }
02333         }
02334 
02335         /*
02336         *   Now loop through every pixel that was left without index
02337         *   and find if they have neighbouring pixels that have an index.
02338         *   If so use that polygon as pixel surface.
02339         *   (To avoid seams on uv island edges)
02340         */
02341         #pragma omp parallel for schedule(static)
02342         for (ty = 0; ty < h; ty++)
02343         {
02344             int tx;
02345             for (tx = 0; tx < w; tx++)
02346             {
02347                 int index = tx+w*ty;
02348                 PaintUVPoint *tPoint = (&tempPoints[index]);
02349 
02350                 /* If point isnt't on canvas mesh   */
02351                 if (tPoint->face_index == -1) {
02352                     int u_min, u_max, v_min, v_max;
02353                     int u,v, ind;
02354                     float point[2];
02355 
02356                     /* get loop area    */
02357                     u_min = (tx > 0) ? -1 : 0;
02358                     u_max = (tx < (w-1)) ? 1 : 0;
02359                     v_min = (ty > 0) ? -1 : 0;
02360                     v_max = (ty < (h-1)) ? 1 : 0;
02361 
02362                     point[0] = ((float)tx + 0.5f) / w;
02363                     point[1] = ((float)ty + 0.5f) / h;
02364 
02365                     /* search through defined area for neighbour    */
02366                     for (u=u_min; u<=u_max; u++)
02367                         for (v=v_min; v<=v_max; v++) {
02368                             /* if not this pixel itself */
02369                             if (u!=0 || v!=0) {
02370                                 ind = (tx+u)+w*(ty+v);
02371 
02372                                 /* if neighbour has index   */
02373                                 if (tempPoints[ind].face_index != -1) {
02374 
02375                                     float uv1co[2], uv2co[2], uv3co[2], uv[2];
02376                                     int i = tempPoints[ind].face_index, j;
02377 
02378                                     /* Now calculate pixel data for this pixel as it was on polygon surface */
02379                                     if (!tempPoints[ind].quad) {
02380                                         copy_v2_v2(uv1co, tface[i].uv[0]);
02381                                         copy_v2_v2(uv2co, tface[i].uv[1]);
02382                                         copy_v2_v2(uv3co, tface[i].uv[2]);
02383                                     }
02384                                     else {
02385                                         copy_v2_v2(uv1co, tface[i].uv[0]);
02386                                         copy_v2_v2(uv2co, tface[i].uv[2]);
02387                                         copy_v2_v2(uv3co, tface[i].uv[3]);
02388                                     }
02389 
02390                                     /* Add b-weights per anti-aliasing sample   */
02391                                     for (j=0; j<aa_samples; j++) {
02392 
02393                                         uv[0] = point[0] + jitter5sample[j*2] / w;
02394                                         uv[1] = point[1] + jitter5sample[j*2+1] / h;
02395                                         barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index*aa_samples+j].v);
02396                                     }
02397 
02398                                     /* Set values   */
02399                                     tPoint->neighbour_pixel = ind;              // face index
02400                                     tPoint->quad = tempPoints[ind].quad;        // quad or tri
02401 
02402                                     /* save vertex indexes  */
02403                                     tPoint->v1 = mface[i].v1;
02404                                     tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2;
02405                                     tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3;
02406 
02407                                     u = u_max + 1;  /* make sure we exit outer loop as well */
02408                                     break;
02409                                 }
02410                         }
02411                     }
02412                 }
02413             }
02414         }
02415 
02416         /*
02417         *   When base loop is over convert found neighbour indexes to real ones
02418         *   Also count the final number of active surface points
02419         */
02420         for (ty = 0; ty < h; ty++)
02421         {
02422             int tx;
02423             for (tx = 0; tx < w; tx++)
02424             {
02425                 int index = tx+w*ty;
02426                 PaintUVPoint *tPoint = (&tempPoints[index]);
02427 
02428                 if (tPoint->face_index == -1 && tPoint->neighbour_pixel != -1) tPoint->face_index = tempPoints[tPoint->neighbour_pixel].face_index;
02429                 if (tPoint->face_index != -1) active_points++;
02430             }
02431         }
02432 
02433         /*  Generate surface adjacency data. */
02434         {
02435             int i, cursor=0;
02436 
02437             /* Create a temporary array of final indexes (before unassigned
02438             *  pixels have been dropped) */
02439             for (i=0; i<w*h; i++) {
02440                 if (tempPoints[i].face_index != -1) {
02441                     final_index[i] = cursor;
02442                     cursor++;
02443                 }
02444             }
02445             /* allocate memory */
02446             sData->total_points = w*h;
02447             dynamicPaint_initAdjacencyData(surface, 1);
02448 
02449             if (sData->adj_data) {
02450                 PaintAdjData *ed = sData->adj_data;
02451                 unsigned int n_pos = 0;
02452                 for (ty = 0; ty < h; ty++)
02453                 {
02454                     int tx;
02455                     for (tx = 0; tx < w; tx++)
02456                     {
02457                         int i, index = tx+w*ty;
02458 
02459                         if (tempPoints[index].face_index != -1) {
02460                             ed->n_index[final_index[index]] = n_pos;
02461                             ed->n_num[final_index[index]] = 0;
02462 
02463                             for (i=0; i<8; i++) {
02464 
02465                                 /* Try to find a neighbouring pixel in defined direction
02466                                 *  If not found, -1 is returned */
02467                                 int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i);
02468 
02469                                 if (n_target != -1) {
02470                                     ed->n_target[n_pos] = final_index[n_target];
02471                                     ed->n_num[final_index[index]]++;
02472                                     n_pos++;
02473                                 }
02474                             }
02475                         }
02476                     }
02477                 }
02478             }
02479         }
02480 
02481         /* Create final surface data without inactive points */
02482         {
02483             ImgSeqFormatData *f_data = MEM_callocN(sizeof(struct ImgSeqFormatData), "ImgSeqFormatData");
02484             if (f_data) {
02485                 f_data->uv_p = MEM_callocN(active_points*sizeof(struct PaintUVPoint), "PaintUVPoint");
02486                 f_data->barycentricWeights = MEM_callocN(active_points*aa_samples*sizeof(struct Vec3f), "PaintUVPoint");
02487 
02488                 if (!f_data->uv_p || !f_data->barycentricWeights) error=1;
02489             }
02490             else error=1;
02491 
02492             sData->total_points = active_points;
02493             
02494             /* in case of allocation error, free everything */
02495             if (error) {
02496                 if (f_data) {
02497                     if (f_data->uv_p) MEM_freeN(f_data->uv_p);
02498                     if (f_data->barycentricWeights) MEM_freeN(f_data->barycentricWeights);
02499                     MEM_freeN(f_data);
02500                 }
02501             }
02502             else {
02503                 int index, cursor = 0;
02504                 sData->total_points = active_points;
02505                 sData->format_data = f_data;
02506 
02507                 for(index = 0; index < (w*h); index++) {
02508                     if (tempPoints[index].face_index != -1) {
02509                         memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint));
02510                         memcpy(&f_data->barycentricWeights[cursor*aa_samples], &tempWeights[index*aa_samples], sizeof(Vec3f)*aa_samples);
02511                         cursor++;
02512                     }
02513                 }
02514             }
02515         }
02516     }
02517     if (error==1) setError(canvas, "Not enough free memory.");
02518 
02519     if (faceBB) MEM_freeN(faceBB);
02520     if (tempPoints) MEM_freeN(tempPoints);
02521     if (tempWeights) MEM_freeN(tempWeights);
02522     if (final_index) MEM_freeN(final_index);
02523 
02524     /* Init surface type data */
02525     if (!error) {
02526         dynamicPaint_allocateSurfaceType(surface);
02527 
02528 #if 0
02529         /*  -----------------------------------------------------------------
02530         *   For debug, output pixel statuses to the color map
02531         *   -----------------------------------------------------------------*/
02532         #pragma omp parallel for schedule(static)
02533         for (index = 0; index < sData->total_points; index++)
02534         {
02535             ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
02536             PaintUVPoint *uvPoint = &((PaintUVPoint*)f_data->uv_p)[index];
02537             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
02538             pPoint->alpha=1.0f;
02539 
02540             /* Every pixel that is assigned as "edge pixel" gets blue color */
02541             if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f;
02542             /* and every pixel that finally got an polygon gets red color   */
02543             if (uvPoint->face_index != -1) pPoint->color[0] = 1.0f;
02544             /* green color shows pixel face index hash  */
02545             if (uvPoint->face_index != -1) pPoint->color[1] = (float)(uvPoint->face_index % 255)/256.0f;
02546         }
02547 
02548 #endif
02549         dynamicPaint_setInitialColor(surface);
02550     }
02551 
02552     return (error == 0);
02553 }
02554 
02555 /*
02556 *   Outputs an image file from uv surface data.
02557 */
02558 void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char* filename, short output_layer)
02559 {
02560     int index;
02561     ImBuf* ibuf = NULL;
02562     PaintSurfaceData *sData = surface->data;
02563     ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
02564     /* OpenEXR or PNG   */
02565     int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG;
02566     char output_file[FILE_MAX];
02567 
02568     if (!sData || !sData->type_data) {setError(surface->canvas, "Image save failed: Invalid surface.");return;}
02569     /* if selected format is openexr, but current build doesnt support one */
02570     #ifndef WITH_OPENEXR
02571     if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG;
02572     #endif
02573     BLI_strncpy(output_file, filename, sizeof(output_file));
02574     BKE_add_image_extension(output_file, format);
02575 
02576     /* Validate output file path    */
02577     BLI_path_abs(output_file, G.main->name);
02578     BLI_make_existing_file(output_file);
02579 
02580     /* Init image buffer    */
02581     ibuf = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat);
02582     if (ibuf == NULL) {setError(surface->canvas, "Image save failed: Not enough free memory.");return;}
02583 
02584     #pragma omp parallel for schedule(static)
02585     for (index = 0; index < sData->total_points; index++)
02586     {
02587         int pos=f_data->uv_p[index].pixel_index*4;  /* image buffer position */
02588 
02589         /* Set values of preferred type */
02590         if (output_layer == 1) {
02591             /* wetmap */
02592             if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
02593                 PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
02594                 float value = (point->wetness > 1.0f) ? 1.0f : point->wetness;
02595 
02596                 ibuf->rect_float[pos]=value;
02597                 ibuf->rect_float[pos+1]=value;
02598                 ibuf->rect_float[pos+2]=value;
02599                 ibuf->rect_float[pos+3]=1.0f;
02600             }
02601         }
02602         else if (output_layer == 0) {
02603             /* Paintmap */
02604             if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
02605                 PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
02606 
02607                 /* blend wet and dry layers */
02608                 blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]);
02609 
02610                 /* Multiply color by alpha if enabled   */
02611                 if (surface->flags & MOD_DPAINT_MULALPHA) {
02612                     ibuf->rect_float[pos]   *= ibuf->rect_float[pos+3];
02613                     ibuf->rect_float[pos+1] *= ibuf->rect_float[pos+3];
02614                     ibuf->rect_float[pos+2] *= ibuf->rect_float[pos+3];
02615                 }
02616             }
02617             /* displace */
02618             else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
02619                 float depth = ((float*)sData->type_data)[index];
02620                 if (surface->depth_clamp)
02621                     depth /= surface->depth_clamp;
02622 
02623                 if (surface->disp_type == MOD_DPAINT_DISP_DISPLACE) {
02624                     depth = (0.5f - depth/2.0f);
02625                 }
02626 
02627                 CLAMP(depth, 0.0f, 1.0f);
02628 
02629                 ibuf->rect_float[pos]=depth;
02630                 ibuf->rect_float[pos+1]=depth;
02631                 ibuf->rect_float[pos+2]=depth;
02632                 ibuf->rect_float[pos+3]=1.0f;
02633             }
02634             /* waves */
02635             else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
02636                 PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
02637                 float depth = wPoint->height;
02638                 if (surface->depth_clamp)
02639                         depth /= surface->depth_clamp;
02640                 depth = (0.5f + depth/2.0f);
02641                 CLAMP(depth, 0.0f, 1.0f);
02642 
02643                 ibuf->rect_float[pos]=depth;
02644                 ibuf->rect_float[pos+1]=depth;
02645                 ibuf->rect_float[pos+2]=depth;
02646                 ibuf->rect_float[pos+3]=1.0f;
02647             }
02648         }
02649     }
02650 
02651     /* Set output format, png in case exr isnt supported */
02652     ibuf->ftype= PNG|95;
02653 #ifdef WITH_OPENEXR
02654     if (format == R_IMF_IMTYPE_OPENEXR) {   /* OpenEXR 32-bit float */
02655         ibuf->ftype = OPENEXR | OPENEXR_COMPRESS;
02656     }
02657 #endif
02658 
02659     /* Save image */
02660     IMB_saveiff(ibuf, output_file, IB_rectfloat);
02661     IMB_freeImBuf(ibuf);
02662 }
02663 
02664 
02665 /***************************** Material / Texture Sampling ******************************/
02666 
02667 /* stores a copy of required materials to allow doing adjustments
02668 *  without interfering the render/preview */
02669 typedef struct BrushMaterials {
02670     Material *mat;
02671     Material **ob_mats;
02672     int tot;
02673 } BrushMaterials;
02674 
02675 /* Initialize materials for brush object:
02676 *  Calculates inverse matrices for linked objects, updates
02677 *  volume caches etc. */
02678 static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
02679 {
02680     /* Calculate inverse transformation matrix
02681     *  for this object */
02682     invert_m4_m4(brushOb->imat, brushOb->obmat);
02683     copy_m4_m4(brushOb->imat_ren, brushOb->imat);
02684 
02685     /* Now process every material linked to this brush object */
02686     if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) {
02687         int i, tot=(*give_totcolp(brushOb));
02688 
02689         /* allocate material pointer array */
02690         if (tot) {
02691             bMats->ob_mats = MEM_callocN(sizeof(Material*)*(tot), "BrushMaterials");
02692             for (i=0; i<tot; i++) {
02693                 bMats->ob_mats[i] = RE_init_sample_material(give_current_material(brushOb,(i+1)), scene);
02694             }
02695         }
02696         bMats->tot = tot;
02697     }
02698     else {
02699         bMats->mat = RE_init_sample_material(ui_mat, scene);
02700     }
02701 }
02702 
02703 /* free all data allocated by dynamicPaint_updateBrushMaterials() */
02704 static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats)
02705 {
02706     /* Now process every material linked to this brush object */
02707     if (bMats->ob_mats) {
02708         int i;
02709         for (i=0; i<bMats->tot; i++) {
02710             RE_free_sample_material(bMats->ob_mats[i]);
02711         }
02712         MEM_freeN(bMats->ob_mats);
02713     }
02714     else if (bMats->mat) {
02715         RE_free_sample_material(bMats->mat);
02716     }
02717 }
02718 
02719 /*
02720 *   Get material diffuse color and alpha (including linked textures) in given coordinates
02721 */
02722 void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm)
02723 {
02724     Material *mat = bMats->mat;
02725     MFace *mface = orcoDm->getFaceArray(orcoDm);
02726 
02727     /* If no material defined, use the one assigned to the mesh face */
02728     if (mat == NULL) {
02729         if (bMats->ob_mats) {
02730             int mat_nr = mface[faceIndex].mat_nr;
02731             if (mat_nr >= (*give_totcolp(brushOb))) return;
02732             mat = bMats->ob_mats[mat_nr];
02733             if (mat == NULL) return;    /* No material assigned */
02734         }
02735         else return;
02736     }
02737 
02738     RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb);
02739 }
02740 
02741 
02742 /***************************** Ray / Nearest Point Utils ******************************/
02743 
02744 
02745 /*  A modified callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
02746 *   userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
02747 *  
02748 *   To optimize brush detection speed this doesn't calculate hit coordinates or normal.
02749 *   If ray hit the second half of a quad, no[0] is set to 1.0f.
02750 */
02751 static void mesh_faces_spherecast_dp(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
02752 {
02753     const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
02754     MVert *vert = data->vert;
02755     MFace *face = data->face + index;
02756     short quad = 0;
02757 
02758     float *t0, *t1, *t2, *t3;
02759     t0 = vert[ face->v1 ].co;
02760     t1 = vert[ face->v2 ].co;
02761     t2 = vert[ face->v3 ].co;
02762     t3 = face->v4 ? vert[ face->v4].co : NULL;
02763 
02764     do
02765     {   
02766         float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
02767 
02768         if(dist >= 0 && dist < hit->dist)
02769         {
02770             hit->index = index;
02771             hit->dist = dist;
02772             hit->no[0] = (quad) ? 1.0f : 0.0f;
02773         }
02774 
02775         t1 = t2;
02776         t2 = t3;
02777         t3 = NULL;
02778         quad = 1;
02779 
02780     } while(t2);
02781 }
02782 
02783 /* A modified callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
02784 *  userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
02785 *  
02786 *   To optimize brush detection speed this doesn't calculate hit normal.
02787 *   If ray hit the second half of a quad, no[0] is set to 1.0f, else 0.0f
02788 */
02789 static void mesh_faces_nearest_point_dp(void *userdata, int index, const float *co, BVHTreeNearest *nearest)
02790 {
02791     const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
02792     MVert *vert = data->vert;
02793     MFace *face = data->face + index;
02794     short quad = 0;
02795 
02796     float *t0, *t1, *t2, *t3;
02797     t0 = vert[ face->v1 ].co;
02798     t1 = vert[ face->v2 ].co;
02799     t2 = vert[ face->v3 ].co;
02800     t3 = face->v4 ? vert[ face->v4].co : NULL;
02801 
02802     do
02803     {   
02804         float nearest_tmp[3], dist;
02805         int vertex, edge;
02806         
02807         dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
02808         if(dist < nearest->dist)
02809         {
02810             nearest->index = index;
02811             nearest->dist = dist;
02812             copy_v3_v3(nearest->co, nearest_tmp);
02813             nearest->no[0] = (quad) ? 1.0f : 0.0f;
02814         }
02815 
02816         t1 = t2;
02817         t2 = t3;
02818         t3 = NULL;
02819         quad = 1;
02820 
02821     } while(t2);
02822 }
02823 
02824 
02825 /***************************** Brush Painting Calls ******************************/
02826 
02827 /*
02828 *   Mix color values to canvas point.
02829 *
02830 *   surface : canvas surface
02831 *   index : surface point index
02832 *   paintFlags : paint object flags
02833 *   paintColor,Alpha,Wetness : to be mixed paint values
02834 *   timescale : value used to adjust time dependand
02835 *               operations when using substeps
02836 */
02837 static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, float *paintColor, float *paintAlpha, float *paintWetness, float *timescale)
02838 {
02839     PaintPoint *pPoint = &((PaintPoint*)surface->data->type_data)[index];
02840 
02841     /* Add paint    */
02842     if (!(paintFlags & MOD_DPAINT_ERASE)) {
02843         float mix[4];
02844         float temp_alpha = (*paintAlpha) * ((paintFlags & MOD_DPAINT_ABS_ALPHA) ? 1.0f : (*timescale));
02845 
02846         /* mix brush color with wet layer color */
02847         blendColors(pPoint->e_color, pPoint->e_alpha, paintColor, temp_alpha, mix);
02848         copy_v3_v3(pPoint->e_color, mix);
02849 
02850         /* mix wetness and alpha depending on selected alpha mode */
02851         if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
02852             /* update values to the brush level unless theyre higher already */
02853             if (pPoint->e_alpha < (*paintAlpha)) pPoint->e_alpha = (*paintAlpha);
02854             if (pPoint->wetness < (*paintWetness)) pPoint->wetness = (*paintWetness);
02855         }
02856         else {
02857             float wetness = (*paintWetness);
02858             CLAMP(wetness, 0.0f, 1.0f);
02859             pPoint->e_alpha = mix[3];
02860             pPoint->wetness = pPoint->wetness*(1.0f-wetness) + wetness;
02861         }
02862 
02863         if (pPoint->wetness<MIN_WETNESS) pPoint->wetness = MIN_WETNESS;
02864 
02865         pPoint->state = DPAINT_PAINT_NEW;
02866     }
02867     /* Erase paint  */
02868     else {
02869         float a_ratio, a_highest;
02870         float wetness;
02871         float invFact = 1.0f - (*paintAlpha);
02872 
02873         /*
02874         *   Make highest alpha to match erased value
02875         *   but maintain alpha ratio
02876         */
02877         if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
02878             a_highest = (pPoint->e_alpha > pPoint->alpha) ? pPoint->e_alpha : pPoint->alpha;
02879             if (a_highest > invFact) {
02880                 a_ratio = invFact / a_highest;
02881 
02882                 pPoint->e_alpha *= a_ratio;
02883                 pPoint->alpha *= a_ratio;
02884             }
02885         }
02886         else {
02887             pPoint->e_alpha -= (*paintAlpha) * (*timescale);
02888             if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
02889             pPoint->alpha -= (*paintAlpha) * (*timescale);
02890             if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
02891         }
02892 
02893         wetness = (1.0f - (*paintWetness)) * pPoint->e_alpha;
02894         if (pPoint->wetness > wetness) pPoint->wetness = wetness;
02895     }
02896 }
02897 
02898 /* applies given brush intersection value for wave surface */
02899 static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrushSettings *brush, float isect_height)
02900 {
02901     float isect_change = isect_height - wPoint->brush_isect;
02902     int hit = 0;
02903     /* intersection marked regardless of brush type or hit */
02904     wPoint->brush_isect = isect_height;
02905     wPoint->state = DPAINT_WAVE_ISECT_CHANGED;
02906 
02907     isect_height *= brush->wave_factor;
02908 
02909     /* determine hit depending on wave_factor */
02910     if (brush->wave_factor > 0.0f && wPoint->height > isect_height)
02911         hit = 1;
02912     else if (brush->wave_factor < 0.0f && wPoint->height < isect_height)
02913         hit = 1;
02914 
02915     if (hit) {
02916         if (brush->wave_type == MOD_DPAINT_WAVEB_DEPTH) {
02917             wPoint->height = isect_height;
02918             wPoint->state = DPAINT_WAVE_OBSTACLE;
02919             wPoint->velocity = 0.0f;
02920         }
02921         else if (brush->wave_type == MOD_DPAINT_WAVEB_FORCE)
02922             wPoint->velocity = isect_height;
02923         else if (brush->wave_type == MOD_DPAINT_WAVEB_REFLECT)
02924             wPoint->state = DPAINT_WAVE_REFLECT_ONLY;
02925         else if (brush->wave_type == MOD_DPAINT_WAVEB_CHANGE) {
02926             if (isect_change < 0.0f)
02927                 wPoint->height += isect_change*brush->wave_factor;
02928         }
02929     }
02930 }
02931 
02932 /*
02933 *   add brush results to the surface data depending on surface type
02934 */
02935 static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned int index, DynamicPaintBrushSettings *brush,
02936                                          float paint[3], float influence, float depth, float vel_factor, float timescale)
02937 {
02938         PaintSurfaceData *sData = surface->data;
02939         float strength;
02940 
02941         /* apply influence scale */
02942         influence *= surface->influence_scale;
02943         depth *= surface->influence_scale;
02944 
02945         strength = influence * brush->alpha;
02946         CLAMP(strength, 0.0f, 1.0f);
02947 
02948         /* Sample velocity colorband if required */
02949         if (brush->flags & (MOD_DPAINT_VELOCITY_ALPHA|MOD_DPAINT_VELOCITY_COLOR|MOD_DPAINT_VELOCITY_DEPTH)) {
02950             float coba_res[4];
02951             vel_factor /= brush->max_velocity;
02952             CLAMP(vel_factor, 0.0f, 1.0f);
02953 
02954             if (do_colorband(brush->vel_ramp, vel_factor, coba_res)) {
02955                 if (brush->flags & MOD_DPAINT_VELOCITY_COLOR) {
02956                     paint[0] = coba_res[0];
02957                     paint[1] = coba_res[1];
02958                     paint[2] = coba_res[2];
02959                 }
02960                 if (brush->flags & MOD_DPAINT_VELOCITY_ALPHA)
02961                     strength *= coba_res[3];
02962                 if (brush->flags & MOD_DPAINT_VELOCITY_DEPTH)
02963                     depth *= coba_res[3];
02964             }
02965         }
02966 
02967         /* mix paint surface */
02968         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
02969 
02970             float paintWetness = brush->wetness * strength;
02971             float paintAlpha = strength;
02972 
02973             dynamicPaint_mixPaintColors(surface, index, brush->flags, paint, &paintAlpha, &paintWetness, &timescale);
02974 
02975         }
02976         /* displace surface */
02977         else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
02978             float *value = (float*)sData->type_data;
02979 
02980             if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL)
02981                 depth = value[index] + depth;
02982 
02983             if (surface->depth_clamp) {
02984                 CLAMP(depth, 0.0f-surface->depth_clamp, surface->depth_clamp);
02985             }
02986 
02987             if (brush->flags & MOD_DPAINT_ERASE) {
02988                 value[index] *= (1.0f - strength);
02989                 if (value[index] < 0.0f) value[index] = 0.0f;
02990             }
02991             else {
02992                 if (value[index] < depth) value[index] = depth;
02993             }
02994         }
02995         /* vertex weight group surface */
02996         else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
02997             float *value = (float*)sData->type_data;
02998 
02999             if (brush->flags & MOD_DPAINT_ERASE) {
03000                 value[index] *= (1.0f - strength);
03001                 if (value[index] < 0.0f) value[index] = 0.0f;
03002             }
03003             else {
03004                 if (value[index] < strength) value[index] = strength;
03005             }
03006         }
03007         /* wave surface */
03008         else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
03009             if (brush->wave_clamp) {
03010                 CLAMP(depth, 0.0f-brush->wave_clamp, brush->wave_clamp);
03011             }
03012 
03013             dynamicPaint_mixWaveHeight(&((PaintWavePoint*)sData->type_data)[index],
03014                 brush, 0.0f-depth);
03015         }
03016 
03017         /* doing velocity based painting */
03018         if (sData->bData->brush_velocity) {
03019             sData->bData->brush_velocity[index*4+3] *= influence;
03020         }
03021 }
03022 
03023 /* checks whether surface and brush bounds intersect depending on brush type */
03024 static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush, float brush_radius)
03025 {
03026     if (brush->collision == MOD_DPAINT_COL_VOLUME)
03027         return boundsIntersect(b1, b2);
03028     else if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST)
03029         return boundsIntersectDist(b1, b2, brush_radius);
03030     else return 1;
03031 }
03032 
03033 /* calculate velocity for mesh vertices */
03034 static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
03035 {
03036     int i;
03037     float prev_obmat[4][4];
03038     DerivedMesh *dm_p, *dm_c;
03039     MVert *mvert_p, *mvert_c;
03040     int numOfVerts_p, numOfVerts_c;
03041 
03042     float cur_sfra = scene->r.subframe;
03043     int cur_fra = scene->r.cfra;
03044     float prev_sfra = cur_sfra - timescale;
03045     int prev_fra = cur_fra;
03046 
03047     if (prev_sfra < 0.0f) {
03048         prev_sfra += 1.0f;
03049         prev_fra = cur_fra - 1;
03050     }
03051 
03052     /* previous frame dm */
03053     scene->r.cfra = prev_fra;
03054     scene->r.subframe = prev_sfra;
03055 
03056     subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene));
03057     dm_p = CDDM_copy(brush->dm);
03058     numOfVerts_p = dm_p->getNumVerts(dm_p);
03059     mvert_p = dm_p->getVertArray(dm_p);
03060     copy_m4_m4(prev_obmat, ob->obmat);
03061 
03062     /* current frame dm */
03063     scene->r.cfra = cur_fra;
03064     scene->r.subframe = cur_sfra;
03065 
03066     subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene));
03067     dm_c = brush->dm;
03068     numOfVerts_c = dm_c->getNumVerts(dm_c);
03069     mvert_c = dm_p->getVertArray(dm_c);
03070 
03071     (*brushVel) = (struct Vec3f *) MEM_mallocN(numOfVerts_c*sizeof(Vec3f), "Dynamic Paint brush velocity");
03072     if (!(*brushVel)) return;
03073 
03074     /* if mesh is constructive -> num of verts has changed,
03075     *  only use current frame derived mesh */
03076     if (numOfVerts_p != numOfVerts_c)
03077         mvert_p = mvert_c;
03078 
03079     /* calculate speed */
03080     #pragma omp parallel for schedule(static)
03081     for (i=0; i<numOfVerts_c; i++) {
03082         float p1[3], p2[3];
03083 
03084         copy_v3_v3(p1, mvert_p[i].co);
03085         mul_m4_v3(prev_obmat, p1);
03086 
03087         copy_v3_v3(p2, mvert_c[i].co);
03088         mul_m4_v3(ob->obmat, p2);
03089 
03090         sub_v3_v3v3((*brushVel)[i].v, p2, p1);
03091         mul_v3_fl((*brushVel)[i].v, 1.0f/timescale);
03092     }
03093 
03094     dm_p->release(dm_p);
03095 }
03096 
03097 /* calculate velocity for object center point */
03098 static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
03099 {
03100     float prev_obmat[4][4];
03101     float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f};
03102 
03103     float cur_sfra = scene->r.subframe;
03104     int cur_fra = scene->r.cfra;
03105     float prev_sfra = cur_sfra - timescale;
03106     int prev_fra = cur_fra;
03107 
03108     if (prev_sfra < 0.0f) {
03109         prev_sfra += 1.0f;
03110         prev_fra = cur_fra - 1;
03111     }
03112 
03113     /* previous frame dm */
03114     scene->r.cfra = prev_fra;
03115     scene->r.subframe = prev_sfra;
03116     subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_curframe(scene));
03117     copy_m4_m4(prev_obmat, ob->obmat);
03118 
03119     /* current frame dm */
03120     scene->r.cfra = cur_fra;
03121     scene->r.subframe = cur_sfra;
03122     subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_curframe(scene));
03123 
03124     /* calculate speed */
03125     mul_m4_v3(prev_obmat, prev_loc);
03126     mul_m4_v3(ob->obmat, cur_loc);
03127 
03128     sub_v3_v3v3(brushVel->v, cur_loc, prev_loc);
03129     mul_v3_fl(brushVel->v, 1.0f/timescale);
03130 }
03131 
03132 /*
03133 *   Paint a brush object mesh to the surface
03134 */
03135 static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
03136                                   DynamicPaintBrushSettings *brush,
03137                                   Object *brushOb,
03138                                   BrushMaterials *bMats,
03139                                   Scene *scene,
03140                                   float timescale)
03141 {
03142     PaintSurfaceData *sData = surface->data;
03143     PaintBakeData *bData = sData->bData;
03144     DerivedMesh *dm = NULL;
03145     Vec3f *brushVelocity = NULL;
03146     MVert *mvert = NULL;
03147     MFace *mface = NULL;
03148 
03149     if (brush->flags & MOD_DPAINT_USES_VELOCITY)
03150         dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale);
03151 
03152     if (!brush->dm) return 0;
03153     {
03154         BVHTreeFromMesh treeData = {0};
03155         float avg_brushNor[3] = {0.0f};
03156         float brush_radius = brush->paint_distance * surface->radius_scale;
03157         int numOfVerts;
03158         int ii;
03159         Bounds3D mesh_bb = {0};
03160         VolumeGrid *grid = bData->grid;
03161 
03162         dm = CDDM_copy(brush->dm);
03163         mvert = dm->getVertArray(dm);
03164         mface = dm->getFaceArray(dm);
03165         numOfVerts = dm->getNumVerts(dm);
03166 
03167         /*  Transform collider vertices to global space
03168         *   (Faster than transforming per surface point
03169         *   coordinates and normals to object space) */
03170         for (ii=0; ii<numOfVerts; ii++) {
03171             mul_m4_v3(brushOb->obmat, mvert[ii].co);
03172             boundInsert(&mesh_bb, mvert[ii].co);
03173 
03174             /* for project brush calculate average normal */
03175             if (brush->collision & MOD_DPAINT_COL_DIST && brush->flags & MOD_DPAINT_PROX_PROJECT) {
03176                 float nor[3];
03177                 normal_short_to_float_v3(nor, mvert[ii].no);
03178                 mul_mat3_m4_v3(brushOb->obmat, nor);
03179                 normalize_v3(nor);
03180 
03181                 add_v3_v3(avg_brushNor, nor);
03182             }
03183         }
03184 
03185         if (brush->collision & MOD_DPAINT_COL_DIST && brush->flags & MOD_DPAINT_PROX_PROJECT) {
03186             mul_v3_fl(avg_brushNor, 1.0f/(float)numOfVerts);
03187             /* instead of null vector use positive z */
03188             if (!(MIN3(avg_brushNor[0],avg_brushNor[1],avg_brushNor[2])))
03189                 avg_brushNor[2] = 1.0f;
03190             else
03191                 normalize_v3(avg_brushNor);
03192         }
03193 
03194         /* check bounding box collision */
03195         if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius))
03196         /* Build a bvh tree from transformed vertices   */
03197         if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8))
03198         {
03199             int c_index;
03200             int total_cells = grid->dim[0]*grid->dim[1]*grid->dim[2];
03201 
03202             /* loop through space partitioning grid */
03203             for (c_index=0; c_index<total_cells; c_index++) {
03204                 int id;
03205 
03206                 /* check grid cell bounding box */
03207                 if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius))
03208                     continue;
03209 
03210                 /* loop through cell points and process brush */
03211                 #pragma omp parallel for schedule(static)
03212                 for (id = 0; id < grid->s_num[c_index]; id++)
03213                 {
03214                     int index = grid->t_index[grid->s_pos[c_index] + id];
03215                     int ss, samples = bData->s_num[index];
03216                     float total_sample = (float)samples;
03217                     float brushStrength = 0.0f; /* brush influence factor */
03218                     float depth = 0.0f;     /* brush intersection depth */
03219                     float velocity_val = 0.0f;
03220 
03221                     float paintColor[3] = {0.0f};
03222                     int numOfHits = 0;
03223 
03224                     /* for image sequence anti-aliasing, use gaussian factors */
03225                     if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
03226                         total_sample = gaussianTotal;
03227 
03228                     /* Supersampling    */
03229                     for (ss=0; ss<samples; ss++)
03230                     {
03231 
03232                         float ray_start[3], ray_dir[3];
03233                         float sample_factor = 0.0f;
03234                         float sampleStrength = 0.0f;
03235                         BVHTreeRayHit hit;
03236                         BVHTreeNearest nearest;
03237                         short hit_found = 0;
03238 
03239                         /* volume sample */
03240                         float volume_factor = 0.0f;
03241                         /* proximity sample */
03242                         float proximity_factor = 0.0f;
03243                         float prox_colorband[4] = {0.0f};
03244                         int inner_proximity = (brush->flags & MOD_DPAINT_INVERSE_PROX && 
03245                                                    brush->collision == MOD_DPAINT_COL_VOLDIST);
03246 
03247                         /* hit data */
03248                         float hitCoord[3];
03249                         int hitFace = -1;
03250                         short hitQuad = 0;
03251 
03252                         /* Supersampling factor */
03253                         if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
03254                             sample_factor = gaussianFactors[ss];
03255                         else
03256                             sample_factor = 1.0f;
03257 
03258                         /* Get current sample position in world coordinates */
03259                         copy_v3_v3(ray_start, bData->realCoord[bData->s_pos[index]+ss].v);
03260                         copy_v3_v3(ray_dir, bData->bNormal[index].invNorm);
03261 
03262                         /* a simple hack to minimize chance of ray leaks at identical ray <-> edge locations */
03263                         add_v3_fl(ray_start, 0.001f);
03264 
03265                         hit.index = -1;
03266                         hit.dist = 9999;
03267                         nearest.index = -1;
03268                         nearest.dist = brush_radius * brush_radius; /* find_nearest uses squared distance */
03269 
03270                         /* Check volume collision   */
03271                         if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
03272                         if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
03273                         {
03274                             /* We hit a triangle, now check if collision point normal is facing the point   */
03275 
03276                             /*  For optimization sake, hit point normal isn't calculated in ray cast loop   */
03277                             int v1=mface[hit.index].v1, v2=mface[hit.index].v2, v3=mface[hit.index].v3, quad=(hit.no[0] == 1.0f);
03278                             float dot;
03279 
03280                             if (quad) {v2=mface[hit.index].v3; v3=mface[hit.index].v4;}
03281                             normal_tri_v3( hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co);
03282                             dot = ray_dir[0]*hit.no[0] + ray_dir[1]*hit.no[1] + ray_dir[2]*hit.no[2];
03283 
03284                             /*  If ray and hit face normal are facing same direction
03285                             *   hit point is inside a closed mesh. */
03286                             if (dot>=0)
03287                             {
03288                                 float dist = hit.dist;
03289                                 int f_index = hit.index;
03290 
03291                                 /* Also cast a ray in opposite direction to make sure
03292                                 *  point is at least surrounded by two brush faces */
03293                                 negate_v3(ray_dir);
03294                                 hit.index = -1;
03295                                 hit.dist = 9999;
03296 
03297                                 BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData);
03298 
03299                                 if(hit.index != -1) {
03300                                     /* Add factor on supersample filter */
03301                                     volume_factor = 1.0f;
03302                                     hit_found = HIT_VOLUME;
03303 
03304                                     /* Mark hit info */
03305                                     madd_v3_v3v3fl(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
03306                                     depth += dist*sample_factor;
03307                                     hitFace = f_index;
03308                                     hitQuad = quad;
03309                                 }
03310                             }
03311                         }
03312                     
03313                         /* Check proximity collision    */
03314                         if ((brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) &&
03315                             (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX)))
03316                         {
03317                             float proxDist = -1.0f;
03318                             float hitCo[3];
03319                             short hQuad;
03320                             int face;
03321 
03322                             /* if inverse prox and no hit found, skip this sample */
03323                             if (inner_proximity && !hit_found) continue;
03324 
03325                             /* If pure distance proximity, find the nearest point on the mesh */
03326                             if (brush->collision != MOD_DPAINT_COL_DIST || !(brush->flags & MOD_DPAINT_PROX_PROJECT)) {
03327                                 if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
03328                                     proxDist = sqrtf(nearest.dist);
03329                                     copy_v3_v3(hitCo, nearest.co);
03330                                     hQuad = (nearest.no[0] == 1.0f);
03331                                     face = nearest.index;
03332                                 }
03333                             }
03334                             else { /* else cast a ray in defined projection direction */
03335                                 float proj_ray[3] = {0.0f};
03336 
03337                                 if (brush->ray_dir == MOD_DPAINT_RAY_CANVAS) {
03338                                     copy_v3_v3(proj_ray, bData->bNormal[index].invNorm);
03339                                     negate_v3(proj_ray);
03340                                 }
03341                                 else if (brush->ray_dir == MOD_DPAINT_RAY_BRUSH_AVG) {
03342                                     copy_v3_v3(proj_ray, avg_brushNor);
03343                                 }
03344                                 else  { /* MOD_DPAINT_RAY_ZPLUS */
03345                                     proj_ray[2] = 1.0f;
03346                                 }
03347                                 hit.index = -1;
03348                                 hit.dist = brush_radius;
03349 
03350                                 /* Do a face normal directional raycast, and use that distance  */
03351                                 if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
03352                                 {
03353                                     proxDist = hit.dist;
03354                                     madd_v3_v3v3fl(hitCo, ray_start, proj_ray, hit.dist);   /* Calculate final hit coordinates */
03355                                     hQuad = (hit.no[0] == 1.0f);
03356                                     face = hit.index;
03357                                 }
03358                             }
03359 
03360                             /* If a hit was found, calculate required values    */
03361                             if (proxDist >= 0.0f && proxDist <= brush_radius) {
03362                                 proximity_factor = proxDist / brush_radius;
03363                                 CLAMP(proximity_factor, 0.0f, 1.0f);
03364                                 if (!inner_proximity)
03365                                     proximity_factor = 1.0f - proximity_factor;
03366 
03367                                 hit_found = HIT_PROXIMITY;
03368 
03369                                 /* if no volume hit, use prox point face info */
03370                                 if (hitFace == -1) {
03371                                     copy_v3_v3(hitCoord, hitCo);
03372                                     hitQuad = hQuad;
03373                                     hitFace = face;
03374                                 }
03375                             }
03376                         }
03377 
03378                         /* mix final sample strength depending on brush settings */
03379                         if (hit_found) {
03380                             /* if "negate volume" enabled, negate all factors within volume*/
03381                             if (brush->collision == MOD_DPAINT_COL_VOLDIST && brush->flags & MOD_DPAINT_NEGATE_VOLUME) {
03382                                 volume_factor = 1.0f - volume_factor;
03383                                 if (inner_proximity)
03384                                     proximity_factor = 1.0f - proximity_factor;
03385                             }
03386 
03387                             /* apply final sample depending on final hit type */
03388                             if (hit_found == HIT_VOLUME) {
03389                                 sampleStrength = volume_factor;
03390                             }
03391                             else if (hit_found == HIT_PROXIMITY) {
03392                                 /* apply falloff curve to the proximity_factor */
03393                                 if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, (1.0f-proximity_factor), prox_colorband))
03394                                     proximity_factor = prox_colorband[3];
03395                                 else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_CONSTANT)
03396                                     proximity_factor = (!inner_proximity || brush->flags & MOD_DPAINT_NEGATE_VOLUME) ? 1.0f : 0.0f;
03397                                 /* apply sample */
03398                                 sampleStrength = proximity_factor;
03399                             }
03400 
03401                             sampleStrength *= sample_factor;
03402                         }
03403                         else continue;
03404 
03405                         /* velocity brush, only do on main sample */
03406                         if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss==0 && brushVelocity) {
03407                             int v1,v2,v3;
03408                             float weights[4];
03409                             float brushPointVelocity[3];
03410                             float velocity[3];
03411 
03412                             if (!hitQuad) {
03413                                 v1 = mface[hitFace].v1;
03414                                 v2 = mface[hitFace].v2;
03415                                 v3 = mface[hitFace].v3;
03416                             }
03417                             else {
03418                                 v1 = mface[hitFace].v2;
03419                                 v2 = mface[hitFace].v3;
03420                                 v3 = mface[hitFace].v4;
03421                             }
03422                             /* calculate barycentric weights for hit point */
03423                             interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
03424 
03425                             /* simple check based on brush surface velocity,
03426                             *  todo: perhaps implement something that handles volume movement as well */
03427                             
03428                             /* interpolate vertex speed vectors to get hit point velocity */    
03429                             interp_v3_v3v3v3(   brushPointVelocity,
03430                                                 brushVelocity[v1].v,
03431                                                 brushVelocity[v2].v,
03432                                                 brushVelocity[v3].v, weights);
03433 
03434                             /* substract canvas point velocity */
03435                             if (bData->velocity) {
03436                                 sub_v3_v3v3(velocity, brushPointVelocity, bData->velocity[index].v);
03437                             }
03438                             else {
03439                                 copy_v3_v3(velocity, brushPointVelocity);
03440                             }
03441                             velocity_val = len_v3(velocity);
03442 
03443                             /* if brush has smudge enabled store brush velocity */
03444                             if (surface->type == MOD_DPAINT_SURFACE_T_PAINT &&
03445                                 brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
03446                                 copy_v3_v3(&bData->brush_velocity[index*4], velocity);
03447                                 mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
03448                                 bData->brush_velocity[index*4+3] = velocity_val;
03449                             }
03450                         }
03451 
03452                         /*
03453                         *   Process hit color and alpha
03454                         */
03455                         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
03456                         {
03457                             float sampleColor[3];
03458                             float alpha_factor = 1.0f;
03459 
03460                             sampleColor[0] = brush->r;
03461                             sampleColor[1] = brush->g;
03462                             sampleColor[2] = brush->b;
03463                         
03464                             /* Get material+textures color on hit point if required */
03465                             if (brush_usesMaterial(brush, scene))
03466                                 dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]+ss].v, hitCoord, hitFace, hitQuad, brush->dm);
03467 
03468                             /* Sample proximity colorband if required   */
03469                             if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
03470                                 if (!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
03471                                     sampleColor[0] = prox_colorband[0];
03472                                     sampleColor[1] = prox_colorband[1];
03473                                     sampleColor[2] = prox_colorband[2];
03474                                 }
03475                             }
03476 
03477                             /* Add AA sample */
03478                             paintColor[0] += sampleColor[0];
03479                             paintColor[1] += sampleColor[1];
03480                             paintColor[2] += sampleColor[2];
03481                             sampleStrength *= alpha_factor;
03482                             numOfHits++;
03483                         }
03484 
03485                         /* apply sample strength */
03486                         brushStrength += sampleStrength;
03487                     } // end supersampling
03488 
03489 
03490                     /* if any sample was inside paint range */
03491                     if (brushStrength > 0.0f || depth > 0.0f) {
03492 
03493                         /* apply supersampling results  */
03494                         if (samples > 1) {
03495                             brushStrength /= total_sample;
03496                         }
03497                         CLAMP(brushStrength, 0.0f, 1.0f);
03498 
03499                         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
03500                             /* Get final pixel color and alpha  */
03501                             paintColor[0] /= numOfHits;
03502                             paintColor[1] /= numOfHits;
03503                             paintColor[2] /= numOfHits;
03504                         }
03505                         /* get final object space depth */
03506                         else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
03507                                 surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
03508                             depth /= bData->bNormal[index].normal_scale * total_sample;
03509                         }
03510                         
03511                         dynamicPaint_updatePointData(surface, index, brush, paintColor, brushStrength, depth, velocity_val, timescale);
03512                     }
03513                 }
03514             }
03515         }
03516         /* free bvh tree */
03517         free_bvhtree_from_mesh(&treeData);
03518         dm->release(dm);
03519 
03520     }
03521 
03522     /* free brush velocity data */
03523     if (brushVelocity)
03524         MEM_freeN(brushVelocity);
03525 
03526     return 1;
03527 }
03528 
03529 /*
03530 *   Paint a particle system to the surface
03531 */
03532 static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
03533                                        ParticleSystem *psys,
03534                                        DynamicPaintBrushSettings *brush,
03535                                        float timescale)
03536 {
03537     ParticleSettings *part=psys->part;
03538     ParticleData *pa = NULL;
03539     PaintSurfaceData *sData = surface->data;
03540     PaintBakeData *bData = sData->bData;
03541     VolumeGrid *grid = bData->grid; 
03542 
03543     KDTree *tree;
03544     int particlesAdded = 0;
03545     int invalidParticles = 0;
03546     int p = 0;
03547 
03548     float solidradius = surface->radius_scale*((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius);
03549     float smooth = brush->particle_smooth*surface->radius_scale;
03550 
03551     float range = solidradius + smooth;
03552     float particle_timestep = 0.04f * part->timetweak;
03553 
03554     Bounds3D part_bb = {0};
03555 
03556     if (psys->totpart < 1) return 1;
03557 
03558     /*
03559     *   Build a kd-tree to optimize distance search
03560     */
03561     tree= BLI_kdtree_new(psys->totpart);
03562 
03563     /* loop through particles and insert valid ones to the tree */
03564     for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)    {
03565 
03566         /* Proceed only if particle is active   */
03567         if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;                                 
03568         else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue;                                    
03569         else if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
03570 
03571         /*  for debug purposes check if any NAN particle proceeds
03572         *   For some reason they get past activity check, this should rule most of them out */
03573         if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) {invalidParticles++;continue;}
03574 
03575         /* make sure particle is close enough to canvas */
03576         if (!boundIntersectPoint(&grid->grid_bounds, pa->state.co, range)) continue;
03577 
03578         BLI_kdtree_insert(tree, p, pa->state.co, NULL);
03579 
03580         /* calc particle system bounds */
03581         boundInsert(&part_bb, pa->state.co);
03582 
03583         particlesAdded++;
03584     }
03585     if (invalidParticles)
03586         printf("Warning: Invalid particle(s) found!\n");
03587 
03588     /* If no suitable particles were found, exit    */
03589     if (particlesAdded < 1) {
03590         BLI_kdtree_free(tree);
03591         return 1;
03592     }
03593 
03594     /* begin thread safe malloc */
03595     BLI_begin_threaded_malloc();
03596 
03597     /* only continue if particle bb is close enough to canvas bb */
03598     if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range))
03599     {
03600         int c_index;
03601         int total_cells = grid->dim[0]*grid->dim[1]*grid->dim[2];
03602         
03603         /* balance tree */
03604         BLI_kdtree_balance(tree);
03605 
03606         /* loop through space partitioning grid */
03607         for (c_index=0; c_index<total_cells; c_index++) {
03608             int id;
03609 
03610             /* check cell bounding box */
03611             if (!grid->s_num[c_index] ||
03612                 !boundsIntersectDist(&grid->bounds[c_index], &part_bb, range))
03613                 continue;
03614 
03615             /* loop through cell points */
03616             #pragma omp parallel for schedule(static)
03617             for (id = 0; id < grid->s_num[c_index]; id++)
03618             {
03619                 int index = grid->t_index[grid->s_pos[c_index] + id];
03620                 float disp_intersect = 0.0f;
03621                 float radius = 0.0f;
03622                 float strength = 0.0f;
03623                 float velocity_val = 0.0f;
03624                 int part_index= -1;
03625 
03626                 /*
03627                 *   With predefined radius, there is no variation between particles.
03628                 *   It's enough to just find the nearest one.
03629                 */
03630                 {
03631                     KDTreeNearest nearest;
03632                     float smooth_range, part_solidradius;
03633 
03634                     /* Find nearest particle and get distance to it */
03635                     BLI_kdtree_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest);
03636                     /* if outside maximum range, no other particle can influence either */
03637                     if (nearest.dist > range) continue;
03638 
03639                     if (brush->flags & MOD_DPAINT_PART_RAD) {
03640                         /* use particles individual size */
03641                         ParticleData *pa = psys->particles + nearest.index;
03642                         part_solidradius = pa->size;
03643                     }
03644                     else {
03645                         part_solidradius = solidradius;
03646                     }
03647                     radius = part_solidradius + smooth;
03648                     if (nearest.dist < radius) {
03649                         /* distances inside solid radius has maximum influence -> dist = 0  */
03650                         smooth_range = (nearest.dist - part_solidradius);
03651                         if (smooth_range<0.0f) smooth_range=0.0f;
03652                         /* do smoothness if enabled */
03653                         if (smooth) smooth_range/=smooth;
03654 
03655                         strength = 1.0f - smooth_range;
03656                         disp_intersect = radius - nearest.dist;
03657                         part_index = nearest.index;
03658                     }
03659                 }
03660                 /* If using random per particle radius and closest particle didn't give max influence   */
03661                 if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) {
03662                     /*
03663                     *   If we use per particle radius, we have to sample all particles
03664                     *   within max radius range
03665                     */
03666                     KDTreeNearest *nearest;
03667 
03668                     int n, particles = 0;
03669                     float smooth_range = smooth * (1.0f-strength), dist;
03670                     /* calculate max range that can have particles with higher influence than the nearest one */
03671                     float max_range = smooth - strength*smooth + solidradius;
03672 
03673                     particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest);
03674 
03675                     /* Find particle that produces highest influence */
03676                     for(n=0; n<particles; n++) {
03677                         ParticleData *pa = psys->particles + nearest[n].index;
03678                         float s_range;
03679 
03680                         /* skip if out of range */
03681                         if (nearest[n].dist > (pa->size + smooth))
03682                             continue;
03683 
03684                         /* update hit data */
03685                         s_range = nearest[n].dist - pa->size;
03686                         /* skip if higher influence is already found */
03687                         if (smooth_range < s_range)
03688                             continue;
03689 
03690                         /* update hit data */
03691                         smooth_range = s_range;
03692                         dist = nearest[n].dist;
03693                         part_index = nearest[n].index;
03694 
03695                         /* If inside solid range and no disp depth required, no need to seek further */
03696                         if ( (s_range < 0.0f) &&
03697                              (surface->type != MOD_DPAINT_SURFACE_T_DISPLACE) &&
03698                              (surface->type != MOD_DPAINT_SURFACE_T_WAVE))
03699                         {
03700                             break;
03701                         }
03702                     }
03703 
03704                     if (nearest) MEM_freeN(nearest);
03705 
03706                     /* now calculate influence for this particle */
03707                     {
03708                         float rad = radius + smooth, str;
03709                         if ((rad-dist) > disp_intersect) {
03710                             disp_intersect = radius - dist;
03711                             radius = rad;
03712                         }
03713 
03714                         /* do smoothness if enabled */
03715                         if (smooth_range<0.0f) smooth_range=0.0f;
03716                         if (smooth) smooth_range/=smooth;
03717                         str = 1.0f - smooth_range;
03718                         /* if influence is greater, use this one    */
03719                         if (str > strength) strength = str;
03720                     }
03721                 }
03722 
03723                 if (strength > 0.001f)
03724                 {
03725                     float paintColor[4] = {0.0f};
03726                     float depth = 0.0f;
03727 
03728                     /* apply velocity */
03729                     if ((brush->flags & MOD_DPAINT_USES_VELOCITY) && (part_index != -1)) {
03730                         float velocity[3];
03731                         ParticleData *pa = psys->particles + part_index;
03732                         mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
03733 
03734                         /* substract canvas point velocity */
03735                         if (bData->velocity) {
03736                             sub_v3_v3(velocity, bData->velocity[index].v);
03737                         }
03738                         velocity_val = len_v3(velocity);
03739 
03740                         /* store brush velocity for smudge */
03741                         if ( (surface->type == MOD_DPAINT_SURFACE_T_PAINT) &&
03742                              (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity))
03743                         {
03744                             copy_v3_v3(&bData->brush_velocity[index*4], velocity);
03745                             mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
03746                             bData->brush_velocity[index*4+3] = velocity_val;
03747                         }
03748                     }
03749 
03750                     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
03751                         copy_v3_v3(paintColor, &brush->r);
03752                     }
03753                     else if ( (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) ||
03754                               (surface->type == MOD_DPAINT_SURFACE_T_WAVE))
03755                     {
03756                          /* get displace depth  */
03757                         disp_intersect = (1.0f - sqrtf(disp_intersect / radius)) * radius;
03758                         depth = (radius - disp_intersect) / bData->bNormal[index].normal_scale;
03759                         if (depth<0.0f) depth = 0.0f;
03760                     }
03761                     
03762                     dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
03763                 }
03764             }
03765         }
03766     }
03767     BLI_end_threaded_malloc();
03768     BLI_kdtree_free(tree);
03769 
03770     return 1;
03771 }
03772 
03773 /* paint a single point of defined proximity radius to the surface */
03774 static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
03775                                          Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
03776 {
03777     int index;
03778     float brush_radius = brush->paint_distance * surface->radius_scale;
03779     PaintSurfaceData *sData = surface->data;
03780     PaintBakeData *bData = sData->bData;
03781     Vec3f brushVel;
03782 
03783     if (brush->flags & MOD_DPAINT_USES_VELOCITY)
03784         dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale);
03785 
03786     /*
03787     *   Loop through every surface point
03788     */
03789     #pragma omp parallel for schedule(static)
03790     for (index = 0; index < sData->total_points; index++)
03791     {
03792         float distance = len_v3v3(pointCoord, bData->realCoord[bData->s_pos[index]].v);
03793         float colorband[4] = {0.0f};
03794         float strength;
03795 
03796         if (distance > brush_radius) continue;
03797 
03798         /* Smooth range or color ramp   */
03799         if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH ||
03800             brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) {
03801             
03802             strength = 1.0f - distance / brush_radius;
03803             CLAMP(strength, 0.0f, 1.0f);
03804         }
03805         else strength = 1.0f;
03806 
03807         if (strength >= 0.001f) {
03808             float paintColor[3] = {0.0f};
03809             float depth = 0.0f;
03810             float velocity_val = 0.0f;
03811 
03812             /* material */
03813             if (brush_usesMaterial(brush, scene)) {
03814                 float alpha_factor = 1.0f;
03815                 float hit_coord[3];
03816                 MVert *mvert = brush->dm->getVertArray(brush->dm);
03817                 /* use dummy coord of first vertex */
03818                 copy_v3_v3(hit_coord, mvert[0].co);
03819                 mul_m4_v3(brushOb->obmat, hit_coord);
03820 
03821                 dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm);
03822             }
03823 
03824             /* color ramp */
03825             if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, (1.0f-strength), colorband))
03826                 strength = colorband[3];
03827 
03828             if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
03829                 float velocity[3];
03830 
03831                 /* substract canvas point velocity */
03832                 if (bData->velocity) {
03833                     sub_v3_v3v3(velocity, brushVel.v, bData->velocity[index].v);
03834                 }
03835                 else {
03836                     copy_v3_v3(velocity, brushVel.v);
03837                 }
03838                 velocity_val = len_v3(velocity);
03839 
03840                 /* store brush velocity for smudge */
03841                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && 
03842                     brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
03843                     copy_v3_v3(&bData->brush_velocity[index*4], velocity);
03844                     mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
03845                     bData->brush_velocity[index*4+3] = velocity_val;
03846                 }
03847             }
03848 
03849             if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
03850                 if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
03851                     !(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
03852                     paintColor[0] = colorband[0];
03853                     paintColor[1] = colorband[1];
03854                     paintColor[2] = colorband[2];
03855                 }
03856                 else {
03857                     if (!brush_usesMaterial(brush, scene)) {
03858                         paintColor[0] = brush->r;
03859                         paintColor[1] = brush->g;
03860                         paintColor[2] = brush->b;
03861                     }
03862                 }
03863             }
03864             else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
03865                      surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
03866                  /* get displace depth  */
03867                 float disp_intersect = (1.0f - sqrtf((brush_radius-distance) / brush_radius)) * brush_radius;
03868                 depth = (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale;
03869                 if (depth<0.0f) depth = 0.0f;
03870             }
03871             dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
03872         }
03873     }
03874 
03875     return 1;
03876 }
03877 
03878 
03879 /***************************** Dynamic Paint Step / Baking ******************************/
03880 
03881 /*
03882 *   Calculate current frame neighbouring point distances
03883 *   and direction vectors
03884 */
03885 static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int force_init)
03886 {
03887     PaintSurfaceData *sData = surface->data;
03888     PaintBakeData *bData = sData->bData;
03889     BakeNeighPoint *bNeighs;
03890     PaintAdjData *adj_data = sData->adj_data;
03891     Vec3f *realCoord = bData->realCoord;
03892     int index;
03893 
03894     if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return;
03895 
03896     if (bData->bNeighs) MEM_freeN(bData->bNeighs);
03897     bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint),"PaintEffectBake");
03898     if (!bNeighs) return;
03899 
03900     #pragma omp parallel for schedule(static)
03901     for (index = 0; index < sData->total_points; index++)
03902     {
03903         int i;
03904         int numOfNeighs = adj_data->n_num[index];
03905 
03906         for (i=0; i<numOfNeighs; i++) {
03907             int n_index = adj_data->n_index[index]+i;
03908             int t_index = adj_data->n_target[n_index];
03909 
03910             /* dir vec */
03911             sub_v3_v3v3(bNeighs[n_index].dir, realCoord[bData->s_pos[t_index]].v, realCoord[bData->s_pos[index]].v);
03912             /* dist */
03913             bNeighs[n_index].dist = len_v3(bNeighs[n_index].dir);
03914             /* normalize dir */
03915             if (bNeighs[n_index].dist) mul_v3_fl(bNeighs[n_index].dir, 1.0f/bNeighs[n_index].dist);
03916         }
03917     }
03918 
03919     /* calculate average values (single thread) */
03920     bData->average_dist = 0.0f;
03921     for (index = 0; index < sData->total_points; index++)
03922     {
03923         int i;
03924         int numOfNeighs = adj_data->n_num[index];
03925 
03926         for (i=0; i<numOfNeighs; i++) {
03927             bData->average_dist += (double)bNeighs[adj_data->n_index[index]+i].dist;
03928         }
03929     }
03930     bData->average_dist  /= adj_data->total_targets;
03931 }
03932 
03933 /* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force  */
03934 void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2])
03935 {
03936     BakeNeighPoint *bNeighs = sData->bData->bNeighs;
03937     int numOfNeighs = sData->adj_data->n_num[index];
03938     int i;
03939 
03940     closest_id[0]=closest_id[1]= -1;
03941     closest_d[0]=closest_d[1]= -1.0f;
03942 
03943     /* find closest neigh */
03944     for (i=0; i<numOfNeighs; i++) {
03945         int n_index = sData->adj_data->n_index[index]+i;
03946         float dir_dot = dot_v3v3(bNeighs[n_index].dir, force);
03947 
03948         if (dir_dot>closest_d[0] && dir_dot>0.0f) {closest_d[0]=dir_dot; closest_id[0]=n_index;}
03949     }
03950 
03951     if (closest_d[0] < 0.0f) return;
03952 
03953     /* find second closest neigh */
03954     for (i=0; i<numOfNeighs; i++) {
03955         int n_index = sData->adj_data->n_index[index]+i;
03956         float dir_dot = dot_v3v3(bNeighs[n_index].dir, force);
03957         float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
03958 
03959         if (n_index == closest_id[0]) continue;
03960 
03961         /* only accept neighbour at "other side" of the first one in relation to force dir
03962         *  so make sure angle between this and closest neigh is greater than first angle */
03963         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;}
03964     }
03965 
03966     /* if two valid neighs found, calculate how force effect is divided
03967     *  evenly between them (so that d[0]+d[1] = 1.0)*/
03968     if (closest_id[1] != -1) {
03969         float force_proj[3];
03970         float tangent[3];
03971         float neigh_diff = acosf(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
03972         float force_intersect;
03973         float temp;
03974 
03975         /* project force vector on the plane determined by these two neightbour points
03976         *  and calculate relative force angle from it*/
03977         cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
03978         normalize_v3(tangent);
03979         force_intersect = dot_v3v3(force, tangent);
03980         madd_v3_v3v3fl(force_proj, force, tangent, (-1.0f)*force_intersect);
03981         normalize_v3(force_proj);
03982 
03983         /* get drip factor based on force dir in relation to angle between those neighbours */
03984         temp = dot_v3v3(bNeighs[closest_id[0]].dir, force_proj);
03985         CLAMP(temp, -1.0f, 1.0f); /* float precision might cause values > 1.0f that return infinite */
03986         closest_d[1] = acosf(temp)/neigh_diff;
03987         closest_d[0] = 1.0f - closest_d[1];
03988 
03989         /* and multiply depending on how deeply force intersects surface */
03990         temp = fabs(force_intersect);
03991         CLAMP(temp, 0.0f, 1.0f);
03992         closest_d[0] *= acosf(temp)/1.57079633f;
03993         closest_d[1] *= acosf(temp)/1.57079633f;
03994     }
03995     else {
03996         /* if only single neighbour, still linearize force intersection effect */
03997         closest_d[0] = 1.0f - acosf(closest_d[0])/1.57079633f;
03998     }
03999 }
04000 
04001 static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, float timescale)
04002 {
04003     PaintSurfaceData *sData = surface->data;
04004     PaintBakeData *bData = sData->bData;
04005     BakeNeighPoint *bNeighs = sData->bData->bNeighs;
04006     int index, steps, step;
04007     float eff_scale, max_velocity = 0.0f;
04008 
04009     if (!sData->adj_data) return;
04010 
04011     /* find max velocity */
04012     for (index = 0; index < sData->total_points; index++) {
04013         float vel = bData->brush_velocity[index*4+3];
04014         if (vel > max_velocity) max_velocity = vel;
04015     }
04016 
04017     steps = (int)ceil(max_velocity / bData->average_dist * timescale);
04018     CLAMP(steps, 0, 12);
04019     eff_scale = brush->smudge_strength/(float)steps*timescale;
04020 
04021     for (step=0; step<steps; step++) {
04022 
04023         for (index = 0; index < sData->total_points; index++) {
04024             int i;
04025             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
04026             float smudge_str = bData->brush_velocity[index*4+3];
04027 
04028             /* force targets */
04029             int closest_id[2];
04030             float closest_d[2];
04031 
04032             if (!smudge_str) continue;
04033             
04034             /* get force affect points */
04035             surface_determineForceTargetPoints(sData, index, &bData->brush_velocity[index*4], closest_d, closest_id);
04036 
04037             /* Apply movement towards those two points */
04038             for (i=0; i<2; i++) {
04039                 int n_index = closest_id[i];
04040                 if (n_index != -1 && closest_d[i]>0.0f) {
04041                     float dir_dot = closest_d[i], dir_factor;
04042                     float speed_scale = eff_scale*smudge_str/bNeighs[n_index].dist;
04043                     PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
04044 
04045                     /* just skip if angle is too extreme */
04046                     if (dir_dot <= 0.0f) continue;
04047 
04048                     dir_factor = dir_dot * speed_scale;
04049                     if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength;
04050 
04051                     /* mix new color and alpha */
04052                     mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor);
04053                     ePoint->alpha = ePoint->alpha*(1.0f-dir_factor) + pPoint->alpha*dir_factor;
04054 
04055                     /* smudge "wet layer" */
04056                     mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor);
04057                     ePoint->e_alpha = ePoint->e_alpha*(1.0f-dir_factor) + pPoint->e_alpha*dir_factor;
04058                     pPoint->wetness *= (1.0f-dir_factor);
04059                 }
04060             }
04061         }
04062     }
04063 }
04064 
04065 /*
04066 *   Prepare data required by effects for current frame.
04067 *   Returns number of steps required
04068 */
04069 static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
04070 {
04071     double average_force = 0.0f;
04072     float shrink_speed=0.0f, spread_speed=0.0f;
04073     float fastest_effect, avg_dist;
04074     int steps;
04075     PaintSurfaceData *sData = surface->data;
04076     PaintBakeData *bData = sData->bData;
04077     Vec3f *realCoord = bData->realCoord;
04078     int index;
04079 
04080     /* Init force data if required */
04081     if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
04082         float vel[3] = {0};
04083         ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights);
04084 
04085         /* allocate memory for force data (dir vector + strength) */
04086         *force = MEM_mallocN(sData->total_points*4*sizeof(float), "PaintEffectForces");
04087 
04088         if (*force) {
04089             #pragma omp parallel for schedule(static)
04090             for (index = 0; index < sData->total_points; index++)
04091             {
04092                 float forc[3] = {0};
04093 
04094                 /* apply force fields */
04095                 if (effectors) {
04096                     EffectedPoint epoint;
04097                     pd_point_from_loc(scene, realCoord[bData->s_pos[index]].v, vel, index, &epoint);
04098                     epoint.vel_to_sec = 1.0f;
04099                     pdDoEffectors(effectors, NULL, surface->effector_weights, &epoint, forc, NULL);
04100                 }
04101 
04102                 /* if global gravity is enabled, add it too */
04103                 if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)
04104                     /* also divide by 10 to about match default grav
04105                     *  with default force strength (1.0) */
04106                     madd_v3_v3fl(forc, scene->physics_settings.gravity, 
04107                                 surface->effector_weights->global_gravity*surface->effector_weights->weight[0] / 10.f);
04108 
04109                 /* add surface point velocity and acceleration if enabled */
04110                 if (bData->velocity) {
04111                     if (surface->drip_vel)
04112                         madd_v3_v3fl(forc, bData->velocity[index].v, surface->drip_vel*(-1.0f));
04113 
04114                     /* acceleration */
04115                     if (bData->prev_velocity && surface->drip_acc) {
04116                         float acc[3];
04117                         copy_v3_v3(acc, bData->velocity[index].v);
04118                         sub_v3_v3(acc, bData->prev_velocity[index].v);
04119                         madd_v3_v3fl(forc, acc, surface->drip_acc*(-1.0f));
04120                     }
04121                 }
04122 
04123                 /* force strength */
04124                 (*force)[index*4+3] = len_v3(forc);
04125                 /* normalize and copy */
04126                 if ((*force)[index*4+3]) mul_v3_fl(forc, 1.0f/(*force)[index*4+3]);
04127                 copy_v3_v3(&((*force)[index*4]), forc);
04128             }
04129 
04130             /* calculate average values (single thread) */
04131             for (index = 0; index < sData->total_points; index++)
04132             {
04133                 average_force += (*force)[index*4+3];
04134             }
04135             average_force /= sData->total_points;
04136         }
04137         pdEndEffectors(&effectors);
04138     }
04139 
04140     /* Get number of required steps using averate point distance
04141     *  so that just a few ultra close pixels wont up substeps to max */
04142 
04143     /* adjust number of required substep by fastest active effect */
04144     if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD)
04145         spread_speed = surface->spread_speed;
04146     if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK)
04147         shrink_speed = surface->shrink_speed;
04148 
04149     fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
04150     avg_dist = bData->average_dist*CANVAS_REL_SIZE/getSurfaceDimension(sData);
04151 
04152     steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/avg_dist*timescale);
04153     CLAMP(steps, 1, 20);
04154 
04155     return steps;
04156 }
04157 
04158 /*
04159 *   Processes active effect step.
04160 */
04161 static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps)
04162 {
04163     PaintSurfaceData *sData = surface->data;
04164     BakeNeighPoint *bNeighs = sData->bData->bNeighs;
04165     float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE;
04166     int index;
04167     timescale /= steps;
04168 
04169     if (!sData->adj_data) return;
04170 
04171     /*
04172     *   Spread Effect
04173     */
04174     if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD)  {
04175         float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale;
04176 
04177         /* Copy current surface to the previous points array to read unmodified values  */
04178         memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
04179 
04180         #pragma omp parallel for schedule(static)
04181         for (index = 0; index < sData->total_points; index++)
04182         {
04183             int i;
04184             int numOfNeighs = sData->adj_data->n_num[index];
04185             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
04186 
04187             /*  Only reads values from the surface copy (prevPoint[]),
04188             *   so this one is thread safe */
04189 
04190             /*  Loop through neighbouring points    */
04191             for (i=0; i<numOfNeighs; i++) {
04192                 int n_index = sData->adj_data->n_index[index]+i;
04193                 float w_factor /* , p_alpha = pPoint->e_alpha */ /* UNUSED */;
04194                 PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
04195                 float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
04196                 float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed;
04197 
04198                 /* do color mixing */
04199                 if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix);
04200 
04201                 /* Only continue if surrounding point has higher wetness */
04202                 if (ePoint->wetness<pPoint->wetness || ePoint->wetness<MIN_WETNESS) continue;
04203 
04204                 w_factor = 1.0f/numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale;
04205                 CLAMP(w_factor, 0.0f, 1.0f);
04206 
04207                 /* mix new wetness and color */
04208                 pPoint->wetness = (1.0f-w_factor)*pPoint->wetness + w_factor*ePoint->wetness;
04209                 pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor);
04210             }
04211         }
04212     }
04213 
04214     /*
04215     *   Shrink Effect
04216     */
04217     if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK)  {
04218         float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale;
04219 
04220         /* Copy current surface to the previous points array to read unmodified values  */
04221         memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
04222 
04223         #pragma omp parallel for schedule(static)
04224         for (index = 0; index < sData->total_points; index++)
04225         {
04226             int i;
04227             int numOfNeighs = sData->adj_data->n_num[index];
04228             float totalAlpha = 0.0f;
04229             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
04230 
04231             for (i=0; i<numOfNeighs; i++) {
04232                 int n_index = sData->adj_data->n_index[index]+i;
04233                 float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
04234                 PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
04235                 float a_factor, ea_factor, w_factor;
04236 
04237                 totalAlpha += ePoint->e_alpha;
04238 
04239                 /* Check if neighbouring point has lower alpha,
04240                 *  if so, decrease this point's alpha as well*/
04241                 if (pPoint->alpha <= 0.0f && pPoint->e_alpha <= 0.0f && pPoint->wetness <= 0.0f) continue;
04242 
04243                 /* decrease factor for dry paint alpha */
04244                 a_factor = (1.0f - ePoint->alpha)/numOfNeighs * (pPoint->alpha - ePoint->alpha) * speed_scale;
04245                 if (a_factor < 0.0f) a_factor = 0.0f;
04246                 /* decrease factor for wet paint alpha */
04247                 ea_factor = (1.0f - ePoint->e_alpha)/8 * (pPoint->e_alpha - ePoint->e_alpha) * speed_scale;
04248                 if (ea_factor < 0.0f) ea_factor = 0.0f;
04249                 /* decrease factor for paint wetness */
04250                 w_factor = (1.0f - ePoint->wetness)/8 * (pPoint->wetness - ePoint->wetness) * speed_scale;
04251                 if (w_factor < 0.0f) w_factor = 0.0f;
04252 
04253                 pPoint->alpha -= a_factor;
04254                 if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
04255                 pPoint->e_alpha -= ea_factor;
04256                 if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
04257                 pPoint->wetness -= w_factor;
04258                 if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f;
04259             }
04260         }
04261     }
04262 
04263     /*
04264     *   Drip Effect
04265     */
04266     if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) 
04267     {
04268         float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*timescale/2.0f;
04269         /* Copy current surface to the previous points array to read unmodified values  */
04270         memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
04271 
04272         for (index = 0; index < sData->total_points; index++) {
04273             int i;
04274             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
04275             PaintPoint *pPoint_prev = &prevPoint[index];
04276 
04277             int closest_id[2];
04278             float closest_d[2];
04279 
04280             /* adjust drip speed depending on wetness */
04281             float w_factor = pPoint_prev->wetness - 0.025f;
04282             if (w_factor <= 0) continue;
04283             CLAMP(w_factor, 0.0f, 1.0f);
04284 
04285             /* get force affect points */
04286             surface_determineForceTargetPoints(sData, index, &force[index*4], closest_d, closest_id);
04287 
04288             /* Apply movement towards those two points */
04289             for (i=0; i<2; i++) {
04290                 int n_index = closest_id[i];
04291                 if (n_index != -1 && closest_d[i]>0.0f) {
04292                     float dir_dot = closest_d[i], dir_factor, a_factor;
04293                     float speed_scale = eff_scale*force[index*4+3]/bNeighs[n_index].dist;
04294                     PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
04295                     float e_wet = ePoint->wetness;
04296 
04297                     /* just skip if angle is too extreme */
04298                     if (dir_dot <= 0.0f) continue;
04299 
04300                     dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor;
04301                     if (dir_factor > 0.5f) dir_factor = 0.5f;
04302 
04303                     /* mix new wetness*/
04304                     ePoint->wetness += dir_factor;
04305                     CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS);
04306 
04307                     /* mix new color */
04308                     a_factor = dir_factor / pPoint_prev->wetness;
04309                     CLAMP(a_factor, 0.0f, 1.0f);
04310                     mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor);
04311                     /* dripping is supposed to preserve alpha level */
04312                     if (pPoint_prev->e_alpha > ePoint->e_alpha) {
04313                         ePoint->e_alpha += a_factor * pPoint_prev->e_alpha;
04314                         if (ePoint->e_alpha > pPoint_prev->e_alpha)
04315                             ePoint->e_alpha = pPoint_prev->e_alpha;
04316                     }
04317 
04318                     /* decrease paint wetness on current point */
04319                     pPoint->wetness -= (ePoint->wetness - e_wet);
04320                     CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
04321                 }
04322             }
04323         }
04324     }
04325 }
04326 
04327 void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
04328 {
04329     PaintSurfaceData *sData = surface->data;
04330     BakeNeighPoint *bNeighs = sData->bData->bNeighs;
04331     int index;
04332     int steps, ss;
04333     float dt, min_dist, damp_factor;
04334     float wave_speed = surface->wave_speed;
04335     double average_dist = 0.0f;
04336     Bounds3D *mb = &sData->bData->mesh_bounds;
04337     float canvas_size = MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
04338     float wave_scale = CANVAS_REL_SIZE/canvas_size;
04339 
04340     /* allocate memory */
04341     PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points*sizeof(PaintWavePoint), "Temp previous points for wave simulation");
04342     if (!prevPoint) return;
04343 
04344     /* calculate average neigh distance (single thread) */
04345     for (index = 0; index < sData->total_points; index++)
04346     {
04347         int i;
04348         int numOfNeighs = sData->adj_data->n_num[index];
04349 
04350         for (i=0; i<numOfNeighs; i++) {
04351             average_dist += bNeighs[sData->adj_data->n_index[index]+i].dist;
04352         }
04353     }
04354     average_dist  *= wave_scale/sData->adj_data->total_targets;
04355 
04356     /* determine number of required steps */
04357     steps = (int)ceil((WAVE_TIME_FAC*timescale*surface->wave_timescale) / (average_dist/wave_speed/3));
04358     CLAMP(steps, 1, 20);
04359     timescale /= steps;
04360 
04361     /* apply simulation values for final timescale */
04362     dt = WAVE_TIME_FAC*timescale*surface->wave_timescale;
04363     min_dist = wave_speed*dt*1.5f;
04364     damp_factor = pow((1.0f-surface->wave_damping), timescale*surface->wave_timescale);
04365 
04366     for (ss=0; ss<steps; ss++) {
04367 
04368         /* copy previous frame data */
04369         memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(PaintWavePoint));
04370 
04371         #pragma omp parallel for schedule(static)
04372         for (index = 0; index < sData->total_points; index++) {
04373             PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
04374             int numOfNeighs = sData->adj_data->n_num[index];
04375             float force = 0.0f, avg_dist = 0.0f, avg_height = 0.0f;
04376             int numOfN = 0, numOfRN = 0;
04377             int i;
04378 
04379             if (wPoint->state > 0) continue;
04380 
04381             /* calculate force from surrounding points */
04382             for (i=0; i<numOfNeighs; i++) {
04383                 int n_index = sData->adj_data->n_index[index]+i;
04384                 float dist = bNeighs[n_index].dist*wave_scale;
04385                 PaintWavePoint *tPoint = &prevPoint[sData->adj_data->n_target[n_index]];
04386 
04387                 if (!dist || tPoint->state>0) continue;
04388                 if (dist<min_dist) dist=min_dist;
04389                 avg_dist += dist;
04390                 numOfN++;
04391 
04392                 /* count average height for edge points for open borders */
04393                 if (!(sData->adj_data->flags[sData->adj_data->n_target[n_index]] & ADJ_ON_MESH_EDGE)) {
04394                     avg_height += tPoint->height;
04395                     numOfRN++;
04396                 }
04397 
04398                 force += (tPoint->height - wPoint->height) / (dist*dist);
04399             }
04400             avg_dist = (numOfN) ? avg_dist/numOfN : 0.0f;
04401 
04402             if (surface->flags & MOD_DPAINT_WAVE_OPEN_BORDERS &&
04403                 sData->adj_data->flags[index] & ADJ_ON_MESH_EDGE) {
04404                 /* if open borders, apply a fake height to keep waves going on */
04405                 avg_height = (numOfRN) ? avg_height/numOfRN : 0.0f;
04406                 wPoint->height = (dt*wave_speed*avg_height + wPoint->height*avg_dist) / (avg_dist + dt*wave_speed);
04407             }
04408             /* else do wave eq */
04409             else {
04410                 /* add force towards zero height based on average dist */
04411                 if (avg_dist)
04412                     force += (0.0f - wPoint->height) * surface->wave_spring / (avg_dist*avg_dist) / 2.0f;
04413 
04414                 /* change point velocity */
04415                 wPoint->velocity += force*dt * wave_speed*wave_speed;
04416                 /* damping */
04417                 wPoint->velocity *= damp_factor;
04418                 /* and new height */
04419                 wPoint->height += wPoint->velocity*dt;
04420             }
04421         }
04422     }
04423 
04424     /* reset state */
04425     #pragma omp parallel for schedule(static)
04426     for (index = 0; index < sData->total_points; index++) {
04427         PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
04428         /* if there wasnt any brush intersection, clear isect height */
04429         if (wPoint->state == DPAINT_WAVE_NONE) {
04430             wPoint->brush_isect = 0.0f;
04431         }
04432         wPoint->state = DPAINT_WAVE_NONE;
04433     }
04434 
04435     MEM_freeN(prevPoint);
04436 }
04437 
04438 /* Do dissolve and fading effects */
04439 static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float timescale)
04440 {
04441     PaintSurfaceData *sData = surface->data;
04442     int index;
04443 
04444     #pragma omp parallel for schedule(static)
04445     for (index=0; index<sData->total_points; index++)
04446     {
04447         /* Do drying dissolve effects */
04448         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
04449             PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
04450             /* drying */
04451             if (surface->flags & MOD_DPAINT_USE_DRYING) {
04452                 if (pPoint->wetness >= MIN_WETNESS) {
04453                     int i;
04454                     float dry_ratio, f_color[4];
04455                     float p_wetness = pPoint->wetness;
04456                     VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG));
04457                     if (pPoint->wetness<0.0f) pPoint->wetness=0.0f;
04458 
04459                     if (pPoint->wetness < surface->color_dry_threshold) {
04460                         dry_ratio = pPoint->wetness/p_wetness;
04461 
04462                         /*
04463                         *   Slowly "shift" paint from wet layer to dry layer as it drys:
04464                         */
04465                         /* make sure alpha values are within proper range */
04466                         CLAMP(pPoint->alpha, 0.0f, 1.0f);
04467                         CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
04468 
04469                         /* get current final blended color of these layers */
04470                         blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
04471                         /* reduce wet layer alpha by dry factor */
04472                         pPoint->e_alpha *= dry_ratio;
04473 
04474                         /* now calculate new alpha for dry layer that keeps final blended color unchanged */
04475                         pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha);
04476                         /* for each rgb component, calculate a new dry layer color that keeps the final blend color
04477                         *  with these new alpha values. (wet layer color doesnt change)*/
04478                         if (pPoint->alpha) {
04479                             for (i=0; i<3; i++) {
04480                                 pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha));
04481                             }
04482                         }
04483                     }
04484 
04485                     pPoint->state = DPAINT_PAINT_WET;
04486                 }
04487                 /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
04488                 else if (pPoint->state > 0) {
04489                     float f_color[4];
04490                     blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
04491                     copy_v3_v3(pPoint->color, f_color);
04492                     pPoint->alpha = f_color[3];
04493                     /* clear wet layer */
04494                     pPoint->wetness = 0.0f;
04495                     pPoint->e_alpha = 0.0f;
04496                     pPoint->state = DPAINT_PAINT_DRY;
04497                 }
04498             }
04499 
04500             if (surface->flags & MOD_DPAINT_DISSOLVE) {
04501                 VALUE_DISSOLVE(pPoint->alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
04502                 if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
04503 
04504                 VALUE_DISSOLVE(pPoint->e_alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
04505                 if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
04506             }
04507         }
04508         /* dissolve for float types */
04509         else if (surface->flags & MOD_DPAINT_DISSOLVE &&
04510                 (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
04511                  surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)) {
04512 
04513             float *point = &((float*)sData->type_data)[index];
04514             /* log or linear */
04515             VALUE_DISSOLVE(*point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG));
04516             if (*point < 0.0f) *point = 0.0f;
04517         }
04518     }
04519 }
04520 
04521 static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob)
04522 {
04523     PaintSurfaceData *sData = surface->data;
04524     PaintBakeData *bData = sData->bData;
04525     DerivedMesh *dm = surface->canvas->dm;
04526     MVert *mvert = dm->getVertArray(dm);
04527 
04528     int numOfVerts = dm->getNumVerts(dm);
04529     int i;
04530     int ret = 0;
04531 
04532     if (!bData->prev_verts) return 1;
04533 
04534     /* matrix comparison */
04535     for (i=0; i<4; i++) {
04536         int j;
04537         for (j=0; j<4; j++)
04538         if (bData->prev_obmat[i][j] != ob->obmat[i][j]) return 1;
04539     }
04540 
04541     /* vertices */
04542     #pragma omp parallel for schedule(static)
04543     for (i=0; i<numOfVerts; i++) {
04544         int j;
04545         for (j=0; j<3; j++)
04546             if (bData->prev_verts[i].co[j] != mvert[i].co[j]) {
04547                 ret = 1;
04548                 break;
04549             }
04550     }
04551 
04552     return ret;
04553 }
04554 
04555 static int surface_needsVelocityData(DynamicPaintSurface *surface, Scene *scene)
04556 {
04557     if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP)
04558         return 1;
04559 
04560     if (surface_getBrushFlags(surface, scene) & BRUSH_USES_VELOCITY)
04561         return 1;
04562 
04563     return 0;
04564 }
04565 
04566 static int surface_needsAccelerationData(DynamicPaintSurface *surface)
04567 {
04568     if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP)
04569         return 1;
04570 
04571     return 0;
04572 }
04573 
04574 /* Prepare for surface step by creating PaintBakeNormal data */
04575 static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *scene, Object *ob)
04576 {
04577     PaintSurfaceData *sData = surface->data;
04578     PaintAdjData *adj_data = sData->adj_data;
04579     PaintBakeData *bData = sData->bData;
04580     DerivedMesh *dm = surface->canvas->dm;
04581     int index, new_bdata = 0;
04582     int do_velocity_data = surface_needsVelocityData(surface, scene);
04583     int do_accel_data = surface_needsAccelerationData(surface);
04584 
04585     int canvasNumOfVerts = dm->getNumVerts(dm);
04586     MVert *mvert = dm->getVertArray(dm);
04587     Vec3f *canvas_verts;
04588 
04589     if (bData) {
04590         int surface_moved = dynamicPaint_surfaceHasMoved(surface, ob);
04591 
04592         /* get previous speed for accelertaion */
04593         if (do_accel_data && bData->prev_velocity && bData->velocity)
04594             memcpy(bData->prev_velocity, bData->velocity, sData->total_points*sizeof(Vec3f));
04595 
04596         /* reset speed vectors */
04597         if (do_velocity_data && bData->velocity && (bData->clear || !surface_moved))
04598             memset(bData->velocity, 0, sData->total_points*sizeof(Vec3f));
04599 
04600         /* if previous data exists and mesh hasn't moved, no need to recalc */
04601         if (!surface_moved)
04602             return 1;
04603     }
04604 
04605     canvas_verts = (struct Vec3f *) MEM_mallocN(canvasNumOfVerts*sizeof(struct Vec3f), "Dynamic Paint transformed canvas verts");
04606     if (!canvas_verts) return 0;
04607 
04608     /* allocate memory if required */
04609     if (!bData) {
04610         sData->bData = bData = (struct PaintBakeData *) MEM_callocN(sizeof(struct PaintBakeData), "Dynamic Paint bake data");
04611         if (!bData) {
04612             if (canvas_verts) MEM_freeN(canvas_verts);
04613             return 0;
04614         }
04615 
04616         /* Init bdata */
04617         bData->bNormal = (struct PaintBakeNormal *) MEM_mallocN(sData->total_points*sizeof(struct PaintBakeNormal), "Dynamic Paint step data");
04618         bData->s_pos = MEM_mallocN(sData->total_points*sizeof(unsigned int), "Dynamic Paint bData s_pos");
04619         bData->s_num = MEM_mallocN(sData->total_points*sizeof(unsigned int), "Dynamic Paint bData s_num");
04620         bData->realCoord = (struct Vec3f *) MEM_mallocN(surface_totalSamples(surface)*sizeof(Vec3f), "Dynamic Paint point coords");
04621         bData->prev_verts = MEM_mallocN(canvasNumOfVerts*sizeof(MVert), "Dynamic Paint bData prev_verts");
04622 
04623         /* if any allocation failed, free everything */
04624         if (!bData->bNormal || !bData->s_pos || !bData->s_num || !bData->realCoord || !canvas_verts) {
04625             if (bData->bNormal) MEM_freeN(bData->bNormal);
04626             if (bData->s_pos) MEM_freeN(bData->s_pos);
04627             if (bData->s_num) MEM_freeN(bData->s_num);
04628             if (bData->realCoord) MEM_freeN(bData->realCoord);
04629             if (canvas_verts) MEM_freeN(canvas_verts);
04630 
04631             return setError(surface->canvas, "Not enough free memory.");
04632         }
04633 
04634         new_bdata = 1;
04635     }
04636 
04637     if (do_velocity_data && !bData->velocity) {
04638         bData->velocity = (struct Vec3f *) MEM_callocN(sData->total_points*sizeof(Vec3f), "Dynamic Paint velocity");
04639     }
04640     if (do_accel_data && !bData->prev_velocity) {
04641         bData->prev_velocity = (struct Vec3f *) MEM_mallocN(sData->total_points*sizeof(Vec3f), "Dynamic Paint prev velocity");
04642         /* copy previous vel */
04643         if (bData->prev_velocity && bData->velocity)
04644             memcpy(bData->prev_velocity, bData->velocity, sData->total_points*sizeof(Vec3f));
04645     }
04646 
04647     /*
04648     *   Make a transformed copy of canvas derived mesh vertices to avoid recalculation.
04649     */
04650     bData->mesh_bounds.valid = 0;
04651     for (index=0; index<canvasNumOfVerts; index++) {
04652         copy_v3_v3(canvas_verts[index].v, mvert[index].co);
04653         mul_m4_v3(ob->obmat, canvas_verts[index].v);
04654         boundInsert(&bData->mesh_bounds, canvas_verts[index].v);
04655     }
04656 
04657     /*
04658     *   Prepare each surface point for a new step
04659     */
04660     #pragma omp parallel for schedule(static)
04661     for (index=0; index<sData->total_points; index++)
04662     {
04663         float prev_point[3] = {0.0f, 0.0f, 0.0f};
04664         if (do_velocity_data && !new_bdata) {
04665             copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v);
04666         }
04667         /*
04668         *   Calculate current 3D-position and normal of each surface point
04669         */
04670         if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
04671             float n1[3], n2[3], n3[3];
04672             ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
04673             PaintUVPoint *tPoint = &((PaintUVPoint*)f_data->uv_p)[index];
04674             int ss;
04675 
04676             bData->s_num[index] = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
04677             bData->s_pos[index] = index * bData->s_num[index];
04678 
04679             /* per sample coordinates */
04680             for (ss=0; ss<bData->s_num[index]; ss++) {
04681                 interp_v3_v3v3v3(   bData->realCoord[bData->s_pos[index]+ss].v,
04682                     canvas_verts[tPoint->v1].v,
04683                     canvas_verts[tPoint->v2].v,
04684                     canvas_verts[tPoint->v3].v, f_data->barycentricWeights[index*bData->s_num[index]+ss].v);
04685             }
04686 
04687             /* Calculate current pixel surface normal   */
04688             normal_short_to_float_v3(n1, mvert[tPoint->v1].no);
04689             normal_short_to_float_v3(n2, mvert[tPoint->v2].no);
04690             normal_short_to_float_v3(n3, mvert[tPoint->v3].no);
04691 
04692             interp_v3_v3v3v3(   bData->bNormal[index].invNorm,
04693                 n1, n2, n3, f_data->barycentricWeights[index*bData->s_num[index]].v);
04694             mul_mat3_m4_v3(ob->obmat, bData->bNormal[index].invNorm);
04695             normalize_v3(bData->bNormal[index].invNorm);
04696             negate_v3(bData->bNormal[index].invNorm);
04697         }
04698         else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
04699             int ss;
04700             if (surface->flags & MOD_DPAINT_ANTIALIAS && adj_data) {
04701                 bData->s_num[index] = adj_data->n_num[index]+1;
04702                 bData->s_pos[index] = adj_data->n_index[index]+index;
04703             }
04704             else {
04705                 bData->s_num[index] = 1;
04706                 bData->s_pos[index] = index;
04707             }
04708 
04709             /* calculate position for each sample */
04710             for (ss=0; ss<bData->s_num[index]; ss++) {
04711                 /* first sample is always point center */
04712                 copy_v3_v3(bData->realCoord[bData->s_pos[index]+ss].v, canvas_verts[index].v);
04713                 if (ss > 0) {
04714                     int t_index = adj_data->n_index[index]+(ss-1);
04715                     /* get vertex position at 1/3 of each neigh edge */
04716                     mul_v3_fl(bData->realCoord[bData->s_pos[index]+ss].v, 2.0f/3.0f);
04717                     madd_v3_v3fl(bData->realCoord[bData->s_pos[index]+ss].v, canvas_verts[adj_data->n_target[t_index]].v, 1.0f/3.0f);
04718                 }
04719             }
04720 
04721             /* normal */
04722             normal_short_to_float_v3(bData->bNormal[index].invNorm, mvert[index].no);
04723             mul_mat3_m4_v3(ob->obmat, bData->bNormal[index].invNorm);
04724             normalize_v3(bData->bNormal[index].invNorm);
04725             negate_v3(bData->bNormal[index].invNorm);
04726         }
04727 
04728         /* Prepare surface normal directional scale to easily convert
04729         *  brush intersection amount between global and local space */
04730         if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
04731             surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
04732             float temp_nor[3];
04733             if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
04734                 normal_short_to_float_v3(temp_nor, mvert[index].no);
04735                 normalize_v3(temp_nor);
04736             }
04737             else {
04738                 float n1[3], n2[3], n3[3];
04739                 ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
04740                 PaintUVPoint *tPoint = &((PaintUVPoint*)f_data->uv_p)[index];
04741 
04742                 normal_short_to_float_v3(n1, mvert[tPoint->v1].no);
04743                 normal_short_to_float_v3(n2, mvert[tPoint->v2].no);
04744                 normal_short_to_float_v3(n3, mvert[tPoint->v3].no);
04745                 interp_v3_v3v3v3(temp_nor,
04746                     n1, n2, n3, f_data->barycentricWeights[index*bData->s_num[index]].v);
04747             }
04748 
04749             mul_v3_v3(temp_nor, ob->size);
04750             bData->bNormal[index].normal_scale = len_v3(temp_nor);
04751         }
04752 
04753         /* calculate speed vector */
04754         if (do_velocity_data && !new_bdata && !bData->clear) {
04755             sub_v3_v3v3(bData->velocity[index].v, bData->realCoord[bData->s_pos[index]].v, prev_point);
04756         }
04757     }
04758 
04759     MEM_freeN(canvas_verts);
04760 
04761     /* generate surface space partitioning grid */
04762     surfaceGenerateGrid(surface);
04763     /* calculate current frame neighbouring point distances and global dirs */
04764     dynamicPaint_prepareNeighbourData(surface, 0);
04765 
04766     /* Copy current frame vertices to check against in next frame */
04767     copy_m4_m4(bData->prev_obmat, ob->obmat);
04768     memcpy(bData->prev_verts, mvert, canvasNumOfVerts*sizeof(MVert));
04769 
04770     bData->clear = 0;
04771 
04772     return 1;
04773 }
04774 
04775 /*
04776 *   Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface.
04777 */
04778 static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
04779 {
04780     PaintSurfaceData *sData = surface->data;
04781     PaintBakeData *bData = sData->bData;
04782     DynamicPaintCanvasSettings *canvas = surface->canvas;
04783     int ret = 1;
04784     if (!sData || sData->total_points < 1) return 0;
04785 
04786     dynamicPaint_surfacePreStep(surface, timescale);
04787     /*
04788     *   Loop through surface's target paint objects and do painting
04789     */
04790     {
04791         Base *base = NULL;
04792         GroupObject *go = NULL; 
04793         Object *brushObj = NULL;
04794         ModifierData *md = NULL;
04795 
04796         /* backup current scene frame */
04797         int scene_frame = scene->r.cfra;
04798         float scene_subframe = scene->r.subframe;
04799 
04800         /* either from group or from all objects */
04801         if(surface->brush_group)
04802             go = surface->brush_group->gobject.first;
04803         else
04804             base = scene->base.first;
04805 
04806         while (base || go)
04807         {
04808             brushObj = NULL;
04809             /* select object */
04810             if(surface->brush_group) {                      
04811                 if(go->ob)  brushObj = go->ob;                  
04812             }                   
04813             else                        
04814                 brushObj = base->object;
04815 
04816             if(!brushObj) {         
04817                 /* skip item */
04818                 if(surface->brush_group) go = go->next;
04819                 else base= base->next;                  
04820                 continue;           
04821             }
04822 
04823             /* next item */
04824             if(surface->brush_group)
04825                 go = go->next;
04826             else
04827                 base= base->next;
04828 
04829             /* check if target has an active dp modifier    */
04830             md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
04831             if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))                    
04832             {
04833                 DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
04834                 /* make sure we're dealing with a brush */
04835                 if (pmd2->brush)
04836                 {
04837                     DynamicPaintBrushSettings *brush = pmd2->brush;
04838                     BrushMaterials bMats = {0};
04839 
04840                     /* calculate brush speed vectors if required */
04841                     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE) {
04842                         bData->brush_velocity = MEM_callocN(sData->total_points*sizeof(float)*4, "Dynamic Paint brush velocity");
04843                         /* init adjacency data if not already */
04844                         if (!sData->adj_data)
04845                             dynamicPaint_initAdjacencyData(surface, 1);
04846                         if (!bData->bNeighs)
04847                             dynamicPaint_prepareNeighbourData(surface, 1);
04848                     }
04849 
04850                     /* update object data on this subframe */
04851                     if (subframe) {
04852                         scene_setSubframe(scene, subframe);
04853                         subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
04854                     }
04855                     /* Prepare materials if required    */
04856                     if (brush_usesMaterial(brush, scene))
04857                         dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
04858 
04859                     /* Apply brush on the surface depending on it's collision type */
04860                     /* Particle brush: */
04861                     if (brush->collision == MOD_DPAINT_COL_PSYS) {
04862                         if (brush && brush->psys && brush->psys->part && brush->psys->part->type==PART_EMITTER &&
04863                             psys_check_enabled(brushObj, brush->psys)) {
04864 
04865                             /* Paint a particle system */
04866                             BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
04867                             dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
04868                         }
04869                     }
04870                     /* Object center distance: */
04871                     else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
04872                         dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
04873                     }
04874                     /* Mesh volume/proximity: */
04875                     else if (brushObj != ob) {
04876                         dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale);
04877                     }
04878 
04879                     /* free temp material data */
04880                     if (brush_usesMaterial(brush, scene))
04881                         dynamicPaint_freeBrushMaterials(&bMats);
04882                     /* reset object to it's original state */
04883                     if (subframe) {
04884                         scene->r.cfra = scene_frame;
04885                         scene->r.subframe = scene_subframe;
04886                         subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
04887                     }
04888 
04889                     /* process special brush effects, like smudge */
04890                     if (bData->brush_velocity) {
04891                         if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE)
04892                             dynamicPaint_doSmudge(surface, brush, timescale);
04893                         MEM_freeN(bData->brush_velocity);
04894                         bData->brush_velocity = NULL;
04895                     }
04896                 }
04897             }
04898         }
04899     }
04900 
04901     /* surfaces operations that use adjacency data */
04902     if (sData->adj_data && bData->bNeighs)
04903     {
04904         /* wave type surface simulation step */
04905         if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
04906             dynamicPaint_doWaveStep(surface, timescale);
04907         }
04908 
04909         /* paint surface effects */
04910         if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT)
04911         {
04912             int steps = 1, s;
04913             PaintPoint *prevPoint;
04914             float *force = NULL;
04915 
04916             /* Allocate memory for surface previous points to read unchanged values from    */
04917             prevPoint = MEM_mallocN(sData->total_points*sizeof(struct PaintPoint), "PaintSurfaceDataCopy");
04918             if (!prevPoint)
04919                 return setError(canvas, "Not enough free memory.");
04920 
04921             /* Prepare effects and get number of required steps */
04922             steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale);
04923             for (s = 0; s < steps; s++) {
04924                 dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
04925             }
04926 
04927             /* Free temporary effect data   */
04928             if (prevPoint) MEM_freeN(prevPoint);
04929             if (force) MEM_freeN(force);
04930         }
04931     }
04932 
04933     return ret;
04934 }
04935 
04936 /*
04937 *   Calculate a single frame and included subframes for surface
04938 */
04939 int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame)
04940 {
04941     float timescale = 1.0f;
04942 
04943     /* apply previous displace on derivedmesh if incremental surface */
04944     if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL)
04945         dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm);
04946 
04947     /* update bake data */
04948     dynamicPaint_generateBakeData(surface, scene, cObject); 
04949     
04950     /* dont do substeps for first frame */
04951     if (surface->substeps && (frame != surface->start_frame)) {
04952         int st;
04953         timescale = 1.0f / (surface->substeps+1);
04954 
04955         for (st = 1; st <= surface->substeps; st++) {
04956             float subframe = ((float) st) / (surface->substeps+1);
04957             if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe)) return 0;
04958         }
04959     }
04960 
04961     return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f);
04962 }