2 ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * Contributor(s): Miika Hämäläinen
11 * ***** END GPL LICENSE BLOCK *****
15 #include "MEM_guardedalloc.h"
20 #include "BLI_blenlib.h"
22 #include "BLI_kdtree.h"
23 #include "BLI_threads.h"
24 #include "BLI_utildefines.h"
26 #include "DNA_anim_types.h"
27 #include "DNA_dynamicpaint_types.h"
28 #include "DNA_group_types.h" /*GroupObject*/
29 #include "DNA_material_types.h"
30 #include "DNA_mesh_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_modifier_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_texture_types.h"
38 #include "BKE_animsys.h"
39 #include "BKE_bvhutils.h" /* bvh tree */
40 #include "BKE_blender.h"
41 #include "BKE_cdderivedmesh.h"
42 #include "BKE_context.h"
43 #include "BKE_customdata.h"
44 #include "BKE_colortools.h"
45 #include "BKE_deform.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_DerivedMesh.h"
48 #include "BKE_dynamicpaint.h"
49 #include "BKE_effect.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
53 #include "BKE_material.h"
54 #include "BKE_modifier.h"
55 #include "BKE_object.h"
56 #include "BKE_particle.h"
57 #include "BKE_pointcache.h"
58 #include "BKE_scene.h"
59 #include "BKE_texture.h"
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63 #include "RNA_enum_types.h"
65 /* for image output */
66 #include "IMB_imbuf_types.h"
67 #include "IMB_imbuf.h"
69 /* to read material/texture color */
70 #include "RE_render_ext.h"
71 #include "RE_shader_ext.h"
77 /* precalculated gaussian factors for 5x super sampling */
78 static float gaussianFactors[5] = { 0.996849f,
83 static float gaussianTotal = 3.309425f;
85 /* UV Image neighbouring pixel table x and y list */
86 static int neighX[8] = {1,1,0,-1,-1,-1, 0, 1};
87 static int neighY[8] = {0,1,1, 1, 0,-1,-1,-1};
89 /* subframe_updateObject() flags */
90 #define UPDATE_PARENTS (1<<0)
91 #define UPDATE_MESH (1<<1)
92 #define UPDATE_EVERYTHING (UPDATE_PARENTS|UPDATE_MESH)
93 /* surface_getBrushFlags() return vals */
94 #define BRUSH_USES_VELOCITY (1<<0)
95 /* brush mesh raycast status */
97 #define HIT_PROXIMITY 2
98 /* paint effect default movement per frame in global units */
99 #define EFF_MOVEMENT_PER_FRAME 0.05f
100 /* initial wave time factor */
101 #define WAVE_TIME_FAC 0.1
103 #define MIN_WETNESS 0.001f
105 #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)
107 /***************************** Internal Structs ***************************/
109 typedef struct Bounds2D {
110 float min[2], max[2];
113 typedef struct Bounds3D {
115 float min[3], max[3];
118 typedef struct VolumeGrid {
120 Bounds3D grid_bounds; /* whole grid bounds */
122 Bounds3D *bounds; /* (x*y*z) precalculated grid cell bounds */
123 int *s_pos; /* (x*y*z) t_index begin id */
124 int *s_num; /* (x*y*z) number of t_index points */
125 int *t_index; /* actual surface point index,
126 access: (s_pos+s_num) */
129 typedef struct Vec3f {
133 typedef struct BakeNeighPoint {
134 float dir[3]; /* vector pointing towards this neighbour */
135 float dist; /* distance to */
138 /* Surface data used while processing a frame */
139 typedef struct PaintBakeNormal {
140 float invNorm[3]; /* current pixel world-space inverted normal */
141 float normal_scale; /* normal directional scale for displace mapping */
144 /* Temp surface data used to process a frame */
145 typedef struct PaintBakeData {
146 /* point space data */
147 PaintBakeNormal *bNormal;
148 int *s_pos; /* index to start reading point sample realCoord */
149 int *s_num; /* num of realCoord samples */
150 Vec3f *realCoord; /* current pixel center world-space coordinates for each sample
151 * ordered as (s_pos+s_num)*/
154 BakeNeighPoint *bNeighs; /* current global neighbour distances and directions, if required */
156 /* space partitioning */
157 VolumeGrid *grid; /* space partitioning grid to optimize brush checks */
159 /* velocity and movement */
160 Vec3f *velocity; /* speed vector in global space movement per frame, if required */
161 Vec3f *prev_velocity;
162 float *brush_velocity; /* special temp data for post-p velocity based brushes like smudge
163 * 3 float dir vec + 1 float str */
164 MVert *prev_verts; /* copy of previous frame vertices. used to observe surface movement */
165 float prev_obmat[4][4]; /* previous frame object matrix */
166 int clear; /* flag to check if surface was cleared/reset -> have to redo velocity etc. */
170 /* UV Image sequence format point */
171 typedef struct PaintUVPoint {
172 /* Pixel / mesh data */
173 unsigned int face_index, pixel_index; /* face index on domain derived mesh */
174 unsigned int v1, v2, v3; /* vertex indexes */
176 unsigned int neighbour_pixel; /* If this pixel isn't uv mapped to any face,
177 but it's neighbouring pixel is */
181 typedef struct ImgSeqFormatData {
183 Vec3f *barycentricWeights; /* b-weights for all pixel samples */
186 typedef struct EffVelPoint {
187 float previous_pos[3];
188 float previous_vel[3];
192 /* adjacency data flags */
193 #define ADJ_ON_MESH_EDGE (1<<0)
195 typedef struct PaintAdjData {
196 int *n_target; /* array of neighbouring point indexes,
197 for single sample use (n_index+neigh_num) */
198 int *n_index; /* index to start reading n_target for each point */
199 int *n_num; /* num of neighs for each point */
200 int *flags; /* vertex adjacency flags */
201 int total_targets; /* size of n_target */
204 /***************************** General Utils ******************************/
206 /* Set canvas error string to display at the bake report */
207 static int setError(DynamicPaintCanvasSettings *canvas, const char *string)
209 /* Add error to canvas ui info label */
210 BLI_strncpy(canvas->error, string, sizeof(canvas->error));
214 /* Get number of surface points for cached types */
215 static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
217 if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
218 return 0; /* not supported atm */
220 else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
221 if (!surface->canvas->dm) return 0; /* invalid derived mesh */
222 return surface->canvas->dm->getNumVerts(surface->canvas->dm);
228 /* checks whether surface's format/type has realtime preview */
229 int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface)
231 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 0;
232 else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
233 if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
234 surface->type == MOD_DPAINT_SURFACE_T_WAVE) return 0;
240 /* get currently active surface (in user interface) */
241 struct DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
243 DynamicPaintSurface *surface = canvas->surfaces.first;
246 for(i=0; surface; surface=surface->next) {
247 if(i == canvas->active_sur)
254 /* set preview to first previewable surface */
255 void dynamicPaint_resetPreview(DynamicPaintCanvasSettings *canvas)
257 DynamicPaintSurface *surface = canvas->surfaces.first;
260 for(; surface; surface=surface->next) {
261 if (!done && dynamicPaint_surfaceHasColorPreview(surface)) {
262 surface->flags |= MOD_DPAINT_PREVIEW;
266 surface->flags &= ~MOD_DPAINT_PREVIEW;
270 /* set preview to defined surface */
271 static void dynamicPaint_setPreview(DynamicPaintSurface *t_surface)
273 DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
274 for(; surface; surface=surface->next) {
275 if (surface == t_surface)
276 surface->flags |= MOD_DPAINT_PREVIEW;
278 surface->flags &= ~MOD_DPAINT_PREVIEW;
282 int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *ob, int output)
287 name = surface->output_name;
288 else if (output == 1)
289 name = surface->output_name2;
293 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
294 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
296 return (CustomData_get_named_layer_index(&me->fdata, CD_MCOL, name) != -1);
298 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
299 return (defgroup_name_index(ob, surface->output_name) != -1);
305 static int surface_duplicateOutputExists(void *arg, const char *name)
307 DynamicPaintSurface *t_surface = (DynamicPaintSurface*)arg;
308 DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
310 for(; surface; surface=surface->next) {
311 if (surface!=t_surface && surface->type==t_surface->type &&
312 surface->format==t_surface->format) {
313 if (surface->output_name[0]!='\0' && !strcmp(name, surface->output_name)) return 1;
314 if (surface->output_name2[0]!='\0' && !strcmp(name, surface->output_name2)) return 1;
320 static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output)
323 BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
325 BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name, sizeof(surface->output_name));
327 BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name2, sizeof(surface->output_name2));
331 static int surface_duplicateNameExists(void *arg, const char *name)
333 DynamicPaintSurface *t_surface = (DynamicPaintSurface*)arg;
334 DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
336 for(; surface; surface=surface->next) {
337 if (surface!=t_surface && !strcmp(name, surface->name)) return 1;
342 void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename)
345 BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
346 BLI_uniquename_cb(surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
350 /* change surface data to defaults on new type */
351 void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
353 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
354 surface->output_name[0]='\0';
355 surface->output_name2[0]='\0';
356 surface->flags |= MOD_DPAINT_ANTIALIAS;
357 surface->depth_clamp = 1.0f;
360 sprintf(surface->output_name, "dp_");
361 strcpy(surface->output_name2,surface->output_name);
362 surface->flags &= ~MOD_DPAINT_ANTIALIAS;
363 surface->depth_clamp = 0.0f;
366 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
367 strcat(surface->output_name,"paintmap");
368 strcat(surface->output_name2,"wetmap");
369 surface_setUniqueOutputName(surface, surface->output_name2, 1);
371 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
372 strcat(surface->output_name,"displace");
374 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
375 strcat(surface->output_name,"weight");
377 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
378 strcat(surface->output_name,"wave");
381 surface_setUniqueOutputName(surface, surface->output_name, 0);
384 if (dynamicPaint_surfaceHasColorPreview(surface))
385 dynamicPaint_setPreview(surface);
387 dynamicPaint_resetPreview(surface->canvas);
390 static int surface_totalSamples(DynamicPaintSurface *surface)
392 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ &&
393 surface->flags & MOD_DPAINT_ANTIALIAS)
394 return (surface->data->total_points*5);
395 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
396 surface->flags & MOD_DPAINT_ANTIALIAS && surface->data->adj_data)
397 return (surface->data->total_points+surface->data->adj_data->total_targets);
399 return surface->data->total_points;
402 static void blendColors(float t_color[3], float t_alpha, float s_color[3], float s_alpha, float result[4])
405 float i_alpha = 1.0f - s_alpha;
406 float f_alpha = t_alpha*i_alpha + s_alpha;
410 for (i=0; i<3; i++) {
411 result[i] = (t_color[i]*t_alpha*i_alpha + s_color[i]*s_alpha)/f_alpha;
415 copy_v3_v3(result, t_color);
417 /* return final alpha */
421 /* assumes source alpha > 0.0f or results NaN colors */
422 static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alpha)
424 float factor = (s_alpha<t_alpha) ? 1.0f : t_alpha/s_alpha;
426 /* set initial color depending on existing alpha */
427 interp_v3_v3v3(t_color, s_color, t_color, factor);
428 /* mix final color */
429 interp_v3_v3v3(t_color, t_color, s_color, s_alpha);
432 /* set "ignore cache" flag for all caches on this object */
433 static void object_cacheIgnoreClear(Object *ob, int state)
437 BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
439 for(pid=pidlist.first; pid; pid=pid->next) {
442 pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
444 pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
448 BLI_freelistN(&pidlist);
451 static void subframe_updateObject(Scene *scene, Object *ob, int flags, float frame)
453 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
455 /* if other is dynamic paint canvas, dont update */
456 if (pmd && pmd->canvas)
459 /* if object has parent, update it too */
460 if ((flags & UPDATE_PARENTS) && ob->parent) subframe_updateObject(scene, ob->parent, 0, frame);
461 if ((flags & UPDATE_PARENTS) && ob->track) subframe_updateObject(scene, ob->track, 0, frame);
463 /* for curve following objects, parented curve has to be updated too */
464 if(ob->type==OB_CURVE) {
466 BKE_animsys_evaluate_animdata(scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM);
469 ob->recalc |= OB_RECALC_ALL;
470 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
471 if (flags & UPDATE_MESH) {
472 /* ignore cache clear during subframe updates
473 * to not mess up cache validity */
474 object_cacheIgnoreClear(ob, 1);
475 object_handle_update(scene, ob);
476 object_cacheIgnoreClear(ob, 0);
479 where_is_object_time(scene, ob, frame);
482 static void scene_setSubframe(Scene *scene, float subframe)
484 /* dynamic paint subframes must be done on previous frame */
486 scene->r.subframe = subframe;
489 #define BRUSH_USES_VELOCITY (1<<0)
491 static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene)
494 GroupObject *go = NULL;
495 Object *brushObj = NULL;
496 ModifierData *md = NULL;
500 if(surface->brush_group)
501 go = surface->brush_group->gobject.first;
503 base = scene->base.first;
510 if(surface->brush_group) {
511 if(go->ob) brushObj = go->ob;
514 brushObj = base->object;
518 if(surface->brush_group) go = go->next;
519 else base= base->next;
523 if(surface->brush_group)
528 md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
529 if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
531 DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
535 DynamicPaintBrushSettings *brush = pmd2->brush;
537 if (brush->flags & MOD_DPAINT_USES_VELOCITY)
538 flags |= BRUSH_USES_VELOCITY;
546 static int brush_usesMaterial(DynamicPaintBrushSettings *brush, Scene *scene)
548 return ((brush->flags & MOD_DPAINT_USE_MATERIAL) && (!strcmp(scene->r.engine, "BLENDER_RENDER")));
551 /* check whether two bounds intersect */
552 static int boundsIntersect(Bounds3D *b1, Bounds3D *b2)
555 if (!b1->valid || !b2->valid) return 0;
557 if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) return 0;
561 /* check whether two bounds intersect inside defined proximity */
562 static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist)
565 if (!b1->valid || !b2->valid) return 0;
567 if (!(b1->min[i] <= (b2->max[i]+dist) && b1->max[i] >= (b2->min[i]-dist))) return 0;
571 /* check whether bounds intersects a point with given radius */
572 static int boundIntersectPoint(Bounds3D *b, float point[3], float radius)
575 if (!b->valid) return 0;
577 if (!(b->min[i] <= (point[i]+radius) && b->max[i] >= (point[i]-radius))) return 0;
581 /* expand bounds by a new point */
582 static void boundInsert(Bounds3D *b, float point[3])
586 copy_v3_v3(b->min, point);
587 copy_v3_v3(b->max, point);
592 if (point[i] < b->min[i]) b->min[i]=point[i];
593 if (point[i] > b->max[i]) b->max[i]=point[i];
598 static void freeGrid(PaintSurfaceData *data)
600 PaintBakeData *bData = data->bData;
601 VolumeGrid *grid = bData->grid;
603 if (grid->bounds) MEM_freeN(grid->bounds);
604 if (grid->s_pos) MEM_freeN(grid->s_pos);
605 if (grid->s_num) MEM_freeN(grid->s_num);
606 if (grid->t_index) MEM_freeN(grid->t_index);
608 MEM_freeN(bData->grid);
612 static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
614 PaintSurfaceData *sData = surface->data;
615 PaintBakeData *bData = sData->bData;
616 Bounds3D *grid_bounds;
618 int grid_cells, axis = 3;
619 int *temp_t_index = NULL;
620 int *temp_s_num = NULL;
623 int num_of_threads = omp_get_max_threads();
625 int num_of_threads = 1;
631 /* allocate separate bounds for each thread */
632 grid_bounds = MEM_callocN(sizeof(Bounds3D)*num_of_threads, "Grid Bounds");
633 bData->grid = MEM_callocN(sizeof(VolumeGrid), "Surface Grid");
636 if (grid && grid_bounds) {
638 float dim_factor, volume, dim[3];
642 /* calculate canvas dimensions */
643 #pragma omp parallel for schedule(static)
644 for (i=0; i<sData->total_points; i++) {
646 int id = omp_get_thread_num();
647 boundInsert(&grid_bounds[id], (bData->realCoord[bData->s_pos[i]].v));
649 boundInsert(&grid_bounds[0], (bData->realCoord[bData->s_pos[i]].v));
653 /* get final dimensions */
654 for (i=0; i<num_of_threads; i++) {
655 boundInsert(&grid->grid_bounds, grid_bounds[i].min);
656 boundInsert(&grid->grid_bounds, grid_bounds[i].max);
660 sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min);
662 min_dim = MAX3(td[0],td[1],td[2]) / 1000.f;
664 /* deactivate zero axises */
665 for (i=0; i<3; i++) {
666 if (td[i]<min_dim) {td[i]=1.0f; axis-=1;}
669 if (axis == 0 || MAX3(td[0],td[1],td[2]) < 0.0001f) {
670 MEM_freeN(grid_bounds);
671 MEM_freeN(bData->grid);
676 /* now calculate grid volume/area/width depending on num of active axis */
677 volume = td[0]*td[1]*td[2];
679 /* determine final grid size by trying to fit average 10.000 points per grid cell */
680 dim_factor = (float)pow(volume / ((double)sData->total_points / 10000.0), 1.0/(double)axis);
682 /* define final grid size using dim_factor, use min 3 for active axises */
683 for (i=0; i<3; i++) {
684 grid->dim[i] = (int)floor(td[i] / dim_factor);
685 CLAMP(grid->dim[i], (dim[i]>=min_dim) ? 3 : 1, 100);
687 grid_cells = grid->dim[0]*grid->dim[1]*grid->dim[2];
689 /* allocate memory for grids */
690 grid->bounds = MEM_callocN(sizeof(Bounds3D) * grid_cells, "Surface Grid Bounds");
691 grid->s_pos = MEM_callocN(sizeof(int) * grid_cells, "Surface Grid Position");
692 grid->s_num = MEM_callocN(sizeof(int) * grid_cells*num_of_threads, "Surface Grid Points");
693 temp_s_num = MEM_callocN(sizeof(int) * grid_cells, "Temp Surface Grid Points");
694 grid->t_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Grid Target Ids");
695 temp_t_index = MEM_callocN(sizeof(int) * sData->total_points, "Temp Surface Grid Target Ids");
697 /* in case of an allocation failture abort here */
698 if (!grid->bounds || !grid->s_pos || !grid->s_num || !grid->t_index || !temp_s_num || !temp_t_index)
702 /* calculate number of points withing each cell */
703 #pragma omp parallel for schedule(static)
704 for (i=0; i<sData->total_points; i++) {
706 for (j=0; j<3; j++) {
707 co[j] = (int)floor((bData->realCoord[bData->s_pos[i]].v[j] - grid->grid_bounds.min[j])/dim[j]*grid->dim[j]);
708 CLAMP(co[j], 0, grid->dim[j]-1);
711 temp_t_index[i] = co[0] + co[1] * grid->dim[0] + co[2] * grid->dim[0]*grid->dim[1];
713 grid->s_num[temp_t_index[i]+omp_get_thread_num()*grid_cells]++;
715 grid->s_num[temp_t_index[i]]++;
719 /* for first cell only calc s_num */
720 for (i=1; i<num_of_threads; i++) {
721 grid->s_num[0] += grid->s_num[i*grid_cells];
724 /* calculate grid indexes */
725 for (i=1; i<grid_cells; i++) {
727 for (id=1; id<num_of_threads; id++) {
728 grid->s_num[i] += grid->s_num[i+id*grid_cells];
730 grid->s_pos[i] = grid->s_pos[i-1] + grid->s_num[i-1];
733 /* save point indexes to final array */
734 for (i=0; i<sData->total_points; i++) {
735 int pos = grid->s_pos[temp_t_index[i]] + temp_s_num[temp_t_index[i]];
736 grid->t_index[pos] = i;
738 temp_s_num[temp_t_index[i]]++;
741 /* calculate cell bounds */
744 #pragma omp parallel for schedule(static)
745 for (x=0; x<grid->dim[0]; x++) {
747 for (y=0; y<grid->dim[1]; y++) {
749 for (z=0; z<grid->dim[2]; z++) {
750 int j, b_index = x + y * grid->dim[0] + z * grid->dim[0]*grid->dim[1];
752 for (j=0; j<3; j++) {
753 int s = (j==0) ? x : ((j==1) ? y : z);
754 grid->bounds[b_index].min[j] = grid->grid_bounds.min[j] + dim[j]/grid->dim[j]*s;
755 grid->bounds[b_index].max[j] = grid->grid_bounds.min[j] + dim[j]/grid->dim[j]*(s+1);
757 grid->bounds[b_index].valid = 1;
764 if (temp_s_num) MEM_freeN(temp_s_num);
765 if (temp_t_index) MEM_freeN(temp_t_index);
767 /* free per thread s_num values */
768 grid->s_num = MEM_reallocN(grid->s_num, sizeof(int) * grid_cells);
770 if (error || !grid->s_num) {
771 setError(surface->canvas, "Not enough free memory.");
776 if (grid_bounds) MEM_freeN(grid_bounds);
779 /***************************** Freeing data ******************************/
781 /* Free brush data */
782 void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
786 pmd->brush->dm->release(pmd->brush->dm);
787 pmd->brush->dm = NULL;
789 if(pmd->brush->paint_ramp)
790 MEM_freeN(pmd->brush->paint_ramp);
791 pmd->brush->paint_ramp = NULL;
792 if(pmd->brush->vel_ramp)
793 MEM_freeN(pmd->brush->vel_ramp);
794 pmd->brush->vel_ramp = NULL;
796 MEM_freeN(pmd->brush);
801 static void dynamicPaint_freeAdjData(PaintSurfaceData *data)
803 if (data->adj_data) {
804 if (data->adj_data->n_index) MEM_freeN(data->adj_data->n_index);
805 if (data->adj_data->n_num) MEM_freeN(data->adj_data->n_num);
806 if (data->adj_data->n_target) MEM_freeN(data->adj_data->n_target);
807 if (data->adj_data->flags) MEM_freeN(data->adj_data->flags);
808 MEM_freeN(data->adj_data);
809 data->adj_data = NULL;
813 static void free_bakeData(PaintSurfaceData *data)
815 PaintBakeData *bData = data->bData;
817 if (bData->bNormal) MEM_freeN(bData->bNormal);
818 if (bData->s_pos) MEM_freeN(bData->s_pos);
819 if (bData->s_num) MEM_freeN(bData->s_num);
820 if (bData->realCoord) MEM_freeN(bData->realCoord);
821 if (bData->bNeighs) MEM_freeN(bData->bNeighs);
822 if (bData->grid) freeGrid(data);
823 if (bData->prev_verts) MEM_freeN(bData->prev_verts);
824 if (bData->velocity) MEM_freeN(bData->velocity);
825 if (bData->prev_velocity) MEM_freeN(bData->prev_velocity);
827 MEM_freeN(data->bData);
832 /* free surface data if it's not used anymore */
833 void surface_freeUnusedData(DynamicPaintSurface *surface)
835 if (!surface->data) return;
837 /* free bakedata if not active or surface is baked */
838 if (!(surface->flags & MOD_DPAINT_ACTIVE) ||
839 (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED))
840 free_bakeData(surface->data);
843 void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface)
845 PaintSurfaceData *data = surface->data;
847 if (data->format_data) {
848 /* format specific free */
849 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
850 ImgSeqFormatData *format_data = (ImgSeqFormatData*)data->format_data;
851 if (format_data->uv_p)
852 MEM_freeN(format_data->uv_p);
853 if (format_data->barycentricWeights)
854 MEM_freeN(format_data->barycentricWeights);
856 MEM_freeN(data->format_data);
859 if (data->type_data) MEM_freeN(data->type_data);
860 dynamicPaint_freeAdjData(data);
864 MEM_freeN(surface->data);
865 surface->data = NULL;
868 void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
871 BKE_ptcache_free_list(&(surface->ptcaches));
872 surface->pointcache = NULL;
874 if(surface->effector_weights)
875 MEM_freeN(surface->effector_weights);
876 surface->effector_weights = NULL;
878 BLI_remlink(&(surface->canvas->surfaces), surface);
879 dynamicPaint_freeSurfaceData(surface);
883 /* Free canvas data */
884 void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
887 /* Free surface data */
888 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
889 DynamicPaintSurface *next_surface = NULL;
892 next_surface = surface->next;
893 dynamicPaint_freeSurface(surface);
894 surface = next_surface;
899 pmd->canvas->dm->release(pmd->canvas->dm);
900 pmd->canvas->dm = NULL;
902 MEM_freeN(pmd->canvas);
907 /* Free whole dp modifier */
908 void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd)
911 dynamicPaint_freeCanvas(pmd);
912 dynamicPaint_freeBrush(pmd);
917 /***************************** Initialize and reset ******************************/
920 * Creates a new surface and adds it to the list
921 * If scene is null, frame range of 1-250 is used
922 * A pointer to this surface is returned
924 struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene)
926 DynamicPaintSurface *surface= MEM_callocN(sizeof(DynamicPaintSurface), "DynamicPaintSurface");
927 if (!surface) return NULL;
929 surface->canvas = canvas;
930 surface->format = MOD_DPAINT_SURFACE_F_VERTEX;
931 surface->type = MOD_DPAINT_SURFACE_T_PAINT;
934 surface->pointcache = BKE_ptcache_add(&(surface->ptcaches));
935 surface->pointcache->flag |= PTCACHE_DISK_CACHE;
936 surface->pointcache->step = 1;
938 /* Set initial values */
939 surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG |
940 MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1;
942 surface->effect_ui = 1;
944 surface->diss_speed = 250;
945 surface->dry_speed = 500;
946 surface->depth_clamp = 0.0f;
947 surface->disp_factor = 1.0f;
948 surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
949 surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
951 surface->init_color[0] = 1.0f;
952 surface->init_color[1] = 1.0f;
953 surface->init_color[2] = 1.0f;
954 surface->init_color[3] = 1.0f;
956 surface->image_resolution = 256;
957 surface->substeps = 0;
960 surface->start_frame = scene->r.sfra;
961 surface->end_frame = scene->r.efra;
964 surface->start_frame = 1;
965 surface->end_frame = 250;
968 surface->spread_speed = 1.0f;
969 surface->color_spread_speed = 1.0f;
970 surface->shrink_speed = 1.0f;
972 surface->wave_damping = 0.05f;
973 surface->wave_speed = 1.0f;
974 surface->wave_timescale = 1.0f;
975 surface->wave_spring = 0.20f;
977 BLI_snprintf(surface->image_output_path, sizeof(surface->image_output_path), "%sdynamicpaint", U.textudir);
978 BLI_cleanup_dir(NULL, surface->image_output_path);
979 dynamicPaintSurface_setUniqueName(surface, "Surface");
981 surface->effector_weights = BKE_add_effector_weights(NULL);
983 dynamicPaintSurface_updateType(surface);
985 BLI_addtail(&canvas->surfaces, surface);
991 * Initialize modifier data
993 int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene)
996 if(type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
997 DynamicPaintCanvasSettings *canvas;
999 dynamicPaint_freeCanvas(pmd);
1001 canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas");
1007 /* Create one surface */
1008 if (!dynamicPaint_createNewSurface(canvas, scene))
1012 else if(type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
1013 DynamicPaintBrushSettings *brush;
1015 dynamicPaint_freeBrush(pmd);
1017 brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint");
1024 brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA;
1025 brush->collision = MOD_DPAINT_COL_VOLUME;
1031 brush->alpha = 1.0f;
1032 brush->wetness = 1.0f;
1034 brush->paint_distance = 1.0f;
1035 brush->proximity_falloff = MOD_DPAINT_PRFALL_SMOOTH;
1037 brush->particle_radius = 0.2f;
1038 brush->particle_smooth = 0.05f;
1040 brush->wave_factor = 1.0f;
1041 brush->wave_clamp = 0.0f;
1042 brush->smudge_strength = 0.3f;
1043 brush->max_velocity = 1.0f;
1047 /* Paint proximity falloff colorramp. */
1051 brush->paint_ramp = add_colorband(0);
1052 if (!brush->paint_ramp)
1054 ramp = brush->paint_ramp->data;
1055 /* Add default smooth-falloff ramp. */
1056 ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
1058 ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].pos = 1.0f;
1060 pmd->brush->paint_ramp->tot = 2;
1063 /* Brush velocity ramp. */
1067 brush->vel_ramp = add_colorband(0);
1068 if (!brush->vel_ramp)
1070 ramp = brush->vel_ramp->data;
1071 ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
1072 ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
1073 brush->paint_ramp->tot = 2;
1083 void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd)
1086 tpmd->type = pmd->type;
1088 dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_CANVAS, NULL);
1090 dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_BRUSH, NULL);
1094 tpmd->canvas->pmd = tpmd;
1096 } else if (tpmd->brush) {
1097 DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
1098 t_brush->pmd = tpmd;
1100 t_brush->flags = brush->flags;
1101 t_brush->collision = brush->collision;
1103 t_brush->mat = brush->mat;
1104 t_brush->r = brush->r;
1105 t_brush->g = brush->g;
1106 t_brush->b = brush->b;
1107 t_brush->alpha = brush->alpha;
1108 t_brush->wetness = brush->wetness;
1110 t_brush->particle_radius = brush->particle_radius;
1111 t_brush->particle_smooth = brush->particle_smooth;
1112 t_brush->paint_distance = brush->paint_distance;
1113 t_brush->psys = brush->psys;
1115 if (brush->paint_ramp)
1116 memcpy(t_brush->paint_ramp, brush->paint_ramp, sizeof(ColorBand));
1117 if (brush->vel_ramp)
1118 memcpy(t_brush->vel_ramp, brush->vel_ramp, sizeof(ColorBand));
1120 t_brush->proximity_falloff = brush->proximity_falloff;
1121 t_brush->wave_type = brush->wave_type;
1122 t_brush->ray_dir = brush->ray_dir;
1124 t_brush->wave_factor = brush->wave_factor;
1125 t_brush->wave_clamp = brush->wave_clamp;
1126 t_brush->max_velocity = brush->max_velocity;
1127 t_brush->smudge_strength = brush->smudge_strength;
1131 /* allocates surface data depending on surface type */
1132 static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface)
1134 PaintSurfaceData *sData = surface->data;
1136 switch (surface->type) {
1137 case MOD_DPAINT_SURFACE_T_PAINT:
1138 sData->type_data = MEM_callocN(sizeof(PaintPoint)*sData->total_points, "DynamicPaintSurface Data");
1140 case MOD_DPAINT_SURFACE_T_DISPLACE:
1141 sData->type_data = MEM_callocN(sizeof(float)*sData->total_points, "DynamicPaintSurface DepthData");
1143 case MOD_DPAINT_SURFACE_T_WEIGHT:
1144 sData->type_data = MEM_callocN(sizeof(float)*sData->total_points, "DynamicPaintSurface WeightData");
1146 case MOD_DPAINT_SURFACE_T_WAVE:
1147 sData->type_data = MEM_callocN(sizeof(PaintWavePoint)*sData->total_points, "DynamicPaintSurface WaveData");
1151 if (sData->type_data == NULL) setError(surface->canvas, "Not enough free memory!");
1154 static int surface_usesAdjDistance(DynamicPaintSurface *surface)
1156 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && surface->effect) return 1;
1157 if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) return 1;
1161 static int surface_usesAdjData(DynamicPaintSurface *surface)
1163 if (surface_usesAdjDistance(surface)) return 1;
1164 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
1165 surface->flags & MOD_DPAINT_ANTIALIAS) return 1;
1170 /* initialize surface adjacency data */
1171 static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init)
1173 PaintSurfaceData *sData = surface->data;
1176 int neigh_points = 0;
1178 if (!surface_usesAdjData(surface) && !force_init) return;
1180 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1181 /* For vertex format, neighbours are connected by edges */
1182 neigh_points = 2*surface->canvas->dm->getNumEdges(surface->canvas->dm);
1184 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
1185 neigh_points = sData->total_points*8;
1187 if (!neigh_points) return;
1189 /* allocate memory */
1190 ed = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data");
1192 ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index");
1193 ed->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts");
1194 temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data");
1195 ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets");
1196 ed->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags");
1197 ed->total_targets = neigh_points;
1199 /* in case of allocation error, free memory */
1200 if (!ed->n_index || !ed->n_num || !ed->n_target || !temp_data) {
1201 dynamicPaint_freeAdjData(sData);
1202 if (temp_data) MEM_freeN(temp_data);
1203 setError(surface->canvas, "Not enough free memory.");
1207 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1211 /* For vertex format, count every vertex that is connected by an edge */
1212 int numOfEdges = surface->canvas->dm->getNumEdges(surface->canvas->dm);
1213 int numOfFaces = surface->canvas->dm->getNumFaces(surface->canvas->dm);
1214 struct MEdge *edge = surface->canvas->dm->getEdgeArray(surface->canvas->dm);
1215 struct MFace *face = surface->canvas->dm->getFaceArray(surface->canvas->dm);
1217 /* count number of edges per vertex */
1218 for (i=0; i<numOfEdges; i++) {
1219 ed->n_num[edge[i].v1]++;
1220 ed->n_num[edge[i].v2]++;
1222 temp_data[edge[i].v1]++;
1223 temp_data[edge[i].v2]++;
1226 /* to locate points on "mesh edge" */
1227 for (i=0; i<numOfFaces; i++) {
1228 temp_data[face[i].v1]++;
1229 temp_data[face[i].v2]++;
1230 temp_data[face[i].v3]++;
1232 temp_data[face[i].v4]++;
1235 /* now check if total number of edges+faces for
1236 * each vertex is even, if not -> vertex is on mesh edge */
1237 for (i=0; i<sData->total_points; i++) {
1238 if ((temp_data[i]%2) ||
1240 ed->flags[i] |= ADJ_ON_MESH_EDGE;
1242 /* reset temp data */
1246 /* order n_index array */
1248 for (i=0; i<sData->total_points; i++) {
1249 ed->n_index[i] = n_pos;
1250 n_pos += ed->n_num[i];
1253 /* and now add neighbour data using that info */
1254 for (i=0; i<numOfEdges; i++) {
1256 int index = edge[i].v1;
1257 n_pos = ed->n_index[index]+temp_data[index];
1258 ed->n_target[n_pos] = edge[i].v2;
1263 n_pos = ed->n_index[index]+temp_data[index];
1264 ed->n_target[n_pos] = edge[i].v1;
1268 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1269 /* for image sequences, only allocate memory.
1270 * bake initialization takes care of rest */
1273 MEM_freeN(temp_data);
1276 void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
1278 PaintSurfaceData *sData = surface->data;
1279 PaintPoint* pPoint = (PaintPoint*)sData->type_data;
1280 DerivedMesh *dm = surface->canvas->dm;
1283 if (surface->type != MOD_DPAINT_SURFACE_T_PAINT)
1286 if (surface->init_color_type == MOD_DPAINT_INITIAL_NONE)
1289 else if (surface->init_color_type == MOD_DPAINT_INITIAL_COLOR) {
1290 /* apply color to every surface point */
1291 #pragma omp parallel for schedule(static)
1292 for (i=0; i<sData->total_points; i++) {
1293 copy_v3_v3(pPoint[i].color, surface->init_color);
1294 pPoint[i].alpha = surface->init_color[3];
1297 /* UV mapped texture */
1298 else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
1299 Tex *tex = surface->init_texture;
1301 MFace *mface = dm->getFaceArray(dm);
1302 int numOfFaces = dm->getNumFaces(dm);
1308 CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname);
1309 tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
1312 /* for vertex surface loop through tfaces and find uv color
1313 * that provides highest alpha */
1314 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1315 #pragma omp parallel for schedule(static)
1316 for (i=0; i<numOfFaces; i++) {
1317 int numOfVert = (mface[i].v4) ? 4 : 3;
1318 float uv[3] = {0.0f};
1320 for (j=0; j<numOfVert; j++) {
1321 TexResult texres = {0};
1322 unsigned int *vert = (&mface[i].v1)+j;
1324 /* remap to -1.0 to 1.0 */
1325 uv[0] = tface[i].uv[j][0]*2.0f - 1.0f;
1326 uv[1] = tface[i].uv[j][1]*2.0f - 1.0f;
1328 multitex_ext_safe(tex, uv, &texres);
1330 if (texres.tin > pPoint[*vert].alpha) {
1331 copy_v3_v3(pPoint[*vert].color, &texres.tr);
1332 pPoint[*vert].alpha = texres.tin;
1337 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1338 ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
1339 int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
1341 #pragma omp parallel for schedule(static)
1342 for (i=0; i<sData->total_points; i++) {
1343 float uv[9] = {0.0f};
1344 float uv_final[3] = {0.0f};
1346 TexResult texres = {0};
1348 /* collect all uvs */
1349 for (j=0; j<3; j++) {
1350 int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
1351 copy_v2_v2(&uv[j*3], tface[f_data->uv_p[i].face_index].uv[v]);
1354 /* interpolate final uv pos */
1355 interp_v3_v3v3v3( uv_final, &uv[0], &uv[3], &uv[6],
1356 f_data->barycentricWeights[i*samples].v);
1357 /* remap to -1.0 to 1.0 */
1358 uv_final[0] = uv_final[0]*2.0f - 1.0f;
1359 uv_final[1] = uv_final[1]*2.0f - 1.0f;
1361 multitex_ext_safe(tex, uv_final, &texres);
1364 copy_v3_v3(pPoint[i].color, &texres.tr);
1365 pPoint[i].alpha = texres.tin;
1369 /* vertex color layer */
1370 else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) {
1371 MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername);
1374 /* for vertex surface, just copy colors from mcol */
1375 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1376 MFace *mface = dm->getFaceArray(dm);
1377 int numOfFaces = dm->getNumFaces(dm);
1379 #pragma omp parallel for schedule(static)
1380 for (i=0; i<numOfFaces; i++) {
1381 int numOfVert = (mface[i].v4) ? 4 : 3;
1383 for (j=0; j<numOfVert; j++) {
1384 unsigned int *vert = ((&mface[i].v1)+j);
1386 pPoint[*vert].color[0] = 1.0f/255.f*(float)col[i*4+j].b;
1387 pPoint[*vert].color[1] = 1.0f/255.f*(float)col[i*4+j].g;
1388 pPoint[*vert].color[2] = 1.0f/255.f*(float)col[i*4+j].r;
1389 pPoint[*vert].alpha = 1.0f/255.f*(float)col[i*4+j].a;
1393 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1394 ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
1395 int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
1397 #pragma omp parallel for schedule(static)
1398 for (i=0; i<sData->total_points; i++) {
1399 int face_ind = f_data->uv_p[i].face_index;
1400 float colors[3][4] = {{0.0f,0.0f,0.0f,0.0f}};
1401 float final_color[4];
1403 /* collect color values */
1404 for (j=0; j<3; j++) {
1405 int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
1406 colors[j][0] = 1.0f/255.f*(float)col[face_ind*4+v].b;
1407 colors[j][1] = 1.0f/255.f*(float)col[face_ind*4+v].g;
1408 colors[j][2] = 1.0f/255.f*(float)col[face_ind*4+v].r;
1409 colors[j][3] = 1.0f/255.f*(float)col[face_ind*4+v].a;
1412 /* interpolate final color */
1413 interp_v4_v4v4v4( final_color, colors[0], colors[1], colors[2],
1414 f_data->barycentricWeights[i*samples].v);
1416 copy_v3_v3(pPoint[i].color, final_color);
1417 pPoint[i].alpha = final_color[3];
1423 /* clears surface data back to zero */
1424 void dynamicPaint_clearSurface(DynamicPaintSurface *surface)
1426 PaintSurfaceData *sData = surface->data;
1427 if (sData && sData->type_data) {
1428 unsigned int data_size;
1430 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
1431 data_size = sizeof(PaintPoint);
1432 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
1433 data_size = sizeof(PaintWavePoint);
1435 data_size = sizeof(float);
1437 memset(sData->type_data, 0, data_size * sData->total_points);
1439 /* set initial color */
1440 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
1441 dynamicPaint_setInitialColor(surface);
1444 sData->bData->clear = 1;
1448 /* completely (re)initializes surface (only for point cache types)*/
1449 int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
1451 int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
1452 /* dont touch image sequence types. they get handled only on bake */
1453 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
1455 if (surface->data) dynamicPaint_freeSurfaceData(surface);
1456 if (numOfPoints < 1) return 0;
1458 /* allocate memory */
1459 surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
1460 if (!surface->data) return 0;
1462 /* allocate data depending on surface type and format */
1463 surface->data->total_points = numOfPoints;
1464 dynamicPaint_allocateSurfaceType(surface);
1465 dynamicPaint_initAdjacencyData(surface, 0);
1467 /* set initial color */
1468 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
1469 dynamicPaint_setInitialColor(surface);
1474 /* make sure allocated surface size matches current requirements */
1475 static void dynamicPaint_checkSurfaceData(DynamicPaintSurface *surface)
1477 if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) {
1478 dynamicPaint_resetSurface(surface);
1483 /***************************** Modifier processing ******************************/
1486 /* apply displacing vertex surface to the derived mesh */
1487 static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result, int update_normals)
1489 PaintSurfaceData *sData = surface->data;
1491 if (!sData || surface->format != MOD_DPAINT_SURFACE_F_VERTEX) return;
1493 /* displace paint */
1494 if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
1495 MVert *mvert = result->getVertArray(result);
1497 float* value = (float*)sData->type_data;
1499 #pragma omp parallel for schedule(static)
1500 for (i=0; i<sData->total_points; i++) {
1501 float normal[3], val=value[i]*surface->disp_factor;
1502 normal_short_to_float_v3(normal, mvert[i].no);
1503 normalize_v3(normal);
1505 mvert[i].co[0] -= normal[0]*val;
1506 mvert[i].co[1] -= normal[1]*val;
1507 mvert[i].co[2] -= normal[2]*val;
1513 CDDM_calc_normals(result);
1517 * Apply canvas data to the object derived mesh
1519 static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd,
1523 DerivedMesh *result = CDDM_copy(dm);
1525 if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
1527 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1528 pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY;
1530 /* loop through surfaces */
1531 for (; surface; surface=surface->next) {
1532 PaintSurfaceData *sData = surface->data;
1534 if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) {
1535 if (!(surface->flags & (MOD_DPAINT_ACTIVE))) continue;
1537 /* process vertex surface previews */
1538 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1540 /* vertex color paint */
1541 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1543 MFace *mface = result->getFaceArray(result);
1544 int numOfFaces = result->getNumFaces(result);
1546 PaintPoint* pPoint = (PaintPoint*)sData->type_data;
1549 /* paint is stored on dry and wet layers, so mix final color first */
1550 float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color");
1552 #pragma omp parallel for schedule(static)
1553 for (i=0; i<sData->total_points; i++) {
1554 /* blend dry and wet layer */
1555 blendColors(pPoint[i].color, pPoint[i].alpha, pPoint[i].e_color, pPoint[i].e_alpha, &fcolor[i*4]);
1558 /* viewport preview */
1559 if (surface->flags & MOD_DPAINT_PREVIEW) {
1560 /* Save preview results to weight layer, to be
1561 * able to share same drawing methods */
1562 col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
1563 if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
1566 #pragma omp parallel for schedule(static)
1567 for (i=0; i<numOfFaces; i++) {
1569 Material *material = give_current_material(ob, mface[i].mat_nr+1);
1571 for (; j<((mface[i].v4)?4:3); j++) {
1572 int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
1574 if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) {
1578 /* Apply material color as base vertex color for preview */
1585 else { /* default grey */
1590 /* mix surface color */
1591 interp_v3_v3v3(c, c, &fcolor[index], fcolor[index+3]);
1593 col[i*4+j].r = FTOCHAR(c[2]);
1594 col[i*4+j].g = FTOCHAR(c[1]);
1595 col[i*4+j].b = FTOCHAR(c[0]);
1599 col[i*4+j].r = FTOCHAR(pPoint[index].wetness);
1600 col[i*4+j].g = FTOCHAR(pPoint[index].wetness);
1601 col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
1605 pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
1610 /* save layer data to output layer */
1613 col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name);
1615 #pragma omp parallel for schedule(static)
1616 for (i=0; i<numOfFaces; i++) {
1618 for (; j<((mface[i].v4)?4:3); j++) {
1619 int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
1622 col[i*4+j].a = FTOCHAR(fcolor[index+3]);
1623 col[i*4+j].r = FTOCHAR(fcolor[index+2]);
1624 col[i*4+j].g = FTOCHAR(fcolor[index+1]);
1625 col[i*4+j].b = FTOCHAR(fcolor[index]);
1633 col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name2);
1635 #pragma omp parallel for schedule(static)
1636 for (i=0; i<numOfFaces; i++) {
1639 for (; j<((mface[i].v4)?4:3); j++) {
1640 int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
1642 col[i*4+j].r = FTOCHAR(pPoint[index].wetness);
1643 col[i*4+j].g = FTOCHAR(pPoint[index].wetness);
1644 col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
1649 /* vertex group paint */
1650 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
1651 int defgrp_index = defgroup_name_index(ob, surface->output_name);
1652 MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
1653 float *weight = (float*)sData->type_data;
1654 /* viewport preview */
1655 if (surface->flags & MOD_DPAINT_PREVIEW) {
1656 /* Save preview results to weight layer, to be
1657 * able to share same drawing methods */
1658 MFace *mface = result->getFaceArray(result);
1659 int numOfFaces = result->getNumFaces(result);
1661 MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
1662 if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
1665 #pragma omp parallel for schedule(static)
1666 for (i=0; i<numOfFaces; i++) {
1667 float temp_color[3];
1669 for (; j<((mface[i].v4)?4:3); j++) {
1670 int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
1672 weight_to_rgb(weight[index], temp_color, temp_color+1, temp_color+2);
1673 col[i*4+j].r = FTOCHAR(temp_color[2]);
1674 col[i*4+j].g = FTOCHAR(temp_color[1]);
1675 col[i*4+j].b = FTOCHAR(temp_color[0]);
1679 pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
1683 /* apply weights into a vertex group, if doesnt exists add a new layer */
1684 if (defgrp_index >= 0 && !dvert && strlen(surface->output_name)>0)
1685 dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
1686 NULL, sData->total_points, surface->output_name);
1687 if (defgrp_index >= 0 && dvert) {
1689 for(i=0; i<sData->total_points; i++) {
1690 MDeformVert *dv= &dvert[i];
1691 MDeformWeight *def_weight = defvert_find_index(dv, defgrp_index);
1693 /* skip if weight value is 0 and no existing weight is found */
1694 if (!def_weight && !weight[i])
1697 /* if not found, add a weight for it */
1699 MDeformWeight *newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1),
1702 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
1706 dv->dw[dv->totweight].def_nr=defgrp_index;
1707 def_weight = &dv->dw[dv->totweight];
1711 /* set weight value */
1712 def_weight->weight = weight[i];
1716 /* wave simulation */
1717 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
1718 MVert *mvert = result->getVertArray(result);
1720 PaintWavePoint* wPoint = (PaintWavePoint*)sData->type_data;
1722 #pragma omp parallel for schedule(static)
1723 for (i=0; i<sData->total_points; i++) {
1725 normal_short_to_float_v3(normal, mvert[i].no);
1726 normalize_v3(normal);
1728 mvert[i].co[0] += normal[0]*wPoint[i].height;
1729 mvert[i].co[1] += normal[1]*wPoint[i].height;
1730 mvert[i].co[2] += normal[2]*wPoint[i].height;
1732 CDDM_calc_normals(result);
1736 dynamicPaint_applySurfaceDisplace(surface, result, 1);
1741 /* make a copy of dm to use as brush data */
1743 if (pmd->brush->dm) pmd->brush->dm->release(pmd->brush->dm);
1744 pmd->brush->dm = CDDM_copy(result);
1750 /* update cache frame range */
1751 void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface)
1753 if (surface->pointcache) {
1754 surface->pointcache->startframe = surface->start_frame;
1755 surface->pointcache->endframe = surface->end_frame;
1759 void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm)
1761 if (canvas->dm) canvas->dm->release(canvas->dm);
1762 canvas->dm = CDDM_copy(dm);
1766 * Updates derived mesh copy and processes dynamic paint step / caches.
1768 static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
1771 DynamicPaintCanvasSettings *canvas = pmd->canvas;
1772 DynamicPaintSurface *surface = canvas->surfaces.first;
1774 /* update derived mesh copy */
1775 canvas_copyDerivedMesh(canvas, dm);
1777 /* in case image sequence baking, stop here */
1778 if (canvas->flags & MOD_DPAINT_BAKING) return;
1780 /* loop through surfaces */
1781 for (; surface; surface=surface->next) {
1782 int current_frame = (int)scene->r.cfra;
1784 /* free bake data if not required anymore */
1785 surface_freeUnusedData(surface);
1787 /* image sequences are handled by bake operator */
1788 if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) continue;
1789 if (!(surface->flags & MOD_DPAINT_ACTIVE)) continue;
1791 /* make sure surface is valid */
1792 dynamicPaint_checkSurfaceData(surface);
1794 /* limit frame range */
1795 CLAMP(current_frame, surface->start_frame, surface->end_frame);
1797 if (current_frame != surface->current_frame || (int)scene->r.cfra == surface->start_frame) {
1798 PointCache *cache = surface->pointcache;
1800 surface->current_frame = current_frame;
1802 /* read point cache */
1803 BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
1804 pid.cache->startframe = surface->start_frame;
1805 pid.cache->endframe = surface->end_frame;
1806 BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL);
1808 /* reset non-baked cache at first frame */
1809 if((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED))
1811 cache->flag |= PTCACHE_REDO_NEEDED;
1812 BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
1813 cache->flag &= ~PTCACHE_REDO_NEEDED;
1816 /* try to read from cache */
1817 if(BKE_ptcache_read(&pid, (float)scene->r.cfra)) {
1818 BKE_ptcache_validate(cache, (int)scene->r.cfra);
1820 /* if read failed and we're on surface range do recalculate */
1821 else if ((int)scene->r.cfra == current_frame
1822 && !(cache->flag & PTCACHE_BAKED)) {
1823 /* calculate surface frame */
1824 canvas->flags |= MOD_DPAINT_BAKING;
1825 dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
1826 canvas->flags &= ~MOD_DPAINT_BAKING;
1828 /* restore canvas derivedmesh if required */
1829 if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE &&
1830 surface->flags & MOD_DPAINT_DISP_INCREMENTAL && surface->next)
1831 canvas_copyDerivedMesh(canvas, dm);
1833 BKE_ptcache_validate(cache, surface->current_frame);
1834 BKE_ptcache_write(&pid, surface->current_frame);
1841 /* Modifier call. Processes dynamic paint modifier step. */
1842 struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
1844 /* Update canvas data for a new frame */
1845 dynamicPaint_frameUpdate(pmd, scene, ob, dm);
1847 /* Return output mesh */
1848 return dynamicPaint_Modifier_apply(pmd, ob, dm);
1852 /***************************** Image Sequence / UV Image Surface Calls ******************************/
1855 * Tries to find the neighbouring pixel in given (uv space) direction.
1856 * Result is used by effect system to move paint on the surface.
1858 * px,py : origin pixel x and y
1859 * n_index : lookup direction index (use neighX,neighY to get final index)
1861 static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh *dm, char *uvname, int w, int h, int px, int py, int n_index)
1863 /* Note: Current method only uses polygon edges to detect neighbouring pixels.
1864 * -> It doesn't always lead to the optimum pixel but is accurate enough
1865 * and faster/simplier than including possible face tip point links)
1869 PaintUVPoint *tPoint = NULL;
1870 PaintUVPoint *cPoint = NULL;
1872 /* shift position by given n_index */
1873 x = px + neighX[n_index];
1874 y = py + neighY[n_index];
1876 if (x<0 || x>=w) return -1;
1877 if (y<0 || y>=h) return -1;
1879 tPoint = &tempPoints[x+w*y]; /* UV neighbour */
1880 cPoint = &tempPoints[px+w*py]; /* Origin point */
1883 * Check if shifted point is on same face -> it's a correct neighbour
1884 * (and if it isn't marked as an "edge pixel")
1886 if ((tPoint->face_index == cPoint->face_index) && (tPoint->neighbour_pixel == -1))
1890 * Even if shifted point is on another face
1891 * -> use this point.
1893 * !! Replace with "is uv faces linked" check !!
1894 * This should work fine as long as uv island
1895 * margin is > 1 pixel.
1897 if ((tPoint->face_index != -1) && (tPoint->neighbour_pixel == -1)) {
1902 * If we get here, the actual neighbouring pixel
1903 * is located on a non-linked uv face, and we have to find
1904 * it's "real" position.
1906 * Simple neighbouring face finding algorithm:
1907 * - find closest uv edge to shifted pixel and get
1908 * the another face that shares that edge
1909 * - find corresponding position of that new face edge
1912 * TODO: Implement something more accurate / optimized?
1915 int numOfFaces = dm->getNumFaces(dm);
1916 MFace *mface = dm->getFaceArray(dm);
1917 MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
1919 /* Get closest edge to that subpixel on UV map */
1921 float pixel[2], dist, t_dist;
1922 int i, uindex[3], edge1_index, edge2_index,
1923 e1_index, e2_index, target_face;
1924 float closest_point[2], lambda, dir_vec[2];
1925 int target_uv1, target_uv2, final_pixel[2], final_index;
1927 float *s_uv1, *s_uv2, *t_uv1, *t_uv2;
1929 pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w;
1930 pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h;
1932 /* Get uv indexes for current face part */
1934 uindex[0] = 0; uindex[1] = 2; uindex[2] = 3;
1937 uindex[0] = 0; uindex[1] = 1; uindex[2] = 2;
1941 * Find closest edge to that pixel
1943 /* Dist to first edge */
1944 e1_index = cPoint->v1; e2_index = cPoint->v2; edge1_index = uindex[0]; edge2_index = uindex[1];
1945 dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
1947 /* Dist to second edge */
1948 t_dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[1]], tface[cPoint->face_index].uv[uindex[2]]);
1949 if (t_dist < dist) {e1_index = cPoint->v2; e2_index = cPoint->v3; edge1_index = uindex[1]; edge2_index = uindex[2]; dist = t_dist;}
1951 /* Dist to third edge */
1952 t_dist = dist_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[2]], tface[cPoint->face_index].uv[uindex[0]]);
1953 if (t_dist < dist) {e1_index = cPoint->v3; e2_index = cPoint->v1; edge1_index = uindex[2]; edge2_index = uindex[0]; dist = t_dist;}
1957 * Now find another face that is linked to that edge
1961 for (i=0; i<numOfFaces; i++) {
1963 * Check if both edge vertices share this face
1965 int v4 = (mface[i].v4) ? mface[i].v4 : -1;
1967 if ((e1_index == mface[i].v1 || e1_index == mface[i].v2 || e1_index == mface[i].v3 || e1_index == v4) &&
1968 (e2_index == mface[i].v1 || e2_index == mface[i].v2 || e2_index == mface[i].v3 || e2_index == v4)) {
1969 if (i == cPoint->face_index) continue;
1976 if (e1_index == mface[i].v1) target_uv1 = 0;
1977 else if (e1_index == mface[i].v2) target_uv1 = 1;
1978 else if (e1_index == mface[i].v3) target_uv1 = 2;
1979 else target_uv1 = 3;
1981 if (e2_index == mface[i].v1) target_uv2 = 0;
1982 else if (e2_index == mface[i].v2) target_uv2 = 1;
1983 else if (e2_index == mface[i].v3) target_uv2 = 2;
1984 else target_uv2 = 3;
1990 /* If none found return -1 */
1991 if (target_face == -1) return -1;
1994 * If target face is connected in UV space as well, just use original index
1996 s_uv1 = (float *)tface[cPoint->face_index].uv[edge1_index];
1997 s_uv2 = (float *)tface[cPoint->face_index].uv[edge2_index];
1998 t_uv1 = (float *)tface[target_face].uv[target_uv1];
1999 t_uv2 = (float *)tface[target_face].uv[target_uv2];
2001 //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]);
2003 if (((s_uv1[0] == t_uv1[0] && s_uv1[1] == t_uv1[1]) &&
2004 (s_uv2[0] == t_uv2[0] && s_uv2[1] == t_uv2[1]) ) ||
2005 ((s_uv2[0] == t_uv1[0] && s_uv2[1] == t_uv1[1]) &&
2006 (s_uv1[0] == t_uv2[0] && s_uv1[1] == t_uv2[1]) )) return ((px+neighX[n_index]) + w*(py+neighY[n_index]));
2009 * Find a point that is relatively at same edge position
2010 * on this other face UV
2012 lambda = closest_to_line_v2(closest_point, pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]);
2013 if (lambda < 0.0f) lambda = 0.0f;
2014 if (lambda > 1.0f) lambda = 1.0f;
2016 sub_v2_v2v2(dir_vec, tface[target_face].uv[target_uv2], tface[target_face].uv[target_uv1]);
2018 mul_v2_fl(dir_vec, lambda);
2020 copy_v2_v2(pixel, tface[target_face].uv[target_uv1]);
2021 add_v2_v2(pixel, dir_vec);
2022 pixel[0] = (pixel[0] * (float)w) - 0.5f;
2023 pixel[1] = (pixel[1] * (float)h) - 0.5f;
2025 final_pixel[0] = (int)floor(pixel[0]);
2026 final_pixel[1] = (int)floor(pixel[1]);
2028 /* If current pixel uv is outside of texture */
2029 if (final_pixel[0] < 0 || final_pixel[0] >= w) return -1;
2030 if (final_pixel[1] < 0 || final_pixel[1] >= h) return -1;
2032 final_index = final_pixel[0] + w * final_pixel[1];
2034 /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */
2035 if (final_index == (px+w*py)) return -1;
2036 /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
2037 if (tempPoints[final_index].face_index != target_face) return -1;
2040 * If final point is an "edge pixel", use it's "real" neighbour instead
2042 if (tempPoints[final_index].neighbour_pixel != -1) final_index = cPoint->neighbour_pixel;
2050 * Create a surface for uv image sequence format
2052 int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
2054 /* Antialias jitter point relative coords */
2055 float jitter5sample[10] = {0.0f, 0.0f,
2064 int active_points = 0;
2067 PaintSurfaceData *sData;
2068 DynamicPaintCanvasSettings *canvas = surface->canvas;
2069 DerivedMesh *dm = canvas->dm;
2071 PaintUVPoint *tempPoints = NULL;
2072 Vec3f *tempWeights = NULL;
2073 /* MVert *mvert = NULL; */ /* UNUSED */
2074 MFace *mface = NULL;
2075 MTFace *tface = NULL;
2076 Bounds2D *faceBB = NULL;
2080 if (!dm) return setError(canvas, "Canvas mesh not updated.");
2081 if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) return setError(canvas, "Can't bake non-\"image sequence\" formats.");
2083 numOfFaces = dm->getNumFaces(dm);
2084 /* mvert = dm->getVertArray(dm); */ /* UNUSED */
2085 mface = dm->getFaceArray(dm);
2088 CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname);
2089 tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
2091 /* Check for validity */
2092 if (!tface) return setError(canvas, "No UV data on canvas.");
2093 if (surface->image_resolution < 16 || surface->image_resolution > 8192) return setError(canvas, "Invalid resolution.");
2095 w = h = surface->image_resolution;
2098 * Start generating the surface
2100 printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i faces.\n", w, h, numOfFaces);
2102 /* Init data struct */
2103 if (surface->data) dynamicPaint_freeSurfaceData(surface);
2104 sData = surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
2105 if (!surface->data) return setError(canvas, "Not enough free memory.");
2107 aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
2108 tempPoints = (struct PaintUVPoint *) MEM_callocN(w*h*sizeof(struct PaintUVPoint), "Temp PaintUVPoint");
2109 if (!tempPoints) error=1;
2111 final_index = (int *) MEM_callocN(w*h*sizeof(int), "Temp UV Final Indexes");
2112 if (!final_index) error=1;
2114 tempWeights = (struct Vec3f *) MEM_mallocN(w*h*aa_samples*sizeof(struct Vec3f), "Temp bWeights");
2115 if (!tempWeights) error=1;
2118 * Generate a temporary bounding box array for UV faces to optimize
2119 * the pixel-inside-a-face search.
2122 faceBB = (struct Bounds2D *) MEM_mallocN(numOfFaces*sizeof(struct Bounds2D), "MPCanvasFaceBB");
2123 if (!faceBB) error=1;
2127 for (ty=0; ty<numOfFaces; ty++) {
2128 int numOfVert = (mface[ty].v4) ? 4 : 3;
2131 copy_v2_v2(faceBB[ty].min, tface[ty].uv[0]);
2132 copy_v2_v2(faceBB[ty].max, tface[ty].uv[0]);
2134 for (i = 1; i<numOfVert; i++) {
2135 if (tface[ty].uv[i][0] < faceBB[ty].min[0]) faceBB[ty].min[0] = tface[ty].uv[i][0];
2136 if (tface[ty].uv[i][1] < faceBB[ty].min[1]) faceBB[ty].min[1] = tface[ty].uv[i][1];
2137 if (tface[ty].uv[i][0] > faceBB[ty].max[0]) faceBB[ty].max[0] = tface[ty].uv[i][0];
2138 if (tface[ty].uv[i][1] > faceBB[ty].max[1]) faceBB[ty].max[1] = tface[ty].uv[i][1];
2144 * Loop through every pixel and check
2145 * if pixel is uv-mapped on a canvas face.
2148 #pragma omp parallel for schedule(static)
2149 for (ty = 0; ty < h; ty++)
2152 for (tx = 0; tx < w; tx++)
2155 int index = tx+w*ty;
2156 PaintUVPoint *tPoint = (&tempPoints[index]);
2158 short isInside = 0; /* if point is inside a uv face */
2160 float d1[2], d2[2], d3[2], point[5][2];
2161 float dot00,dot01,dot02,dot11,dot12, invDenom, u,v;
2163 /* Init per pixel settings */
2164 tPoint->face_index = -1;
2165 tPoint->neighbour_pixel = -1;
2166 tPoint->pixel_index = index;
2168 /* Actual pixel center, used when collision is found */
2169 point[0][0] = ((float)tx + 0.5f) / w;
2170 point[0][1] = ((float)ty + 0.5f) / h;
2173 * A pixel middle sample isn't enough to find very narrow polygons
2174 * So using 4 samples of each corner too
2176 point[1][0] = ((float)tx) / w;
2177 point[1][1] = ((float)ty) / h;
2179 point[2][0] = ((float)tx+1) / w;
2180 point[2][1] = ((float)ty) / h;
2182 point[3][0] = ((float)tx) / w;
2183 point[3][1] = ((float)ty+1) / h;
2185 point[4][0] = ((float)tx+1) / w;
2186 point[4][1] = ((float)ty+1) / h;
2189 /* Loop through samples, starting from middle point */
2190 for (sample=0; sample<5; sample++) {
2192 /* Loop through every face in the mesh */
2193 for (i=0; i<numOfFaces; i++) {
2196 if (faceBB[i].min[0] > (point[sample][0])) continue;
2197 if (faceBB[i].min[1] > (point[sample][1])) continue;
2198 if (faceBB[i].max[0] < (point[sample][0])) continue;
2199 if (faceBB[i].max[1] < (point[sample][1])) continue;
2201 /* Calculate point inside a triangle check
2203 sub_v2_v2v2(d1, tface[i].uv[2], tface[i].uv[0]); // uv2 - uv0
2204 sub_v2_v2v2(d2, tface[i].uv[1], tface[i].uv[0]); // uv1 - uv0
2205 sub_v2_v2v2(d3, point[sample], tface[i].uv[0]); // point - uv0
2207 dot00 = d1[0]*d1[0] + d1[1]*d1[1];
2208 dot01 = d1[0]*d2[0] + d1[1]*d2[1];
2209 dot02 = d1[0]*d3[0] + d1[1]*d3[1];
2210 dot11 = d2[0]*d2[0] + d2[1]*d2[1];
2211 dot12 = d2[0]*d3[0] + d2[1]*d3[1];
2213 invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
2214 u = (dot11 * dot02 - dot01 * dot12) * invDenom;
2215 v = (dot00 * dot12 - dot01 * dot02) * invDenom;
2217 if ((u > 0) && (v > 0) && (u + v < 1)) {isInside=1;} /* is inside a triangle */
2219 /* If collision wasn't found but the face is a quad
2220 * do another check for the second half */
2221 if ((!isInside) && mface[i].v4)
2224 /* change d2 to test the other half */
2225 sub_v2_v2v2(d2, tface[i].uv[3], tface[i].uv[0]); // uv3 - uv0
2228 dot00 = d1[0]*d1[0] + d1[1]*d1[1];
2229 dot01 = d1[0]*d2[0] + d1[1]*d2[1];
2230 dot02 = d1[0]*d3[0] + d1[1]*d3[1];
2231 dot11 = d2[0]*d2[0] + d2[1]*d2[1];
2232 dot12 = d2[0]*d3[0] + d2[1]*d3[1];
2234 invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
2235 u = (dot11 * dot02 - dot01 * dot12) * invDenom;
2236 v = (dot00 * dot12 - dot01 * dot02) * invDenom;
2238 if ((u > 0) && (v > 0) && (u + v < 1)) {isInside=2;} /* is inside the second half of the quad */
2243 * If point was inside the face
2245 if (isInside != 0) {
2247 float uv1co[2], uv2co[2], uv3co[2], uv[2];
2250 /* Get triagnle uvs */
2252 copy_v2_v2(uv1co, tface[i].uv[0]);
2253 copy_v2_v2(uv2co, tface[i].uv[1]);
2254 copy_v2_v2(uv3co, tface[i].uv[2]);
2257 copy_v2_v2(uv1co, tface[i].uv[0]);
2258 copy_v2_v2(uv2co, tface[i].uv[2]);
2259 copy_v2_v2(uv3co, tface[i].uv[3]);
2262 /* Add b-weights per anti-aliasing sample */
2263 for (j=0; j<aa_samples; j++) {
2264 uv[0] = point[0][0] + jitter5sample[j*2] / w;
2265 uv[1] = point[0][1] + jitter5sample[j*2+1] / h;
2267 barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index*aa_samples+j].v);
2270 /* Set surface point face values */
2271 tPoint->face_index = i; /* face index */
2272 tPoint->quad = (isInside == 2) ? 1 : 0; /* quad or tri part*/
2274 /* save vertex indexes */
2275 tPoint->v1 = (isInside == 2) ? mface[i].v1 : mface[i].v1;
2276 tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2;
2277 tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3;
2279 sample = 5; /* make sure we exit sample loop as well */
2288 * Now loop through every pixel that was left without index
2289 * and find if they have neighbouring pixels that have an index.
2290 * If so use that polygon as pixel surface.
2291 * (To avoid seams on uv island edges)
2293 #pragma omp parallel for schedule(static)
2294 for (ty = 0; ty < h; ty++)
2297 for (tx = 0; tx < w; tx++)
2299 int index = tx+w*ty;
2300 PaintUVPoint *tPoint = (&tempPoints[index]);
2302 /* If point isnt't on canvas mesh */
2303 if (tPoint->face_index == -1) {
2304 int u_min, u_max, v_min, v_max;
2309 u_min = (tx > 0) ? -1 : 0;
2310 u_max = (tx < (w-1)) ? 1 : 0;
2311 v_min = (ty > 0) ? -1 : 0;
2312 v_max = (ty < (h-1)) ? 1 : 0;
2314 point[0] = ((float)tx + 0.5f) / w;
2315 point[1] = ((float)ty + 0.5f) / h;
2317 /* search through defined area for neighbour */
2318 for (u=u_min; u<=u_max; u++)
2319 for (v=v_min; v<=v_max; v++) {
2320 /* if not this pixel itself */
2322 ind = (tx+u)+w*(ty+v);
2324 /* if neighbour has index */
2325 if (tempPoints[ind].face_index != -1) {
2327 float uv1co[2], uv2co[2], uv3co[2], uv[2];
2328 int i = tempPoints[ind].face_index, j;
2330 /* Now calculate pixel data for this pixel as it was on polygon surface */
2331 if (!tempPoints[ind].quad) {
2332 copy_v2_v2(uv1co, tface[i].uv[0]);
2333 copy_v2_v2(uv2co, tface[i].uv[1]);
2334 copy_v2_v2(uv3co, tface[i].uv[2]);
2337 copy_v2_v2(uv1co, tface[i].uv[0]);
2338 copy_v2_v2(uv2co, tface[i].uv[2]);
2339 copy_v2_v2(uv3co, tface[i].uv[3]);
2342 /* Add b-weights per anti-aliasing sample */
2343 for (j=0; j<aa_samples; j++) {
2345 uv[0] = point[0] + jitter5sample[j*2] / w;
2346 uv[1] = point[1] + jitter5sample[j*2+1] / h;
2347 barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index*aa_samples+j].v);
2351 tPoint->neighbour_pixel = ind; // face index
2352 tPoint->quad = tempPoints[ind].quad; // quad or tri
2354 /* save vertex indexes */
2355 tPoint->v1 = (tPoint->quad) ? mface[i].v1 : mface[i].v1;
2356 tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2;
2357 tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3;
2359 u = u_max + 1; /* make sure we exit outer loop as well */
2369 * When base loop is over convert found neighbour indexes to real ones
2370 * Also count the final number of active surface points
2372 for (ty = 0; ty < h; ty++)
2375 for (tx = 0; tx < w; tx++)
2377 int index = tx+w*ty;
2378 PaintUVPoint *tPoint = (&tempPoints[index]);
2380 if (tPoint->face_index == -1 && tPoint->neighbour_pixel != -1) tPoint->face_index = tempPoints[tPoint->neighbour_pixel].face_index;
2381 if (tPoint->face_index != -1) active_points++;
2385 /* If any effect enabled, create surface effect / wet layer
2386 * neighbour lists. Processes possibly moving data. */
2387 if (surface_usesAdjData(surface)) {
2391 /* Create a temporary array of final indexes (before unassigned
2392 * pixels have been dropped) */
2393 for (i=0; i<w*h; i++) {
2394 if (tempPoints[i].face_index != -1) {
2395 final_index[i] = cursor;
2399 /* allocate memory */
2400 sData->total_points = w*h;
2401 dynamicPaint_initAdjacencyData(surface, 0);
2403 if (sData->adj_data) {
2404 PaintAdjData *ed = sData->adj_data;
2405 unsigned int n_pos = 0;
2406 //#pragma omp parallel for schedule(static)
2407 for (ty = 0; ty < h; ty++)
2410 for (tx = 0; tx < w; tx++)
2412 int i, index = tx+w*ty;
2414 if (tempPoints[index].face_index != -1) {
2415 ed->n_index[final_index[index]] = n_pos;
2416 ed->n_num[final_index[index]] = 0;
2418 for (i=0; i<8; i++) {
2420 /* Try to find a neighbouring pixel in defined direction
2421 * If not found, -1 is returned */
2422 int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i);
2424 if (n_target != -1) {
2425 ed->n_target[n_pos] = final_index[n_target];
2426 ed->n_num[final_index[index]]++;
2436 /* Create final surface data without inactive points */
2438 ImgSeqFormatData *f_data = MEM_callocN(sizeof(struct ImgSeqFormatData), "ImgSeqFormatData");
2440 f_data->uv_p = MEM_callocN(active_points*sizeof(struct PaintUVPoint), "PaintUVPoint");
2441 f_data->barycentricWeights = MEM_callocN(active_points*aa_samples*sizeof(struct Vec3f), "PaintUVPoint");
2443 if (!f_data->uv_p || !f_data->barycentricWeights) error=1;
2447 sData->total_points = active_points;
2449 /* in case of allocation error, free everything */
2452 if (f_data->uv_p) MEM_freeN(f_data->uv_p);
2453 if (f_data->barycentricWeights) MEM_freeN(f_data->barycentricWeights);
2458 int index, cursor = 0;
2459 sData->total_points = active_points;
2460 sData->format_data = f_data;
2462 for(index = 0; index < (w*h); index++) {
2463 if (tempPoints[index].face_index != -1) {
2464 memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint));
2465 memcpy(&f_data->barycentricWeights[cursor*aa_samples], &tempWeights[index*aa_samples], sizeof(Vec3f)*aa_samples);
2472 if (error==1) setError(canvas, "Not enough free memory.");
2474 if (faceBB) MEM_freeN(faceBB);
2475 if (tempPoints) MEM_freeN(tempPoints);
2476 if (tempWeights) MEM_freeN(tempWeights);
2477 if (final_index) MEM_freeN(final_index);
2479 /* Init surface type data */
2481 dynamicPaint_allocateSurfaceType(surface);
2484 /* -----------------------------------------------------------------
2485 * For debug, output pixel statuses to the color map
2486 * -----------------------------------------------------------------*/
2487 #pragma omp parallel for schedule(static)
2488 for (index = 0; index < sData->total_points; index++)
2490 ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
2491 PaintUVPoint *uvPoint = &((PaintUVPoint*)f_data->uv_p)[index];
2492 PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
2495 /* Every pixel that is assigned as "edge pixel" gets blue color */
2496 if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f;
2497 /* and every pixel that finally got an polygon gets red color */
2498 if (uvPoint->face_index != -1) pPoint->color[0] = 1.0f;
2499 /* green color shows pixel face index hash */
2500 if (uvPoint->face_index != -1) pPoint->color[1] = (float)(uvPoint->face_index % 255)/256.0f;
2504 dynamicPaint_setInitialColor(surface);
2507 return (error == 0);
2511 * Outputs an image file from uv surface data.
2513 void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char* filename, short output_layer)
2517 PaintSurfaceData *sData = surface->data;
2518 ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
2519 /* OpenEXR or PNG */
2520 int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_OPENEXR : R_PNG;
2521 char output_file[FILE_MAX];
2523 if (!sData || !sData->type_data) {setError(surface->canvas, "Image save failed: Invalid surface.");return;}
2524 /* if selected format is openexr, but current build doesnt support one */
2525 #ifndef WITH_OPENEXR
2526 if (format == R_OPENEXR) format = R_PNG;
2528 BLI_strncpy(output_file, filename, sizeof(output_file));
2529 BKE_add_image_extension(output_file, format);
2531 /* Validate output file path */
2532 BLI_path_abs(output_file, G.main->name);
2533 BLI_make_existing_file(output_file);
2535 /* Init image buffer */
2536 ibuf = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat);
2537 if (ibuf == NULL) {setError(surface->canvas, "Image save failed: Not enough free memory.");return;}
2539 #pragma omp parallel for schedule(static)
2540 for (index = 0; index < sData->total_points; index++)
2542 int pos=f_data->uv_p[index].pixel_index*4; /* image buffer position */
2544 /* Set values of preferred type */
2545 if (output_layer == 1) {
2547 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
2548 PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
2549 float value = (point->wetness > 1.0f) ? 1.0f : point->wetness;
2551 ibuf->rect_float[pos]=value;
2552 ibuf->rect_float[pos+1]=value;
2553 ibuf->rect_float[pos+2]=value;
2554 ibuf->rect_float[pos+3]=1.0f;
2557 else if (output_layer == 0) {
2559 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
2560 PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
2562 ibuf->rect_float[pos] = point->color[0];
2563 ibuf->rect_float[pos+1] = point->color[1];
2564 ibuf->rect_float[pos+2] = point->color[2];
2566 if (point->e_alpha) mixColors(&ibuf->rect_float[pos], point->alpha, point->e_color, point->e_alpha);
2568 /* use highest alpha */
2569 ibuf->rect_float[pos+3] = (point->e_alpha > point->alpha) ? point->e_alpha : point->alpha;
2571 /* Multiply color by alpha if enabled */
2572 if (surface->flags & MOD_DPAINT_MULALPHA) {
2573 ibuf->rect_float[pos] *= ibuf->rect_float[pos+3];
2574 ibuf->rect_float[pos+1] *= ibuf->rect_float[pos+3];
2575 ibuf->rect_float[pos+2] *= ibuf->rect_float[pos+3];
2579 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
2580 float depth = ((float*)sData->type_data)[index];
2581 if (surface->depth_clamp)
2582 depth /= surface->depth_clamp;
2584 if (surface->disp_type == MOD_DPAINT_DISP_DISPLACE) {
2585 depth = (0.5f - depth/2.0f);
2588 CLAMP(depth, 0.0f, 1.0f);
2590 ibuf->rect_float[pos]=depth;
2591 ibuf->rect_float[pos+1]=depth;
2592 ibuf->rect_float[pos+2]=depth;
2593 ibuf->rect_float[pos+3]=1.0f;
2596 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
2597 PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
2598 float depth = wPoint->height;
2599 if (surface->depth_clamp)
2600 depth /= surface->depth_clamp;
2601 depth = (0.5f + depth/2.0f);
2602 CLAMP(depth, 0.0f, 1.0f);
2604 ibuf->rect_float[pos]=depth;
2605 ibuf->rect_float[pos+1]=depth;
2606 ibuf->rect_float[pos+2]=depth;
2607 ibuf->rect_float[pos+3]=1.0f;
2612 /* Set output format, png in case exr isnt supported */
2613 ibuf->ftype= PNG|95;
2615 if (format == R_OPENEXR) { /* OpenEXR 32-bit float */
2616 ibuf->ftype = OPENEXR | OPENEXR_COMPRESS;
2621 IMB_saveiff(ibuf, output_file, IB_rectfloat);
2622 IMB_freeImBuf(ibuf);
2626 /***************************** Material / Texture Sampling ******************************/
2628 /* stores a copy of required materials to allow doing adjustments
2629 * without interfering the render/preview */
2630 typedef struct BrushMaterials {
2636 /* Initialize materials for brush object:
2637 * Calculates inverse matrices for linked objects, updates
2638 * volume caches etc. */
2639 static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
2641 /* Calculate inverse transformation matrix
2642 * for this object */
2643 invert_m4_m4(brushOb->imat, brushOb->obmat);
2644 copy_m4_m4(brushOb->imat_ren, brushOb->imat);
2646 /* Now process every material linked to this brush object */
2647 if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) {
2648 int i, tot=(*give_totcolp(brushOb));
2650 /* allocate material pointer array */
2652 bMats->ob_mats = MEM_callocN(sizeof(Material*)*(tot), "BrushMaterials");
2653 for (i=0; i<tot; i++) {
2654 bMats->ob_mats[i] = RE_init_sample_material(give_current_material(brushOb,(i+1)), scene);
2660 bMats->mat = RE_init_sample_material(ui_mat, scene);
2664 /* free all data allocated by dynamicPaint_updateBrushMaterials() */
2665 static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats)
2667 /* Now process every material linked to this brush object */
2668 if (bMats->ob_mats) {
2670 for (i=0; i<bMats->tot; i++) {
2671 RE_free_sample_material(bMats->ob_mats[i]);
2673 MEM_freeN(bMats->ob_mats);
2675 else if (bMats->mat) {
2676 RE_free_sample_material(bMats->mat);
2681 * Get material diffuse color and alpha (including linked textures) in given coordinates
2683 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)
2685 Material *mat = bMats->mat;
2686 MFace *mface = orcoDm->getFaceArray(orcoDm);
2688 /* If no material defined, use the one assigned to the mesh face */
2690 if (bMats->ob_mats) {
2691 int mat_nr = mface[faceIndex].mat_nr;
2692 if (mat_nr >= (*give_totcolp(brushOb))) return;
2693 mat = bMats->ob_mats[mat_nr];
2694 if (mat == NULL) return; /* No material assigned */
2699 RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb);
2703 /***************************** Ray / Nearest Point Utils ******************************/
2706 /* A modified callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
2707 * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
2709 * To optimize brush detection speed this doesn't calculate hit coordinates or normal.
2710 * If ray hit the second half of a quad, no[0] is set to 1.0f.
2712 static void mesh_faces_spherecast_dp(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
2714 const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
2715 MVert *vert = data->vert;
2716 MFace *face = data->face + index;
2719 float *t0, *t1, *t2, *t3;
2720 t0 = vert[ face->v1 ].co;
2721 t1 = vert[ face->v2 ].co;
2722 t2 = vert[ face->v3 ].co;
2723 t3 = face->v4 ? vert[ face->v4].co : NULL;
2727 float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
2729 if(dist >= 0 && dist < hit->dist)
2733 hit->no[0] = (quad) ? 1.0f : 0.0f;
2744 /* A modified callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
2745 * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
2747 * To optimize brush detection speed this doesn't calculate hit normal.
2748 * If ray hit the second half of a quad, no[0] is set to 1.0f, else 0.0f
2750 static void mesh_faces_nearest_point_dp(void *userdata, int index, const float *co, BVHTreeNearest *nearest)
2752 const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
2753 MVert *vert = data->vert;
2754 MFace *face = data->face + index;
2757 float *t0, *t1, *t2, *t3;
2758 t0 = vert[ face->v1 ].co;
2759 t1 = vert[ face->v2 ].co;
2760 t2 = vert[ face->v3 ].co;
2761 t3 = face->v4 ? vert[ face->v4].co : NULL;
2765 float nearest_tmp[3], dist;
2768 dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
2769 if(dist < nearest->dist)
2771 nearest->index = index;
2772 nearest->dist = dist;
2773 copy_v3_v3(nearest->co, nearest_tmp);
2774 nearest->no[0] = (quad) ? 1.0f : 0.0f;