| 
									
										
										
										
											2012-04-30 14:24:11 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-04-30 14:24:11 +00:00
										 |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-11-10 12:28:26 +00:00
										 |  |  |  * Contributor(s): Miika Hämäläinen | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_kdtree.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | #include "BLI_threads.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | #include "BLF_translation.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 17:06:09 +00:00
										 |  |  | #include "DNA_anim_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-29 11:19:29 +00:00
										 |  |  | #include "DNA_armature_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | #include "DNA_constraint_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-05 17:06:09 +00:00
										 |  |  | #include "DNA_dynamicpaint_types.h"
 | 
					
						
							|  |  |  | #include "DNA_group_types.h" /*GroupObject*/
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | #include "DNA_material_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-05 17:06:09 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | #include "DNA_space_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | #include "DNA_texture_types.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-05 17:06:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include "BKE_animsys.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-29 11:19:29 +00:00
										 |  |  | #include "BKE_armature.h"
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | #include "BKE_bvhutils.h"   /* bvh tree	*/
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_blender.h"
 | 
					
						
							|  |  |  | #include "BKE_cdderivedmesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | #include "BKE_constraint.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							|  |  |  | #include "BKE_colortools.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | #include "BKE_deform.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include "BKE_dynamicpaint.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | #include "BKE_effect.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | #include "BKE_image.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_material.h"
 | 
					
						
							|  |  |  | #include "BKE_modifier.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include "BKE_object.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_particle.h"
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #include "BKE_pointcache.h"
 | 
					
						
							|  |  |  | #include "BKE_scene.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "BKE_texture.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | #include "RNA_enum_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | /* for image output	*/ | 
					
						
							|  |  |  | #include "IMB_imbuf_types.h"
 | 
					
						
							|  |  |  | #include "IMB_imbuf.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | /* to read material/texture color	*/ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | #include "RE_render_ext.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | #include "RE_shader_ext.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | #ifdef _OPENMP
 | 
					
						
							| 
									
										
										
										
											2012-11-23 10:03:50 +00:00
										 |  |  | #  include <omp.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 07:18:29 +00:00
										 |  |  | /* could enable at some point but for now there are far too many conversions */ | 
					
						
							| 
									
										
										
										
											2012-11-23 10:03:50 +00:00
										 |  |  | #ifdef __GNUC__
 | 
					
						
							|  |  |  | #  pragma GCC diagnostic ignored "-Wdouble-promotion"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-11-04 07:18:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | /* precalculated gaussian factors for 5x super sampling	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | static float gaussianFactors[5] = {0.996849f, | 
					
						
							|  |  |  |                                    0.596145f, | 
					
						
							|  |  |  |                                    0.596145f, | 
					
						
							|  |  |  |                                    0.596145f, | 
					
						
							|  |  |  |                                    0.524141f}; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | static float gaussianTotal = 3.309425f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | /* UV Image neighboring pixel table x and y list */ | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | static int neighX[8] = {1, 1, 0, -1, -1, -1, 0, 1}; | 
					
						
							|  |  |  | static int neighY[8] = {0, 1, 1, 1, 0, -1, -1, -1}; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* subframe_updateObject() flags */ | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | #define SUBFRAME_RECURSION 5
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | #define UPDATE_MESH (1 << 1)
 | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | #define UPDATE_EVERYTHING (UPDATE_MESH) // | UPDATE_PARENTS
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | /* surface_getBrushFlags() return vals */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | #define BRUSH_USES_VELOCITY (1 << 0)
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | /* brush mesh raycast status */ | 
					
						
							|  |  |  | #define HIT_VOLUME 1
 | 
					
						
							|  |  |  | #define HIT_PROXIMITY 2
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | /* dynamicPaint_findNeighbourPixel() return codes */ | 
					
						
							|  |  |  | #define NOT_FOUND -1
 | 
					
						
							|  |  |  | #define ON_MESH_EDGE -2
 | 
					
						
							|  |  |  | #define OUT_OF_TEXTURE -3
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | /* paint effect default movement per frame in global units */ | 
					
						
							|  |  |  | #define EFF_MOVEMENT_PER_FRAME 0.05f
 | 
					
						
							|  |  |  | /* initial wave time factor */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | #define WAVE_TIME_FAC (1.0f / 24.f)
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | #define CANVAS_REL_SIZE 5.0f
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | /* drying limits */ | 
					
						
							|  |  |  | #define MIN_WETNESS 0.001f
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | #define MAX_WETNESS 5.0f
 | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* dissolve inline function */ | 
					
						
							|  |  |  | BLI_INLINE void value_dissolve(float *r_value, const float time, const float scale, const int is_log) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	*r_value = (is_log) ? | 
					
						
							|  |  |  | 	              (*r_value) * (powf(MIN_WETNESS, 1.0f / (1.2f * time / scale))) : | 
					
						
							|  |  |  | 	              (*r_value) - 1.0f / time * scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************** Internal Structs ***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | typedef struct Bounds2D { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	float min[2], max[2]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | } Bounds2D; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct Bounds3D { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	int valid; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	float min[3], max[3]; | 
					
						
							|  |  |  | } Bounds3D; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct VolumeGrid { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	int dim[3]; | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | 	Bounds3D grid_bounds; /* whole grid bounds */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	Bounds3D *bounds;   /* (x*y*z) precalculated grid cell bounds */ | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 	int *s_pos; /* (x*y*z) t_index begin id */ | 
					
						
							|  |  |  | 	int *s_num; /* (x*y*z) number of t_index points */ | 
					
						
							|  |  |  | 	int *t_index; /* actual surface point index,
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 	               * access: (s_pos+s_num) */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | } VolumeGrid; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct Vec3f { | 
					
						
							|  |  |  | 	float v[3]; | 
					
						
							|  |  |  | } Vec3f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | typedef struct BakeAdjPoint { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float dir[3];   /* vector pointing towards this neighbor */ | 
					
						
							|  |  |  | 	float dist;     /* distance to */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | } BakeAdjPoint; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* Surface data used while processing a frame	*/ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | typedef struct PaintBakeNormal { | 
					
						
							|  |  |  | 	float invNorm[3];  /* current pixel world-space inverted normal */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	float normal_scale; /* normal directional scale for displace mapping */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | } PaintBakeNormal; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | /* Temp surface data used to process a frame */ | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | typedef struct PaintBakeData { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	/* point space data */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeNormal *bNormal; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int *s_pos; /* index to start reading point sample realCoord */ | 
					
						
							|  |  |  | 	int *s_num; /* num of realCoord samples */ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | 	Vec3f *realCoord;  /* current pixel center world-space coordinates for each sample
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	                    *  ordered as (s_pos+s_num)*/ | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	Bounds3D mesh_bounds; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | 	/* adjacency info */ | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs; /* current global neighbor distances and directions, if required */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	double average_dist; | 
					
						
							|  |  |  | 	/* space partitioning */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	VolumeGrid *grid;       /* space partitioning grid to optimize brush checks */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	/* velocity and movement */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	Vec3f *velocity;        /* speed vector in global space movement per frame, if required */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	Vec3f *prev_velocity; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float *brush_velocity;  /* special temp data for post-p velocity based brushes like smudge
 | 
					
						
							|  |  |  | 	                         *  3 float dir vec + 1 float str */ | 
					
						
							|  |  |  | 	MVert *prev_verts;      /* copy of previous frame vertices. used to observe surface movement */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	float prev_obmat[4][4]; /* previous frame object matrix */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int clear;              /* flag to check if surface was cleared/reset -> have to redo velocity etc. */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | } PaintBakeData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* UV Image sequence format point	*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | typedef struct PaintUVPoint { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Pixel / mesh data */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	unsigned int face_index, pixel_index;   /* face index on domain derived mesh */ | 
					
						
							|  |  |  | 	unsigned int v1, v2, v3;                /* vertex indexes */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	unsigned int neighbour_pixel;   /* If this pixel isn't uv mapped to any face,
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 	                                 * but it's neighboring pixel is */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	short quad; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | } PaintUVPoint; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct ImgSeqFormatData { | 
					
						
							|  |  |  | 	PaintUVPoint *uv_p; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	Vec3f *barycentricWeights;      /* b-weights for all pixel samples */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | } ImgSeqFormatData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | /* adjacency data flags */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | #define ADJ_ON_MESH_EDGE (1 << 0)
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct PaintAdjData { | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 	int *n_target;  /* array of neighboring point indexes,
 | 
					
						
							|  |  |  | 	                 * for single sample use (n_index + neigh_num) */ | 
					
						
							|  |  |  | 	int *n_index;   /* index to start reading n_target for each point */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int *n_num;     /* num of neighs for each point */ | 
					
						
							|  |  |  | 	int *flags;     /* vertex adjacency flags */ | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 	int total_targets; /* size of n_target */ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | } PaintAdjData; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************** General Utils ******************************/ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | /* Set canvas error string to display at the bake report */ | 
					
						
							| 
									
										
										
										
											2011-11-10 12:28:26 +00:00
										 |  |  | static int setError(DynamicPaintCanvasSettings *canvas, const char *string) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Add error to canvas ui info label */ | 
					
						
							| 
									
										
										
										
											2011-11-13 13:56:40 +00:00
										 |  |  | 	BLI_strncpy(canvas->error, string, sizeof(canvas->error)); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* Get number of surface points for cached types */ | 
					
						
							|  |  |  | static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) { | 
					
						
							|  |  |  | 		return 0; /* not supported atm */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (!surface->canvas->dm) return 0;  /* invalid derived mesh */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		return surface->canvas->dm->getNumVerts(surface->canvas->dm); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* checks whether surface's format/type has realtime preview */ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2011-07-03 14:01:57 +00:00
										 |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		    surface->type == MOD_DPAINT_SURFACE_T_WAVE) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* get currently active surface (in user interface) */ | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	DynamicPaintSurface *surface = canvas->surfaces.first; | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (i == canvas->active_sur) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			return surface; | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* set preview to first previewable surface */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | void dynamicPaint_resetPreview(DynamicPaintCanvasSettings *canvas) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	DynamicPaintSurface *surface = canvas->surfaces.first; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:28:19 +00:00
										 |  |  | 	int done = FALSE; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2011-07-03 14:01:57 +00:00
										 |  |  | 		if (!done && dynamicPaint_surfaceHasColorPreview(surface)) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			surface->flags |= MOD_DPAINT_PREVIEW; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:28:19 +00:00
										 |  |  | 			done = TRUE; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			surface->flags &= ~MOD_DPAINT_PREVIEW; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | /* set preview to defined surface */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | static void dynamicPaint_setPreview(DynamicPaintSurface *t_surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	DynamicPaintSurface *surface = t_surface->canvas->surfaces.first; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		if (surface == t_surface) | 
					
						
							|  |  |  | 			surface->flags |= MOD_DPAINT_PREVIEW; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			surface->flags &= ~MOD_DPAINT_PREVIEW; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-14 06:46:07 +00:00
										 |  |  | int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *ob, int output) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-14 06:46:07 +00:00
										 |  |  | 	if (output == 0) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		name = surface->output_name; | 
					
						
							| 
									
										
										
										
											2011-11-14 06:46:07 +00:00
										 |  |  | 	else if (output == 1) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		name = surface->output_name2; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							|  |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							|  |  |  | 			Mesh *me = ob->data; | 
					
						
							|  |  |  | 			return (CustomData_get_named_layer_index(&me->fdata, CD_MCOL, name) != -1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) | 
					
						
							|  |  |  | 			return (defgroup_name_index(ob, surface->output_name) != -1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | static bool surface_duplicateOutputExists(void *arg, const char *name) | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	DynamicPaintSurface *surface = t_surface->canvas->surfaces.first; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; surface; surface = surface->next) { | 
					
						
							|  |  |  | 		if (surface != t_surface && surface->type == t_surface->type && | 
					
						
							|  |  |  | 		    surface->format == t_surface->format) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | 			if (surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) return true; | 
					
						
							|  |  |  | 			if (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)) return true; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-14 16:05:44 +00:00
										 |  |  | static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output) | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char name[64]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */ | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	if (!output) | 
					
						
							|  |  |  | 		BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name, sizeof(surface->output_name)); | 
					
						
							|  |  |  | 	if (output) | 
					
						
							|  |  |  | 		BLI_uniquename_cb(surface_duplicateOutputExists, surface, name, '.', surface->output_name2, sizeof(surface->output_name2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | static bool surface_duplicateNameExists(void *arg, const char *name) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	DynamicPaintSurface *surface = t_surface->canvas->surfaces.first; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | 		if (surface != t_surface && !strcmp(name, surface->name)) return true; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 12:28:26 +00:00
										 |  |  | void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename) | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	char name[64]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */ | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	BLI_uniquename_cb(surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* change surface data to defaults on new type */ | 
					
						
							|  |  |  | void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		surface->output_name[0] = '\0'; | 
					
						
							|  |  |  | 		surface->output_name2[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 		surface->flags |= MOD_DPAINT_ANTIALIAS; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		surface->depth_clamp = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-01-11 12:33:51 +00:00
										 |  |  | 		strcpy(surface->output_name, "dp_"); | 
					
						
							| 
									
										
										
										
											2012-12-16 08:43:05 +00:00
										 |  |  | 		BLI_strncpy(surface->output_name2, surface->output_name, sizeof(surface->output_name2)); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 		surface->flags &= ~MOD_DPAINT_ANTIALIAS; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		surface->depth_clamp = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		strcat(surface->output_name, "paintmap"); | 
					
						
							|  |  |  | 		strcat(surface->output_name2, "wetmap"); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 		surface_setUniqueOutputName(surface, surface->output_name2, 1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		strcat(surface->output_name, "displace"); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		strcat(surface->output_name, "weight"); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		strcat(surface->output_name, "wave"); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	surface_setUniqueOutputName(surface, surface->output_name, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* update preview */ | 
					
						
							|  |  |  | 	if (dynamicPaint_surfaceHasColorPreview(surface)) | 
					
						
							|  |  |  | 		dynamicPaint_setPreview(surface); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		dynamicPaint_resetPreview(surface->canvas); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static int surface_totalSamples(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ && | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	    surface->flags & MOD_DPAINT_ANTIALIAS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return (surface->data->total_points * 5); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX && | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	    surface->flags & MOD_DPAINT_ANTIALIAS && surface->data->adj_data) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		return (surface->data->total_points + surface->data->adj_data->total_targets); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return surface->data->total_points; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 22:13:38 +00:00
										 |  |  | static void blendColors(const float t_color[3], float t_alpha, const float s_color[3], float s_alpha, float result[4]) | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	float i_alpha = 1.0f - s_alpha; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float f_alpha = t_alpha * i_alpha + s_alpha; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* blend colors */ | 
					
						
							|  |  |  | 	if (f_alpha) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 			result[i] = (t_color[i] * t_alpha * i_alpha + s_color[i] * s_alpha) / f_alpha; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		copy_v3_v3(result, t_color); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* return final alpha */ | 
					
						
							|  |  |  | 	result[3] = f_alpha; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | /* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */ | 
					
						
							|  |  |  | static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio) | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	float weight_ratio, factor; | 
					
						
							|  |  |  | 	if (b_weight) { | 
					
						
							|  |  |  | 		/* if first value has no weight just use b_color */ | 
					
						
							|  |  |  | 		if (!a_weight) { | 
					
						
							|  |  |  | 			copy_v3_v3(a_color, b_color); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			return b_weight * ratio; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		weight_ratio = b_weight / (a_weight + b_weight); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-09 03:46:30 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		return a_weight * (1.0f - ratio); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	/* calculate final interpolation factor */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	if (ratio <= 0.5f) { | 
					
						
							|  |  |  | 		factor = weight_ratio * (ratio * 2.0f); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		ratio = (ratio * 2.0f - 1.0f); | 
					
						
							|  |  |  | 		factor = weight_ratio * (1.0f - ratio) + ratio; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	/* mix final color */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	interp_v3_v3v3(a_color, a_color, b_color, factor); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	return (1.0f - factor) * a_weight + factor * b_weight; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | /* set "ignore cache" flag for all caches on this object */ | 
					
						
							|  |  |  | static void object_cacheIgnoreClear(Object *ob, int state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ListBase pidlist; | 
					
						
							|  |  |  | 	PTCacheID *pid; | 
					
						
							|  |  |  | 	BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (pid = pidlist.first; pid; pid = pid->next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (pid->cache) { | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 			if (state) | 
					
						
							|  |  |  | 				pid->cache->flag |= PTCACHE_IGNORE_CLEAR; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_freelistN(&pidlist); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | static int subframe_updateObject(Scene *scene, Object *ob, int flags, int parent_recursion, float frame) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 	bConstraint *con; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	/* if other is dynamic paint canvas, don't update */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (pmd && pmd->canvas) | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 	/* if object has parents, update them too */ | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 	if (parent_recursion) { | 
					
						
							| 
									
										
										
										
											2013-03-25 02:41:30 +00:00
										 |  |  | 		int recursion = parent_recursion - 1; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 		int is_canvas = 0; | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 		if (ob->parent) is_canvas += subframe_updateObject(scene, ob->parent, 0, recursion, frame); | 
					
						
							|  |  |  | 		if (ob->track) is_canvas += subframe_updateObject(scene, ob->track, 0, recursion, frame); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* skip subframe if object is parented
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  to vertex of a dynamic paint canvas */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 		if (is_canvas && (ob->partype == PARVERT1 || ob->partype == PARVERT3)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* also update constraint targets */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (con = ob->constraints.first; con; con = con->next) { | 
					
						
							| 
									
										
										
										
											2012-12-23 11:31:15 +00:00
										 |  |  | 			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 			ListBase targets = {NULL, NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (cti && cti->get_constraint_targets) { | 
					
						
							|  |  |  | 				bConstraintTarget *ct; | 
					
						
							|  |  |  | 				cti->get_constraint_targets(con, &targets); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (ct = targets.first; ct; ct = ct->next) { | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 					if (ct->tar) | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 						subframe_updateObject(scene, ct->tar, 0, recursion, frame); | 
					
						
							| 
									
										
										
										
											2011-12-05 13:36:41 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				/* free temp targets */ | 
					
						
							|  |  |  | 				if (cti->flush_constraint_targets) | 
					
						
							|  |  |  | 					cti->flush_constraint_targets(con, &targets, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-27 00:01:35 +00:00
										 |  |  | 	/* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */ | 
					
						
							|  |  |  | 	ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; | 
					
						
							| 
									
										
										
										
											2011-09-05 17:06:09 +00:00
										 |  |  | 	BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM); | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 	if (flags & UPDATE_MESH) { | 
					
						
							|  |  |  | 		/* ignore cache clear during subframe updates
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  to not mess up cache validity */ | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 		object_cacheIgnoreClear(ob, 1); | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 		BKE_object_handle_update(scene, ob); | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 		object_cacheIgnoreClear(ob, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 		BKE_object_where_is_calc_time(scene, ob, frame); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-29 11:19:29 +00:00
										 |  |  | 	/* for curve following objects, parented curve has to be updated too */ | 
					
						
							|  |  |  | 	if (ob->type == OB_CURVE) { | 
					
						
							|  |  |  | 		Curve *cu = ob->data; | 
					
						
							|  |  |  | 		BKE_animsys_evaluate_animdata(scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* and armatures... */ | 
					
						
							|  |  |  | 	if (ob->type == OB_ARMATURE) { | 
					
						
							|  |  |  | 		bArmature *arm = ob->data; | 
					
						
							|  |  |  | 		BKE_animsys_evaluate_animdata(scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM); | 
					
						
							|  |  |  | 		BKE_pose_where_is(scene, ob); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void scene_setSubframe(Scene *scene, float subframe) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* dynamic paint subframes must be done on previous frame */ | 
					
						
							|  |  |  | 	scene->r.cfra -= 1; | 
					
						
							|  |  |  | 	scene->r.subframe = subframe; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Base *base = NULL; | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  | 	GroupObject *go = NULL; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	Object *brushObj = NULL; | 
					
						
							|  |  |  | 	ModifierData *md = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int flags = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (surface->brush_group) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		go = surface->brush_group->gobject.first; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		base = scene->base.first; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	while (base || go) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		brushObj = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* select object */ | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 		if (surface->brush_group) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (go->ob) brushObj = go->ob; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			brushObj = base->object; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		if (!brushObj) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 			if (surface->brush_group) go = go->next; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			else base = base->next; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (surface->brush_group) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			go = go->next; | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			base = base->next; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			if (pmd2->brush) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				DynamicPaintBrushSettings *brush = pmd2->brush; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (brush->flags & MOD_DPAINT_USES_VELOCITY) | 
					
						
							|  |  |  | 					flags |= BRUSH_USES_VELOCITY; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return flags; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-09 15:46:53 +00:00
										 |  |  | static int brush_usesMaterial(DynamicPaintBrushSettings *brush, Scene *scene) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ((brush->flags & MOD_DPAINT_USE_MATERIAL) && (!strcmp(scene->r.engine, "BLENDER_RENDER"))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* check whether two bounds intersect */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static int boundsIntersect(Bounds3D *b1, Bounds3D *b2) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int i = 2; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	if (!b1->valid || !b2->valid) return 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; i >= 0; i -= 1) | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) return 0; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* check whether two bounds intersect inside defined proximity */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int i = 2; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	if (!b1->valid || !b2->valid) return 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; i >= 0; i -= 1) | 
					
						
							|  |  |  | 		if (!(b1->min[i] <= (b2->max[i] + dist) && b1->max[i] >= (b2->min[i] - dist))) return 0; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* check whether bounds intersects a point with given radius */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static int boundIntersectPoint(Bounds3D *b, float point[3], float radius) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int i = 2; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	if (!b->valid) return 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (; i >= 0; i -= 1) | 
					
						
							|  |  |  | 		if (!(b->min[i] <= (point[i] + radius) && b->max[i] >= (point[i] - radius))) return 0; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* expand bounds by a new point */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static void boundInsert(Bounds3D *b, float point[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	int i = 2; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	if (!b->valid) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		copy_v3_v3(b->min, point); | 
					
						
							|  |  |  | 		copy_v3_v3(b->max, point); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		b->valid = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (; i >= 0; i -= 1) { | 
					
						
							|  |  |  | 			if (point[i] < b->min[i]) b->min[i] = point[i]; | 
					
						
							|  |  |  | 			if (point[i] > b->max[i]) b->max[i] = point[i]; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static float getSurfaceDimension(PaintSurfaceData *sData) | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Bounds3D *mb = &sData->bData->mesh_bounds; | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 	return max_fff((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2])); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static void freeGrid(PaintSurfaceData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintBakeData *bData = data->bData; | 
					
						
							|  |  |  | 	VolumeGrid *grid = bData->grid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (grid->bounds) MEM_freeN(grid->bounds); | 
					
						
							|  |  |  | 	if (grid->s_pos) MEM_freeN(grid->s_pos); | 
					
						
							|  |  |  | 	if (grid->s_num) MEM_freeN(grid->s_num); | 
					
						
							|  |  |  | 	if (grid->t_index) MEM_freeN(grid->t_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(bData->grid); | 
					
						
							|  |  |  | 	bData->grid = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							|  |  |  | 	Bounds3D *grid_bounds; | 
					
						
							|  |  |  | 	VolumeGrid *grid; | 
					
						
							|  |  |  | 	int grid_cells, axis = 3; | 
					
						
							|  |  |  | 	int *temp_t_index = NULL; | 
					
						
							|  |  |  | 	int *temp_s_num = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef _OPENMP
 | 
					
						
							|  |  |  | 	int num_of_threads = omp_get_max_threads(); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	int num_of_threads = 1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bData->grid) | 
					
						
							|  |  |  | 		freeGrid(sData); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate separate bounds for each thread */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	grid_bounds = MEM_callocN(sizeof(Bounds3D) * num_of_threads, "Grid Bounds"); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	bData->grid = MEM_callocN(sizeof(VolumeGrid), "Surface Grid"); | 
					
						
							|  |  |  | 	grid = bData->grid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (grid && grid_bounds) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		int i, error = 0; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		float dim_factor, volume, dim[3]; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		float td[3]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		float min_dim; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* calculate canvas dimensions */ | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			#ifdef _OPENMP
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int id = omp_get_thread_num(); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			boundInsert(&grid_bounds[id], (bData->realCoord[bData->s_pos[i]].v)); | 
					
						
							|  |  |  | 			#else
 | 
					
						
							|  |  |  | 			boundInsert(&grid_bounds[0], (bData->realCoord[bData->s_pos[i]].v)); | 
					
						
							|  |  |  | 			#endif
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* get final dimensions */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < num_of_threads; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			boundInsert(&grid->grid_bounds, grid_bounds[i].min); | 
					
						
							|  |  |  | 			boundInsert(&grid->grid_bounds, grid_bounds[i].max); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		/* get dimensions */ | 
					
						
							|  |  |  | 		sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min); | 
					
						
							|  |  |  | 		copy_v3_v3(td, dim); | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 		min_dim = max_fff(td[0], td[1], td[2]) / 1000.f; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* deactivate zero axises */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < 3; i++) { | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 			if (td[i] < min_dim) { td[i] = 1.0f; axis -= 1; } | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 		if (axis == 0 || max_fff(td[0], td[1], td[2]) < 0.0001f) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			MEM_freeN(grid_bounds); | 
					
						
							|  |  |  | 			MEM_freeN(bData->grid); | 
					
						
							|  |  |  | 			bData->grid = NULL; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		/* now calculate grid volume/area/width depending on num of active axis */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		volume = td[0] * td[1] * td[2]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* determine final grid size by trying to fit average 10.000 points per grid cell */ | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 		dim_factor = (float)pow((double)volume / ((double)sData->total_points / 10000.0), 1.0 / (double)axis); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* define final grid size using dim_factor, use min 3 for active axises */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < 3; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			grid->dim[i] = (int)floor(td[i] / dim_factor); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			CLAMP(grid->dim[i], (dim[i] >= min_dim) ? 3 : 1, 100); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* allocate memory for grids */ | 
					
						
							|  |  |  | 		grid->bounds = MEM_callocN(sizeof(Bounds3D) * grid_cells, "Surface Grid Bounds"); | 
					
						
							|  |  |  | 		grid->s_pos = MEM_callocN(sizeof(int) * grid_cells, "Surface Grid Position"); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		grid->s_num = MEM_callocN(sizeof(int) * grid_cells * num_of_threads, "Surface Grid Points"); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		temp_s_num = MEM_callocN(sizeof(int) * grid_cells, "Temp Surface Grid Points"); | 
					
						
							|  |  |  | 		grid->t_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Grid Target Ids"); | 
					
						
							|  |  |  | 		temp_t_index = MEM_callocN(sizeof(int) * sData->total_points, "Temp Surface Grid Target Ids"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-04 04:35:12 +00:00
										 |  |  | 		/* in case of an allocation failure abort here */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		if (!grid->bounds || !grid->s_pos || !grid->s_num || !grid->t_index || !temp_s_num || !temp_t_index) | 
					
						
							|  |  |  | 			error = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!error) { | 
					
						
							|  |  |  | 			/* calculate number of points withing each cell */ | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				int co[3], j; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (j = 0; j < 3; j++) { | 
					
						
							|  |  |  | 					co[j] = (int)floor((bData->realCoord[bData->s_pos[i]].v[j] - grid->grid_bounds.min[j]) / dim[j] * grid->dim[j]); | 
					
						
							|  |  |  | 					CLAMP(co[j], 0, grid->dim[j] - 1); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				temp_t_index[i] = co[0] + co[1] * grid->dim[0] + co[2] * grid->dim[0] * grid->dim[1]; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				#ifdef _OPENMP
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				grid->s_num[temp_t_index[i] + omp_get_thread_num() * grid_cells]++; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				#else
 | 
					
						
							|  |  |  | 				grid->s_num[temp_t_index[i]]++; | 
					
						
							|  |  |  | 				#endif
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* for first cell only calc s_num */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 1; i < num_of_threads; i++) { | 
					
						
							|  |  |  | 				grid->s_num[0] += grid->s_num[i * grid_cells]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* calculate grid indexes */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 1; i < grid_cells; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				int id; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (id = 1; id < num_of_threads; id++) { | 
					
						
							|  |  |  | 					grid->s_num[i] += grid->s_num[i + id * grid_cells]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				grid->s_pos[i] = grid->s_pos[i - 1] + grid->s_num[i - 1]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* save point indexes to final array */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				int pos = grid->s_pos[temp_t_index[i]] + temp_s_num[temp_t_index[i]]; | 
					
						
							|  |  |  | 				grid->t_index[pos] = i; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 				temp_s_num[temp_t_index[i]]++; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* calculate cell bounds */ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int x; | 
					
						
							|  |  |  | 				#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (x = 0; x < grid->dim[0]; x++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					int y; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					for (y = 0; y < grid->dim[1]; y++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						int z; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						for (z = 0; z < grid->dim[2]; z++) { | 
					
						
							|  |  |  | 							int j, b_index = x + y * grid->dim[0] + z * grid->dim[0] * grid->dim[1]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 							/* set bounds */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (j = 0; j < 3; j++) { | 
					
						
							|  |  |  | 								int s = (j == 0) ? x : ((j == 1) ? y : z); | 
					
						
							|  |  |  | 								grid->bounds[b_index].min[j] = grid->grid_bounds.min[j] + dim[j] / grid->dim[j] * s; | 
					
						
							|  |  |  | 								grid->bounds[b_index].max[j] = grid->grid_bounds.min[j] + dim[j] / grid->dim[j] * (s + 1); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 							grid->bounds[b_index].valid = 1; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (temp_s_num) MEM_freeN(temp_s_num); | 
					
						
							|  |  |  | 		if (temp_t_index) MEM_freeN(temp_t_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* free per thread s_num values */ | 
					
						
							|  |  |  | 		grid->s_num = MEM_reallocN(grid->s_num, sizeof(int) * grid_cells); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		if (error || !grid->s_num) { | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 			setError(surface->canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			freeGrid(sData); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (grid_bounds) MEM_freeN(grid_bounds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /***************************** Freeing data ******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free brush data */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd->brush) { | 
					
						
							|  |  |  | 		if (pmd->brush->dm) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			pmd->brush->dm->release(pmd->brush->dm); | 
					
						
							|  |  |  | 		pmd->brush->dm = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (pmd->brush->paint_ramp) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			MEM_freeN(pmd->brush->paint_ramp); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		pmd->brush->paint_ramp = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (pmd->brush->vel_ramp) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			MEM_freeN(pmd->brush->vel_ramp); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		pmd->brush->vel_ramp = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(pmd->brush); | 
					
						
							|  |  |  | 		pmd->brush = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | static void dynamicPaint_freeAdjData(PaintSurfaceData *data) | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	if (data->adj_data) { | 
					
						
							|  |  |  | 		if (data->adj_data->n_index) MEM_freeN(data->adj_data->n_index); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		if (data->adj_data->n_num) MEM_freeN(data->adj_data->n_num); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		if (data->adj_data->n_target) MEM_freeN(data->adj_data->n_target); | 
					
						
							|  |  |  | 		if (data->adj_data->flags) MEM_freeN(data->adj_data->flags); | 
					
						
							|  |  |  | 		MEM_freeN(data->adj_data); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		data->adj_data = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static void free_bakeData(PaintSurfaceData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintBakeData *bData = data->bData; | 
					
						
							|  |  |  | 	if (bData) { | 
					
						
							|  |  |  | 		if (bData->bNormal) MEM_freeN(bData->bNormal); | 
					
						
							|  |  |  | 		if (bData->s_pos) MEM_freeN(bData->s_pos); | 
					
						
							|  |  |  | 		if (bData->s_num) MEM_freeN(bData->s_num); | 
					
						
							|  |  |  | 		if (bData->realCoord) MEM_freeN(bData->realCoord); | 
					
						
							|  |  |  | 		if (bData->bNeighs) MEM_freeN(bData->bNeighs); | 
					
						
							|  |  |  | 		if (bData->grid) freeGrid(data); | 
					
						
							|  |  |  | 		if (bData->prev_verts) MEM_freeN(bData->prev_verts); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		if (bData->velocity) MEM_freeN(bData->velocity); | 
					
						
							|  |  |  | 		if (bData->prev_velocity) MEM_freeN(bData->prev_velocity); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(data->bData); | 
					
						
							|  |  |  | 		data->bData = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | /* free surface data if it's not used anymore */ | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void surface_freeUnusedData(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!surface->data) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free bakedata if not active or surface is baked */ | 
					
						
							|  |  |  | 	if (!(surface->flags & MOD_DPAINT_ACTIVE) || | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	    (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | 		free_bakeData(surface->data); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *data = surface->data; | 
					
						
							|  |  |  | 	if (!data) return; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if (data->format_data) { | 
					
						
							|  |  |  | 		/* format specific free */ | 
					
						
							|  |  |  | 		if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			ImgSeqFormatData *format_data = (ImgSeqFormatData *)data->format_data; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			if (format_data->uv_p) | 
					
						
							|  |  |  | 				MEM_freeN(format_data->uv_p); | 
					
						
							|  |  |  | 			if (format_data->barycentricWeights) | 
					
						
							|  |  |  | 				MEM_freeN(format_data->barycentricWeights); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		MEM_freeN(data->format_data); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	/* type data */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	if (data->type_data) MEM_freeN(data->type_data); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	dynamicPaint_freeAdjData(data); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	/* bake data */ | 
					
						
							|  |  |  | 	free_bakeData(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	MEM_freeN(surface->data); | 
					
						
							|  |  |  | 	surface->data = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | void dynamicPaint_freeSurface(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* point cache */ | 
					
						
							|  |  |  | 	BKE_ptcache_free_list(&(surface->ptcaches)); | 
					
						
							|  |  |  | 	surface->pointcache = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (surface->effector_weights) | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		MEM_freeN(surface->effector_weights); | 
					
						
							|  |  |  | 	surface->effector_weights = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	BLI_remlink(&(surface->canvas->surfaces), surface); | 
					
						
							|  |  |  | 	dynamicPaint_freeSurfaceData(surface); | 
					
						
							|  |  |  | 	MEM_freeN(surface); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free canvas data */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd->canvas) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/* Free surface data */ | 
					
						
							|  |  |  | 		DynamicPaintSurface *surface = pmd->canvas->surfaces.first; | 
					
						
							|  |  |  | 		DynamicPaintSurface *next_surface = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (surface) { | 
					
						
							|  |  |  | 			next_surface = surface->next; | 
					
						
							|  |  |  | 			dynamicPaint_freeSurface(surface); | 
					
						
							|  |  |  | 			surface = next_surface; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* free dm copy */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		if (pmd->canvas->dm) | 
					
						
							|  |  |  | 			pmd->canvas->dm->release(pmd->canvas->dm); | 
					
						
							|  |  |  | 		pmd->canvas->dm = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(pmd->canvas); | 
					
						
							|  |  |  | 		pmd->canvas = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* Free whole dp modifier */ | 
					
						
							|  |  |  | void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		dynamicPaint_freeCanvas(pmd); | 
					
						
							|  |  |  | 		dynamicPaint_freeBrush(pmd); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************** Initialize and reset ******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  * Creates a new surface and adds it to the list | 
					
						
							|  |  |  |  * If scene is null, frame range of 1-250 is used | 
					
						
							|  |  |  |  * A pointer to this surface is returned | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	DynamicPaintSurface *surface = MEM_callocN(sizeof(DynamicPaintSurface), "DynamicPaintSurface"); | 
					
						
							| 
									
										
										
										
											2013-03-25 08:29:06 +00:00
										 |  |  | 	if (!surface) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	surface->canvas = canvas; | 
					
						
							|  |  |  | 	surface->format = MOD_DPAINT_SURFACE_F_VERTEX; | 
					
						
							|  |  |  | 	surface->type = MOD_DPAINT_SURFACE_T_PAINT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* cache */ | 
					
						
							|  |  |  | 	surface->pointcache = BKE_ptcache_add(&(surface->ptcaches)); | 
					
						
							|  |  |  | 	surface->pointcache->flag |= PTCACHE_DISK_CACHE; | 
					
						
							|  |  |  | 	surface->pointcache->step = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Set initial values */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG | | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	                 MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	surface->effect = 0; | 
					
						
							|  |  |  | 	surface->effect_ui = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 	surface->diss_speed = 250; | 
					
						
							|  |  |  | 	surface->dry_speed = 500; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	surface->color_dry_threshold = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	surface->depth_clamp = 0.0f; | 
					
						
							|  |  |  | 	surface->disp_factor = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	surface->disp_type = MOD_DPAINT_DISP_DISPLACE; | 
					
						
							|  |  |  | 	surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	surface->influence_scale = 1.0f; | 
					
						
							|  |  |  | 	surface->radius_scale = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	surface->init_color[0] = 1.0f; | 
					
						
							|  |  |  | 	surface->init_color[1] = 1.0f; | 
					
						
							|  |  |  | 	surface->init_color[2] = 1.0f; | 
					
						
							|  |  |  | 	surface->init_color[3] = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	surface->image_resolution = 256; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 	surface->substeps = 0; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (scene) { | 
					
						
							|  |  |  | 		surface->start_frame = scene->r.sfra; | 
					
						
							|  |  |  | 		surface->end_frame = scene->r.efra; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		surface->start_frame = 1; | 
					
						
							|  |  |  | 		surface->end_frame = 250; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	surface->spread_speed = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	surface->color_spread_speed = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	surface->shrink_speed = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	surface->wave_damping = 0.04f; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 	surface->wave_speed = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	surface->wave_timescale = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 	surface->wave_spring = 0.20f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 10:04:28 +00:00
										 |  |  | 	modifier_path_init(surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint"); | 
					
						
							| 
									
										
										
										
											2011-11-20 14:38:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-25 08:29:06 +00:00
										 |  |  | 	/* Using ID_BRUSH i18n context, as we have no physics/dpaint one for now... */ | 
					
						
							|  |  |  | 	dynamicPaintSurface_setUniqueName(surface, CTX_DATA_(BLF_I18NCONTEXT_ID_BRUSH, "Surface")); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	surface->effector_weights = BKE_add_effector_weights(NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	dynamicPaintSurface_updateType(surface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_addtail(&canvas->surfaces, surface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return surface; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  * Initialize modifier data | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd) { | 
					
						
							|  |  |  | 		if (type == MOD_DYNAMICPAINT_TYPE_CANVAS) { | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			DynamicPaintCanvasSettings *canvas; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 			if (pmd->canvas) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				dynamicPaint_freeCanvas(pmd); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas"); | 
					
						
							|  |  |  | 			if (!canvas) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			canvas->pmd = pmd; | 
					
						
							|  |  |  | 			canvas->dm = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			/* Create one surface */ | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			if (!dynamicPaint_createNewSurface(canvas, scene)) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH) { | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			DynamicPaintBrushSettings *brush; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 			if (pmd->brush) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				dynamicPaint_freeBrush(pmd); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint"); | 
					
						
							|  |  |  | 			if (!brush) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->pmd = pmd; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->psys = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA; | 
					
						
							|  |  |  | 			brush->collision = MOD_DPAINT_COL_VOLUME; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->mat = NULL; | 
					
						
							|  |  |  | 			brush->r = 0.15f; | 
					
						
							|  |  |  | 			brush->g = 0.4f; | 
					
						
							|  |  |  | 			brush->b = 0.8f; | 
					
						
							|  |  |  | 			brush->alpha = 1.0f; | 
					
						
							|  |  |  | 			brush->wetness = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->paint_distance = 1.0f; | 
					
						
							|  |  |  | 			brush->proximity_falloff = MOD_DPAINT_PRFALL_SMOOTH; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->particle_radius = 0.2f; | 
					
						
							|  |  |  | 			brush->particle_smooth = 0.05f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 			brush->wave_type = MOD_DPAINT_WAVEB_CHANGE; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->wave_factor = 1.0f; | 
					
						
							|  |  |  | 			brush->wave_clamp = 0.0f; | 
					
						
							|  |  |  | 			brush->smudge_strength = 0.3f; | 
					
						
							|  |  |  | 			brush->max_velocity = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			brush->dm = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			/* Paint proximity falloff colorramp. */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				CBData *ramp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-18 18:25:05 +00:00
										 |  |  | 				brush->paint_ramp = add_colorband(false); | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 				if (!brush->paint_ramp) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 					return 0; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 				ramp = brush->paint_ramp->data; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 				/* Add default smooth-falloff ramp.	*/ | 
					
						
							|  |  |  | 				ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f; | 
					
						
							|  |  |  | 				ramp[0].pos = 0.0f; | 
					
						
							|  |  |  | 				ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].pos = 1.0f; | 
					
						
							|  |  |  | 				ramp[1].a = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				pmd->brush->paint_ramp->tot = 2; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* Brush velocity ramp. */ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				CBData *ramp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-18 18:25:05 +00:00
										 |  |  | 				brush->vel_ramp = add_colorband(false); | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 				if (!brush->vel_ramp) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					return 0; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 				ramp = brush->vel_ramp->data; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f; | 
					
						
							|  |  |  | 				ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 				brush->paint_ramp->tot = 2; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Init modifier	*/ | 
					
						
							|  |  |  | 	tpmd->type = pmd->type; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	if (pmd->canvas) | 
					
						
							|  |  |  | 		dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_CANVAS, NULL); | 
					
						
							|  |  |  | 	if (pmd->brush) | 
					
						
							|  |  |  | 		dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_BRUSH, NULL); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Copy data	*/ | 
					
						
							|  |  |  | 	if (tpmd->canvas) { | 
					
						
							| 
									
										
										
										
											2012-12-16 19:19:45 +00:00
										 |  |  | 		DynamicPaintSurface *surface; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		tpmd->canvas->pmd = tpmd; | 
					
						
							| 
									
										
										
										
											2012-12-16 19:19:45 +00:00
										 |  |  | 		/* free default surface */ | 
					
						
							|  |  |  | 		if (tpmd->canvas->surfaces.first) | 
					
						
							|  |  |  | 			dynamicPaint_freeSurface(tpmd->canvas->surfaces.first); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* copy existing surfaces */ | 
					
						
							|  |  |  | 		for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { | 
					
						
							|  |  |  | 			DynamicPaintSurface *t_surface = dynamicPaint_createNewSurface(tpmd->canvas, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* surface settings */ | 
					
						
							|  |  |  | 			t_surface->brush_group = surface->brush_group; | 
					
						
							|  |  |  | 			MEM_freeN(t_surface->effector_weights); | 
					
						
							|  |  |  | 			t_surface->effector_weights = MEM_dupallocN(surface->effector_weights); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->name, surface->name, sizeof(t_surface->name)); | 
					
						
							|  |  |  | 			t_surface->format = surface->format; | 
					
						
							|  |  |  | 			t_surface->type = surface->type; | 
					
						
							|  |  |  | 			t_surface->disp_type = surface->disp_type; | 
					
						
							|  |  |  | 			t_surface->image_fileformat = surface->image_fileformat; | 
					
						
							|  |  |  | 			t_surface->effect_ui = surface->effect_ui; | 
					
						
							|  |  |  | 			t_surface->preview_id = surface->preview_id; | 
					
						
							|  |  |  | 			t_surface->init_color_type = surface->init_color_type; | 
					
						
							|  |  |  | 			t_surface->flags = surface->flags; | 
					
						
							|  |  |  | 			t_surface->effect = surface->effect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t_surface->image_resolution = surface->image_resolution; | 
					
						
							|  |  |  | 			t_surface->substeps = surface->substeps; | 
					
						
							|  |  |  | 			t_surface->start_frame = surface->start_frame; | 
					
						
							|  |  |  | 			t_surface->end_frame = surface->end_frame; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			copy_v4_v4(t_surface->init_color, surface->init_color); | 
					
						
							|  |  |  | 			t_surface->init_texture = surface->init_texture; | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->init_layername, surface->init_layername, sizeof(t_surface->init_layername)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t_surface->dry_speed = surface->dry_speed; | 
					
						
							|  |  |  | 			t_surface->diss_speed = surface->diss_speed; | 
					
						
							|  |  |  | 			t_surface->color_dry_threshold = surface->color_dry_threshold; | 
					
						
							|  |  |  | 			t_surface->depth_clamp = surface->depth_clamp; | 
					
						
							|  |  |  | 			t_surface->disp_factor = surface->disp_factor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t_surface->spread_speed = surface->spread_speed; | 
					
						
							|  |  |  | 			t_surface->color_spread_speed = surface->color_spread_speed; | 
					
						
							|  |  |  | 			t_surface->shrink_speed = surface->shrink_speed; | 
					
						
							|  |  |  | 			t_surface->drip_vel = surface->drip_vel; | 
					
						
							|  |  |  | 			t_surface->drip_acc = surface->drip_acc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t_surface->influence_scale = surface->influence_scale; | 
					
						
							|  |  |  | 			t_surface->radius_scale = surface->radius_scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t_surface->wave_damping = surface->wave_damping; | 
					
						
							|  |  |  | 			t_surface->wave_speed = surface->wave_speed; | 
					
						
							|  |  |  | 			t_surface->wave_timescale = surface->wave_timescale; | 
					
						
							|  |  |  | 			t_surface->wave_spring = surface->wave_spring; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->uvlayer_name, surface->uvlayer_name, sizeof(t_surface->uvlayer_name)); | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->image_output_path, surface->image_output_path, sizeof(t_surface->image_output_path)); | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->output_name, surface->output_name, sizeof(t_surface->output_name)); | 
					
						
							|  |  |  | 			BLI_strncpy(t_surface->output_name2, surface->output_name2, sizeof(t_surface->output_name2)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		dynamicPaint_resetPreview(tpmd->canvas); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (tpmd->brush) { | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 		DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush; | 
					
						
							|  |  |  | 		t_brush->pmd = tpmd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t_brush->flags = brush->flags; | 
					
						
							|  |  |  | 		t_brush->collision = brush->collision; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t_brush->mat = brush->mat; | 
					
						
							|  |  |  | 		t_brush->r = brush->r; | 
					
						
							|  |  |  | 		t_brush->g = brush->g; | 
					
						
							|  |  |  | 		t_brush->b = brush->b; | 
					
						
							|  |  |  | 		t_brush->alpha = brush->alpha; | 
					
						
							|  |  |  | 		t_brush->wetness = brush->wetness; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t_brush->particle_radius = brush->particle_radius; | 
					
						
							|  |  |  | 		t_brush->particle_smooth = brush->particle_smooth; | 
					
						
							|  |  |  | 		t_brush->paint_distance = brush->paint_distance; | 
					
						
							|  |  |  | 		t_brush->psys = brush->psys; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (brush->paint_ramp) | 
					
						
							|  |  |  | 			memcpy(t_brush->paint_ramp, brush->paint_ramp, sizeof(ColorBand)); | 
					
						
							|  |  |  | 		if (brush->vel_ramp) | 
					
						
							|  |  |  | 			memcpy(t_brush->vel_ramp, brush->vel_ramp, sizeof(ColorBand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t_brush->proximity_falloff = brush->proximity_falloff; | 
					
						
							|  |  |  | 		t_brush->wave_type = brush->wave_type; | 
					
						
							|  |  |  | 		t_brush->ray_dir = brush->ray_dir; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t_brush->wave_factor = brush->wave_factor; | 
					
						
							|  |  |  | 		t_brush->wave_clamp = brush->wave_clamp; | 
					
						
							|  |  |  | 		t_brush->max_velocity = brush->max_velocity; | 
					
						
							|  |  |  | 		t_brush->smudge_strength = brush->smudge_strength; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* allocates surface data depending on surface type */ | 
					
						
							|  |  |  | static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	switch (surface->type) { | 
					
						
							|  |  |  | 		case MOD_DPAINT_SURFACE_T_PAINT: | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			sData->type_data = MEM_callocN(sizeof(PaintPoint) * sData->total_points, "DynamicPaintSurface Data"); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case MOD_DPAINT_SURFACE_T_DISPLACE: | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			sData->type_data = MEM_callocN(sizeof(float) * sData->total_points, "DynamicPaintSurface DepthData"); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case MOD_DPAINT_SURFACE_T_WEIGHT: | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			sData->type_data = MEM_callocN(sizeof(float) * sData->total_points, "DynamicPaintSurface WeightData"); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case MOD_DPAINT_SURFACE_T_WAVE: | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			sData->type_data = MEM_callocN(sizeof(PaintWavePoint) * sData->total_points, "DynamicPaintSurface WaveData"); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (sData->type_data == NULL) setError(surface->canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | static int surface_usesAdjDistance(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && surface->effect) return 1; | 
					
						
							|  |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) return 1; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | static int surface_usesAdjData(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	if (surface_usesAdjDistance(surface)) return 1; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX && | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	    surface->flags & MOD_DPAINT_ANTIALIAS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | /* initialize surface adjacency data */ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 	DerivedMesh *dm = surface->canvas->dm; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	PaintAdjData *ad; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	int *temp_data; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int neigh_points = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (!surface_usesAdjData(surface) && !force_init) return; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  | 		/* For vertex format, neighbors are connected by edges */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		neigh_points = 2 * dm->getNumEdges(dm); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		neigh_points = sData->total_points * 8; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!neigh_points) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate memory */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	ad = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data"); | 
					
						
							|  |  |  | 	if (!ad) return; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	ad->n_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Index"); | 
					
						
							|  |  |  | 	ad->n_num = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Counts"); | 
					
						
							|  |  |  | 	temp_data = MEM_callocN(sizeof(int) * sData->total_points, "Temp Adj Data"); | 
					
						
							|  |  |  | 	ad->n_target = MEM_callocN(sizeof(int) * neigh_points, "Surface Adj Targets"); | 
					
						
							|  |  |  | 	ad->flags = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Flags"); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	ad->total_targets = neigh_points; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	/* in case of allocation error, free memory */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) { | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		dynamicPaint_freeAdjData(sData); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		if (temp_data) MEM_freeN(temp_data); | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 		setError(surface->canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		int n_pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* For vertex format, count every vertex that is connected by an edge */ | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 		int numOfEdges = dm->getNumEdges(dm); | 
					
						
							|  |  |  | 		int numOfPolys = dm->getNumPolys(dm); | 
					
						
							|  |  |  | 		struct MEdge *edge =  dm->getEdgeArray(dm); | 
					
						
							|  |  |  | 		struct MPoly *mpoly = dm->getPolyArray(dm); | 
					
						
							|  |  |  | 		struct MLoop *mloop = dm->getLoopArray(dm); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		/* count number of edges per vertex */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < numOfEdges; i++) { | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			ad->n_num[edge[i].v1]++; | 
					
						
							|  |  |  | 			ad->n_num[edge[i].v2]++; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			temp_data[edge[i].v1]++; | 
					
						
							|  |  |  | 			temp_data[edge[i].v2]++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 		/* also add number of vertices to temp_data
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  to locate points on "mesh edge" */ | 
					
						
							|  |  |  | 		for (i = 0; i < numOfPolys; i++) { | 
					
						
							|  |  |  | 			int j = 0; | 
					
						
							|  |  |  | 			for (; j < mpoly[i].totloop; j++) { | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 				temp_data[mloop[mpoly[i].loopstart + j].v]++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* now check if total number of edges+faces for
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  each vertex is even, if not -> vertex is on mesh edge */ | 
					
						
							|  |  |  | 		for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			if ((temp_data[i] % 2) || | 
					
						
							|  |  |  | 			    (temp_data[i] < 4)) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 				ad->flags[i] |= ADJ_ON_MESH_EDGE; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			/* reset temp data */  | 
					
						
							|  |  |  | 			temp_data[i] = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* order n_index array */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		n_pos = 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			ad->n_index[i] = n_pos; | 
					
						
							|  |  |  | 			n_pos += ad->n_num[i]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 		/* and now add neighbor data using that info */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < numOfEdges; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			/* first vertex */ | 
					
						
							|  |  |  | 			int index = edge[i].v1; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			n_pos = ad->n_index[index] + temp_data[index]; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			ad->n_target[n_pos] = edge[i].v2; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			temp_data[index]++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* second vertex */ | 
					
						
							|  |  |  | 			index = edge[i].v2; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			n_pos = ad->n_index[index] + temp_data[index]; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			ad->n_target[n_pos] = edge[i].v1; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			temp_data[index]++; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							|  |  |  | 		/* for image sequences, only allocate memory.
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  bake initialization takes care of rest */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(temp_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	PaintPoint *pPoint = (PaintPoint *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	DerivedMesh *dm = surface->canvas->dm; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->type != MOD_DPAINT_SURFACE_T_PAINT) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (surface->init_color_type == MOD_DPAINT_INITIAL_NONE) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	/* Single color */ | 
					
						
							|  |  |  | 	else if (surface->init_color_type == MOD_DPAINT_INITIAL_COLOR) { | 
					
						
							|  |  |  | 		/* apply color to every surface point */ | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			copy_v3_v3(pPoint[i].color, surface->init_color); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			pPoint[i].alpha = surface->init_color[3]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* UV mapped texture */ | 
					
						
							|  |  |  | 	else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { | 
					
						
							|  |  |  | 		Tex *tex = surface->init_texture; | 
					
						
							|  |  |  | 		MTFace *tface; | 
					
						
							| 
									
										
										
										
											2011-11-11 11:20:46 +00:00
										 |  |  | 		MFace *mface = dm->getTessFaceArray(dm); | 
					
						
							|  |  |  | 		int numOfFaces = dm->getNumTessFaces(dm); | 
					
						
							| 
									
										
										
										
											2012-01-11 08:51:06 +00:00
										 |  |  | 		char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!tex) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-23 17:25:25 +00:00
										 |  |  | 		/* get uv map */ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | 
					
						
							|  |  |  | 		if (!tface) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* for vertex surface loop through tfaces and find uv color
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  that provides highest alpha */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2013-01-21 08:49:42 +00:00
										 |  |  | 			struct ImagePool *pool = BKE_image_pool_new(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static) shared(pool)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfFaces; i++) { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				int numOfVert = (mface[i].v4) ? 4 : 3; | 
					
						
							|  |  |  | 				float uv[3] = {0.0f}; | 
					
						
							|  |  |  | 				int j; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (j = 0; j < numOfVert; j++) { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					TexResult texres = {0}; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					unsigned int *vert = (&mface[i].v1) + j; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* remap to -1.0 to 1.0 */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f; | 
					
						
							|  |  |  | 					uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-21 08:49:42 +00:00
										 |  |  | 					multitex_ext_safe(tex, uv, &texres, pool); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					if (texres.tin > pPoint[*vert].alpha) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 						copy_v3_v3(pPoint[*vert].color, &texres.tr); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 						pPoint[*vert].alpha = texres.tin; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-01-21 08:49:42 +00:00
										 |  |  | 			BKE_image_pool_free(pool); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				float uv[9] = {0.0f}; | 
					
						
							|  |  |  | 				float uv_final[3] = {0.0f}; | 
					
						
							|  |  |  | 				int j; | 
					
						
							|  |  |  | 				TexResult texres = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* collect all uvs */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (j = 0; j < 3; j++) { | 
					
						
							|  |  |  | 					int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j; | 
					
						
							|  |  |  | 					copy_v2_v2(&uv[j * 3], tface[f_data->uv_p[i].face_index].uv[v]); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* interpolate final uv pos */ | 
					
						
							| 
									
										
										
										
											2012-04-29 17:11:40 +00:00
										 |  |  | 				interp_v3_v3v3v3(uv_final, &uv[0], &uv[3], &uv[6], | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				                 f_data->barycentricWeights[i * samples].v); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				/* remap to -1.0 to 1.0 */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				uv_final[0] = uv_final[0] * 2.0f - 1.0f; | 
					
						
							|  |  |  | 				uv_final[1] = uv_final[1] * 2.0f - 1.0f; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					 | 
					
						
							| 
									
										
										
										
											2013-01-21 08:49:42 +00:00
										 |  |  | 				multitex_ext_safe(tex, uv_final, &texres, NULL); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* apply color */ | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				copy_v3_v3(pPoint[i].color, &texres.tr); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				pPoint[i].alpha = texres.tin; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* vertex color layer */ | 
					
						
							|  |  |  | 	else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* for vertex surface, just copy colors from mcol */ | 
					
						
							|  |  |  | 		if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 			MLoop *mloop = dm->getLoopArray(dm); | 
					
						
							|  |  |  | 			int numOfLoops = dm->getNumLoops(dm); | 
					
						
							|  |  |  | 			MCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername); | 
					
						
							|  |  |  | 			if (!col) return; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfLoops; i++) { | 
					
						
							|  |  |  | 				pPoint[mloop[i].v].color[0] = 1.0f / 255.f * (float)col[i].b; | 
					
						
							|  |  |  | 				pPoint[mloop[i].v].color[1] = 1.0f / 255.f * (float)col[i].g; | 
					
						
							|  |  |  | 				pPoint[mloop[i].v].color[2] = 1.0f / 255.f * (float)col[i].r; | 
					
						
							|  |  |  | 				pPoint[mloop[i].v].alpha = 1.0f / 255.f * (float)col[i].a; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 			MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername); | 
					
						
							|  |  |  | 			if (!col) return; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				int face_ind = f_data->uv_p[i].face_index; | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 				float colors[3][4] = {{0.0f, 0.0f, 0.0f, 0.0f}}; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				float final_color[4]; | 
					
						
							|  |  |  | 				int j; | 
					
						
							|  |  |  | 				/* collect color values */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (j = 0; j < 3; j++) { | 
					
						
							|  |  |  | 					int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j; | 
					
						
							|  |  |  | 					colors[j][0] = 1.0f / 255.f * (float)col[face_ind * 4 + v].b; | 
					
						
							|  |  |  | 					colors[j][1] = 1.0f / 255.f * (float)col[face_ind * 4 + v].g; | 
					
						
							|  |  |  | 					colors[j][2] = 1.0f / 255.f * (float)col[face_ind * 4 + v].r; | 
					
						
							|  |  |  | 					colors[j][3] = 1.0f / 255.f * (float)col[face_ind * 4 + v].a; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				/* interpolate final color */ | 
					
						
							| 
									
										
										
										
											2012-04-29 17:11:40 +00:00
										 |  |  | 				interp_v4_v4v4v4(final_color, colors[0], colors[1], colors[2], | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				                 f_data->barycentricWeights[i * samples].v); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				copy_v3_v3(pPoint[i].color, final_color); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				pPoint[i].alpha = final_color[3]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | /* clears surface data back to zero */ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | void dynamicPaint_clearSurface(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	if (sData && sData->type_data) { | 
					
						
							|  |  |  | 		unsigned int data_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) | 
					
						
							|  |  |  | 			data_size = sizeof(PaintPoint); | 
					
						
							|  |  |  | 		else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) | 
					
						
							|  |  |  | 			data_size = sizeof(PaintWavePoint); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			data_size = sizeof(float); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		memset(sData->type_data, 0, data_size * sData->total_points); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* set initial color */ | 
					
						
							|  |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) | 
					
						
							|  |  |  | 			dynamicPaint_setInitialColor(surface); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		if (sData->bData) | 
					
						
							|  |  |  | 			sData->bData->clear = 1; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | /* completely (re)initializes surface (only for point cache types)*/ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | int dynamicPaint_resetSurface(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	/* free existing data */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	if (surface->data) dynamicPaint_freeSurfaceData(surface); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	/* don't reallocate for image sequence types. they get handled only on bake */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	if (numOfPoints < 1) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate memory */ | 
					
						
							|  |  |  | 	surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData"); | 
					
						
							|  |  |  | 	if (!surface->data) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate data depending on surface type and format */ | 
					
						
							|  |  |  | 	surface->data->total_points = numOfPoints; | 
					
						
							|  |  |  | 	dynamicPaint_allocateSurfaceType(surface); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	dynamicPaint_initAdjacencyData(surface, 0); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	/* set initial color */ | 
					
						
							|  |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) | 
					
						
							|  |  |  | 		dynamicPaint_setInitialColor(surface); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* make sure allocated surface size matches current requirements */ | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | static int dynamicPaint_checkSurfaceData(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) { | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 		return dynamicPaint_resetSurface(surface); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /***************************** Modifier processing ******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | /* apply displacing vertex surface to the derived mesh */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	if (!sData || surface->format != MOD_DPAINT_SURFACE_F_VERTEX) return; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	/* displace paint */ | 
					
						
							|  |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { | 
					
						
							|  |  |  | 		MVert *mvert = result->getVertArray(result); | 
					
						
							|  |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float *value = (float *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < sData->total_points; i++) { | 
					
						
							|  |  |  | 			float normal[3], val = value[i] * surface->disp_factor; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 			normal_short_to_float_v3(normal, mvert[i].no); | 
					
						
							|  |  |  | 			normalize_v3(normal); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			mvert[i].co[0] -= normal[0] * val; | 
					
						
							|  |  |  | 			mvert[i].co[1] -= normal[1] * val; | 
					
						
							|  |  |  | 			mvert[i].co[2] -= normal[2] * val; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Apply canvas data to the object derived mesh | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  |                                                 Object *ob, | 
					
						
							|  |  |  |                                                 DerivedMesh *dm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-29 21:59:47 +00:00
										 |  |  | 	DerivedMesh *result = CDDM_copy(dm); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-23 16:29:13 +00:00
										 |  |  | 		DynamicPaintSurface *surface; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		int update_normals = 0; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* loop through surfaces */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-23 16:29:13 +00:00
										 |  |  | 			if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				if (!(surface->flags & (MOD_DPAINT_ACTIVE))) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* process vertex surface previews */ | 
					
						
							|  |  |  | 				if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* vertex color paint */ | 
					
						
							|  |  |  | 					if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 						int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						PaintPoint *pPoint = (PaintPoint *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 						MLoopCol *col = NULL; | 
					
						
							|  |  |  | 						MLoop *mloop = CDDM_get_loops(result); | 
					
						
							|  |  |  | 						int totloop = result->numLoopData; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						/* paint is stored on dry and wet layers, so mix final color first */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						float *fcolor = MEM_callocN(sizeof(float) * sData->total_points * 4, "Temp paint color"); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 							/* blend dry and wet layer */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							blendColors(pPoint[i].color, pPoint[i].alpha, pPoint[i].e_color, pPoint[i].e_alpha, &fcolor[i * 4]); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* viewport preview */ | 
					
						
							| 
									
										
										
										
											2012-01-23 16:32:11 +00:00
										 |  |  | 						if (surface->flags & MOD_DPAINT_PREVIEW) { | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 							MPoly *mp = CDDM_get_polys(result); | 
					
						
							|  |  |  | 							int totpoly = result->numPolyData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
											
										 
											2012-03-18 22:06:57 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2012-03-22 08:41:50 +00:00
										 |  |  | 							/* XXX We have to create a CD_PREVIEW_MCOL, else it might sigsev
 | 
					
						
							| 
									
										
										
										
											2012-01-23 17:17:08 +00:00
										 |  |  | 							 *     (after a SubSurf mod, eg)... */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 							if (!result->getTessFaceDataArray(result, CD_PREVIEW_MCOL)) { | 
					
						
							| 
									
										
										
										
											2012-01-23 17:17:08 +00:00
										 |  |  | 								int numFaces = result->getNumTessFaces(result); | 
					
						
							| 
									
										
										
										
											2012-03-22 08:41:50 +00:00
										 |  |  | 								CustomData_add_layer(&result->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces); | 
					
						
							| 
									
										
										
										
											2012-01-23 17:17:08 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
											
												Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
											
										 
											2012-03-18 22:06:57 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-01-23 17:17:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 							/* Save preview results to weight layer to be
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							 *   able to share same drawing methods */ | 
					
						
							| 
									
										
										
										
											2012-03-22 08:41:50 +00:00
										 |  |  | 							col = CustomData_get_layer(&result->loopData, CD_PREVIEW_MLOOPCOL); | 
					
						
							|  |  |  | 							if (!col) | 
					
						
							|  |  |  | 								col = CustomData_add_layer(&result->loopData, CD_PREVIEW_MLOOPCOL, CD_CALLOC, | 
					
						
							|  |  |  | 								                           NULL, totloop); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							if (col) { | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 								#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								for (i = 0; i < totpoly; i++) { | 
					
						
							|  |  |  | 									int j = 0; | 
					
						
							| 
									
										
										
										
											2012-04-02 22:26:00 +00:00
										 |  |  | 									Material *material = give_current_material(ob, mp[i].mat_nr + 1); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									for (; j < mp[i].totloop; j++) { | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 										int l_index = mp[i].loopstart + j; | 
					
						
							|  |  |  | 										int v_index = mloop[l_index].v; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 										if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 											float c[3]; | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 											v_index *= 4; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 											/* Apply material color as base vertex color for preview */ | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 											col[l_index].a = 255; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 											if (material) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 												c[0] = material->r; | 
					
						
							|  |  |  | 												c[1] = material->g; | 
					
						
							|  |  |  | 												c[2] = material->b; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 											} | 
					
						
							| 
									
										
										
										
											2012-07-03 19:09:07 +00:00
										 |  |  | 											else { /* default gray */ | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 												c[0] = 0.65f; | 
					
						
							|  |  |  | 												c[1] = 0.65f; | 
					
						
							|  |  |  | 												c[2] = 0.65f; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 											} | 
					
						
							|  |  |  | 											/* mix surface color */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 											interp_v3_v3v3(c, c, &fcolor[v_index], fcolor[v_index + 3]); | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-17 20:39:28 +00:00
										 |  |  | 											rgb_float_to_uchar((unsigned char *)&col[l_index].r, c); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 										} | 
					
						
							|  |  |  | 										else { | 
					
						
							| 
									
										
										
										
											2012-01-15 09:16:39 +00:00
										 |  |  | 											col[l_index].r = | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 											    col[l_index].g = | 
					
						
							|  |  |  | 											        col[l_index].b = FTOCHAR(pPoint[v_index].wetness); | 
					
						
							| 
									
										
										
										
											2012-03-17 20:39:28 +00:00
										 |  |  | 											col[l_index].a = 255; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 										} | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* save layer data to output layer */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* paint layer */ | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 						col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name); | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 						/* if output layer is lost from a constructive modifier, re-add it */ | 
					
						
							|  |  |  | 						if (!col && dynamicPaint_outputLayerExists(surface, ob, 0)) | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 							col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name); | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 						/* apply color */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						if (col) { | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 							#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (i = 0; i < totloop; i++) { | 
					
						
							|  |  |  | 								int index = mloop[i].v * 4; | 
					
						
							| 
									
										
										
										
											2012-03-17 20:39:28 +00:00
										 |  |  | 								rgb_float_to_uchar((unsigned char *)&col[i].r, &fcolor[index]); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								col[i].a = FTOCHAR(fcolor[index + 3]); /* IS THIS NEEDED? */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-07-24 17:03:33 +00:00
										 |  |  | 						 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						MEM_freeN(fcolor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* wet layer */ | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 						col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name2); | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 						/* if output layer is lost from a constructive modifier, re-add it */ | 
					
						
							|  |  |  | 						if (!col && dynamicPaint_outputLayerExists(surface, ob, 1)) | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 							col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name2); | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 						/* apply color */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						if (col) { | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 							#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (i = 0; i < totloop; i++) { | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 								int index = mloop[i].v; | 
					
						
							| 
									
										
										
										
											2012-01-15 09:16:39 +00:00
										 |  |  | 								col[i].r = | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								    col[i].g = | 
					
						
							|  |  |  | 								        col[i].b = FTOCHAR(pPoint[index].wetness); | 
					
						
							| 
									
										
										
										
											2012-03-17 20:39:28 +00:00
										 |  |  | 								col[i].a = 255; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
											
												Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
											
										 
											2012-03-18 22:06:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						/* Mark tessellated CD layers as dirty. */ | 
					
						
							|  |  |  | 						result->dirty |= DM_DIRTY_TESS_CDLAYERS; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					/* vertex group paint */ | 
					
						
							|  |  |  | 					else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 						int defgrp_index = defgroup_name_index(ob, surface->output_name); | 
					
						
							|  |  |  | 						MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						float *weight = (float *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 						/* viewport preview */ | 
					
						
							| 
									
										
										
										
											2012-01-23 16:32:11 +00:00
										 |  |  | 						if (surface->flags & MOD_DPAINT_PREVIEW) { | 
					
						
							| 
									
										
										
										
											2011-11-30 20:41:13 +00:00
										 |  |  | 							/* Save preview results to weight layer to be
 | 
					
						
							| 
									
										
										
											
												Fix [#30234] Various problems with CD layers and tesselation, related to modifiers stack.
Should also fix [#30266], [#29451], and partly [#30316].
Here are the changes made by this commit:
* It adds a "dirty" flag to DerivedMesh struct (for now, only DM_DIRTY_TESS_CDLAYERS, but more might be added as needed).
* It adds a new func, DM_update_tessface_data, which assumes tessfaces themselves are valid, but updates tessellated customdata from their poly/loop counter parts.
* At end of modstack, when valid tessellated faces are present in finaldm , but the cdlayers dirty flag is set, call that function (instead of recomputing the whole tessellation).
* Edits to the codes concerned (UVProject, DynamicPaint, and Subsurf modifiers).
* Also add to subsurf dm generation code the creation of a CD_POLYINDEX layer (mandatory for DM_update_tessface_data to work well, and imho all tessellated dm should have one).
Note: some pieces of old code are just #if 0’ed, will clean them later.
											
										 
											2012-03-18 22:06:57 +00:00
										 |  |  | 							 * able to share same drawing methods. | 
					
						
							|  |  |  | 							 * Note this func also sets DM_DIRTY_TESS_CDLAYERS flag! */ | 
					
						
							| 
									
										
											  
											
												Add weight preview to WeightVG modifiers, and first, simple/basic refactor of how modifiers can generate preview.
User side:
* Preview for DynamicPaint should keep the same behavior (for now). Weight preview should be somawhat quicker, though.
* Preview for WeightVG modifiers is only active in WeightPaint mode, and if the affected vgroup is the active one.
* Last active preview modifier in stack wins!
Note: that modifier preview topic is yet to be further refined, quite raw/incomplete for now.
Dev side:
* In draw code, renamed DRAW_DYNAMIC_PAINT_PREVIEW flag to DRAW_MODIFIERS_PREVIEW
* Removed use of MOD_DPAINT_PREVIEW_READY in DynamicPaint code (seems unecessary, and if it was, should be of more general scope).
* Added eModifierTypeFlag_UsesPreview to ModifierTypeFlag, for modifiers that can generate some preview data.
* Added three new modifier funcs, to handle preview modifiers in draw code / mod stack.
* For weights preview: added the generic DM_update_weight_mcol func, which can update WEIGHT_MCOL layer with either a given array of weights (currently used by DynamicPaint only), or from current active vgroup(s).
So now, draw code is fully generic (i.e. no more modifier-type checking in it). Mod stack code is generic to some extent, but will need more work.
											
										 
											2012-01-22 17:54:23 +00:00
										 |  |  | 							DM_update_weight_mcol(ob, result, 0, weight, 0, NULL); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* apply weights into a vertex group, if doesnt exists add a new layer */ | 
					
						
							| 
									
										
										
										
											2012-10-22 17:19:05 +00:00
										 |  |  | 						if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 							dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							                                   NULL, sData->total_points, surface->output_name); | 
					
						
							| 
									
										
										
										
											2012-10-22 17:19:05 +00:00
										 |  |  | 						if (defgrp_index != -1 && dvert) { | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 							int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (i = 0; i < sData->total_points; i++) { | 
					
						
							|  |  |  | 								MDeformVert *dv = &dvert[i]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 								MDeformWeight *def_weight = defvert_find_index(dv, defgrp_index); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 								/* skip if weight value is 0 and no existing weight is found */ | 
					
						
							| 
									
										
										
										
											2011-11-30 10:04:14 +00:00
										 |  |  | 								if ((def_weight != NULL) || (weight[i] != 0.0f)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									/* if not found, add a weight for it */ | 
					
						
							|  |  |  | 									if (def_weight == NULL) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 										def_weight = defvert_verify_index(dv, defgrp_index); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 									} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-30 10:04:14 +00:00
										 |  |  | 									/* set weight value */ | 
					
						
							|  |  |  | 									def_weight->weight = weight[i]; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 					/* wave simulation */ | 
					
						
							|  |  |  | 					else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { | 
					
						
							|  |  |  | 						MVert *mvert = result->getVertArray(result); | 
					
						
							|  |  |  | 						int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						PaintWavePoint *wPoint = (PaintWavePoint *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						for (i = 0; i < sData->total_points; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 							float normal[3]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 							normal_short_to_float_v3(normal, mvert[i].no); | 
					
						
							| 
									
										
										
										
											2011-11-30 10:04:14 +00:00
										 |  |  | 							madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 						update_normals = 1; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* displace */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { | 
					
						
							|  |  |  | 						dynamicPaint_applySurfaceDisplace(surface, result); | 
					
						
							|  |  |  | 						update_normals = 1; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (update_normals) | 
					
						
							| 
									
										
										
										
											2012-01-20 13:25:54 +00:00
										 |  |  | 			CDDM_calc_normals(result); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	/* make a copy of dm to use as brush data */ | 
					
						
							|  |  |  | 	if (pmd->brush) { | 
					
						
							|  |  |  | 		if (pmd->brush->dm) pmd->brush->dm->release(pmd->brush->dm); | 
					
						
							| 
									
										
										
										
											2012-01-29 21:59:47 +00:00
										 |  |  | 		pmd->brush->dm = CDDM_copy(result); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | /* update cache frame range */ | 
					
						
							|  |  |  | void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (surface->pointcache) { | 
					
						
							|  |  |  | 		surface->pointcache->startframe = surface->start_frame; | 
					
						
							|  |  |  | 		surface->pointcache->endframe = surface->end_frame; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | 	if (canvas->dm) { | 
					
						
							|  |  |  | 		canvas->dm->release(canvas->dm); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-29 21:59:47 +00:00
										 |  |  | 	canvas->dm = CDDM_copy(dm); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Updates derived mesh copy and processes dynamic paint step / caches. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (pmd->canvas) { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 		DynamicPaintCanvasSettings *canvas = pmd->canvas; | 
					
						
							|  |  |  | 		DynamicPaintSurface *surface = canvas->surfaces.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* update derived mesh copy */ | 
					
						
							|  |  |  | 		canvas_copyDerivedMesh(canvas, dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* in case image sequence baking, stop here */ | 
					
						
							|  |  |  | 		if (canvas->flags & MOD_DPAINT_BAKING) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* loop through surfaces */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (; surface; surface = surface->next) { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 			int current_frame = (int)scene->r.cfra; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | 			/* free bake data if not required anymore */ | 
					
						
							|  |  |  | 			surface_freeUnusedData(surface); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 			/* image sequences are handled by bake operator */ | 
					
						
							|  |  |  | 			if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) continue; | 
					
						
							|  |  |  | 			if (!(surface->flags & MOD_DPAINT_ACTIVE)) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* make sure surface is valid */ | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 			if (!dynamicPaint_checkSurfaceData(surface)) continue; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* limit frame range */ | 
					
						
							|  |  |  | 			CLAMP(current_frame, surface->start_frame, surface->end_frame); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (current_frame != surface->current_frame || (int)scene->r.cfra == surface->start_frame) { | 
					
						
							|  |  |  | 				PointCache *cache = surface->pointcache; | 
					
						
							|  |  |  | 				PTCacheID pid; | 
					
						
							|  |  |  | 				surface->current_frame = current_frame; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* read point cache */ | 
					
						
							|  |  |  | 				BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface); | 
					
						
							|  |  |  | 				pid.cache->startframe = surface->start_frame; | 
					
						
							|  |  |  | 				pid.cache->endframe = surface->end_frame; | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 				BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* reset non-baked cache at first frame */ | 
					
						
							| 
									
										
										
										
											2012-04-21 15:11:03 +00:00
										 |  |  | 				if ((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED)) { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 					cache->flag |= PTCACHE_REDO_NEEDED; | 
					
						
							|  |  |  | 					BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); | 
					
						
							|  |  |  | 					cache->flag &= ~PTCACHE_REDO_NEEDED; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* try to read from cache */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 				if (BKE_ptcache_read(&pid, (float)scene->r.cfra)) { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 					BKE_ptcache_validate(cache, (int)scene->r.cfra); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				/* if read failed and we're on surface range do recalculate */ | 
					
						
							| 
									
										
										
										
											2012-04-21 15:11:03 +00:00
										 |  |  | 				else if ((int)scene->r.cfra == current_frame && !(cache->flag & PTCACHE_BAKED)) { | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 					/* calculate surface frame */ | 
					
						
							|  |  |  | 					canvas->flags |= MOD_DPAINT_BAKING; | 
					
						
							|  |  |  | 					dynamicPaint_calculateFrame(surface, scene, ob, current_frame); | 
					
						
							|  |  |  | 					canvas->flags &= ~MOD_DPAINT_BAKING; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* restore canvas derivedmesh if required */ | 
					
						
							|  |  |  | 					if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE && | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 					    surface->flags & MOD_DPAINT_DISP_INCREMENTAL && surface->next) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 						canvas_copyDerivedMesh(canvas, dm); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					BKE_ptcache_validate(cache, surface->current_frame); | 
					
						
							|  |  |  | 					BKE_ptcache_write(&pid, surface->current_frame); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /* Modifier call. Processes dynamic paint modifier step. */ | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 	/* For now generate tessfaces in every case
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  XXX - move/remove when most of dpaint functions are converted to use bmesh types */ | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 	DM_ensure_tessface(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	/* Update canvas data for a new frame */ | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	dynamicPaint_frameUpdate(pmd, scene, ob, dm); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Return output mesh */ | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 	return dynamicPaint_Modifier_apply(pmd, ob, dm); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /***************************** Image Sequence / UV Image Surface Calls ******************************/ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Tries to find the neighboring pixel in given (uv space) direction. | 
					
						
							|  |  |  |  *	Result is used by effect system to move paint on the surface. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   px, py : origin pixel x and y | 
					
						
							|  |  |  |  *	n_index : lookup direction index (use neighX, neighY to get final index) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-01-11 12:56:31 +00:00
										 |  |  | static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh *dm, | 
					
						
							|  |  |  |                                            const char *uvname, int w, int h, int px, int py, int n_index) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 	/* Note: Current method only uses polygon edges to detect neighboring pixels.
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  -> It doesn't always lead to the optimum pixel but is accurate enough | 
					
						
							| 
									
										
										
										
											2012-09-26 20:05:38 +00:00
										 |  |  | 	 *  and faster/simpler than including possible face tip point links) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	int x, y; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	PaintUVPoint *tPoint = NULL; | 
					
						
							|  |  |  | 	PaintUVPoint *cPoint = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	/* shift position by given n_index */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	x = px + neighX[n_index]; | 
					
						
							|  |  |  | 	y = py + neighY[n_index]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	if (x < 0 || x >= w) return OUT_OF_TEXTURE; | 
					
						
							|  |  |  | 	if (y < 0 || y >= h) return OUT_OF_TEXTURE; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	tPoint = &tempPoints[x + w * y];        /* UV neighbor */ | 
					
						
							|  |  |  | 	cPoint = &tempPoints[px + w * py];      /* Origin point */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Check if shifted point is on same face -> it's a correct neighbor | 
					
						
							|  |  |  | 	 *   (and if it isn't marked as an "edge pixel") | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if ((tPoint->face_index == cPoint->face_index) && (tPoint->neighbour_pixel == -1)) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		return (x + w * y); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Even if shifted point is on another face | 
					
						
							|  |  |  | 	 *	-> use this point. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 *	!! Replace with "is uv faces linked" check !! | 
					
						
							|  |  |  | 	 *	This should work fine as long as uv island | 
					
						
							|  |  |  | 	 *	margin is > 1 pixel. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if ((tPoint->face_index != -1) && (tPoint->neighbour_pixel == -1)) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		return (x + w * y); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	If we get here, the actual neighboring pixel | 
					
						
							|  |  |  | 	 *	is located on a non-linked uv face, and we have to find | 
					
						
							|  |  |  | 	 *	it's "real" position. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 *	Simple neighboring face finding algorithm: | 
					
						
							|  |  |  | 	 *	- find closest uv edge to shifted pixel and get | 
					
						
							|  |  |  | 	 *	  the another face that shares that edge | 
					
						
							|  |  |  | 	 *	- find corresponding position of that new face edge | 
					
						
							|  |  |  | 	 *	  in uv space | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 *	TODO: Implement something more accurate / optimized? | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-11-11 11:20:46 +00:00
										 |  |  | 		int numOfFaces = dm->getNumTessFaces(dm); | 
					
						
							|  |  |  | 		MFace *mface = dm->getTessFaceArray(dm); | 
					
						
							| 
									
										
										
										
											2011-12-08 00:28:42 +00:00
										 |  |  | 		MTFace *tface =  CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Get closest edge to that subpixel on UV map	*/ | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-08-14 08:44:35 +00:00
										 |  |  | 			float pixel[2]; | 
					
						
							|  |  |  | 			/* distances only used for comparison */ | 
					
						
							|  |  |  | 			float dist_squared, t_dist_squared; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-13 13:56:40 +00:00
										 |  |  | 			int i, uindex[3], edge1_index, edge2_index, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			    e1_index, e2_index, target_face; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			float closest_point[2], lambda, dir_vec[2]; | 
					
						
							|  |  |  | 			int target_uv1, target_uv2, final_pixel[2], final_index; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			float *s_uv1, *s_uv2, *t_uv1, *t_uv2; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w; | 
					
						
							|  |  |  | 			pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* Get uv indexes for current face part	*/ | 
					
						
							|  |  |  | 			if (cPoint->quad) { | 
					
						
							|  |  |  | 				uindex[0] = 0; uindex[1] = 2; uindex[2] = 3; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				uindex[0] = 0; uindex[1] = 1; uindex[2] = 2; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *	Find closest edge to that pixel | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2012-08-14 08:44:35 +00:00
										 |  |  | 			/* Dist to first edge */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			e1_index = cPoint->v1; e2_index = cPoint->v2; edge1_index = uindex[0]; edge2_index = uindex[1]; | 
					
						
							| 
									
										
										
										
											2012-08-14 08:44:35 +00:00
										 |  |  | 			dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 08:44:35 +00:00
										 |  |  | 			/* Dist to second edge */ | 
					
						
							|  |  |  | 			t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[1]], tface[cPoint->face_index].uv[uindex[2]]); | 
					
						
							|  |  |  | 			if (t_dist_squared < dist_squared) { e1_index = cPoint->v2; e2_index = cPoint->v3; edge1_index = uindex[1]; edge2_index = uindex[2]; dist_squared = t_dist_squared; } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 08:44:35 +00:00
										 |  |  | 			/* Dist to third edge */ | 
					
						
							|  |  |  | 			t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[2]], tface[cPoint->face_index].uv[uindex[0]]); | 
					
						
							|  |  |  | 			if (t_dist_squared < dist_squared) { e1_index = cPoint->v3; e2_index = cPoint->v1;  edge1_index = uindex[2]; edge2_index = uindex[0]; dist_squared = t_dist_squared; } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *	Now find another face that is linked to that edge | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			target_face = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfFaces; i++) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 				/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				 *	Check if both edge vertices share this face | 
					
						
							|  |  |  | 				 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				int v4 = (mface[i].v4) ? mface[i].v4 : -1; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if ((e1_index == mface[i].v1 || e1_index == mface[i].v2 || e1_index == mface[i].v3 || e1_index == v4) && | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 				    (e2_index == mface[i].v1 || e2_index == mface[i].v2 || e2_index == mface[i].v3 || e2_index == v4)) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					if (i == cPoint->face_index) continue; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					target_face = i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					 *	Get edge UV index | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 					if (e1_index == mface[i].v1) target_uv1 = 0; | 
					
						
							|  |  |  | 					else if (e1_index == mface[i].v2) target_uv1 = 1; | 
					
						
							|  |  |  | 					else if (e1_index == mface[i].v3) target_uv1 = 2; | 
					
						
							|  |  |  | 					else target_uv1 = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (e2_index == mface[i].v1) target_uv2 = 0; | 
					
						
							|  |  |  | 					else if (e2_index == mface[i].v2) target_uv2 = 1; | 
					
						
							|  |  |  | 					else if (e2_index == mface[i].v3) target_uv2 = 2; | 
					
						
							|  |  |  | 					else target_uv2 = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			/* If none found pixel is on mesh edge	*/ | 
					
						
							|  |  |  | 			if (target_face == -1) return ON_MESH_EDGE; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *	If target face is connected in UV space as well, just use original index | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			s_uv1 = (float *)tface[cPoint->face_index].uv[edge1_index]; | 
					
						
							|  |  |  | 			s_uv2 = (float *)tface[cPoint->face_index].uv[edge2_index]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			t_uv1 = (float *)tface[target_face].uv[target_uv1]; | 
					
						
							|  |  |  | 			t_uv2 = (float *)tface[target_face].uv[target_uv2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//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]);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (((s_uv1[0] == t_uv1[0] && s_uv1[1] == t_uv1[1]) && | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			     (s_uv2[0] == t_uv2[0] && s_uv2[1] == t_uv2[1]) ) || | 
					
						
							|  |  |  | 			    ((s_uv2[0] == t_uv1[0] && s_uv2[1] == t_uv1[1]) && | 
					
						
							|  |  |  | 			     (s_uv1[0] == t_uv2[0] && s_uv1[1] == t_uv2[1]) )) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				return ((px + neighX[n_index]) + w * (py + neighY[n_index])); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *	Find a point that is relatively at same edge position | 
					
						
							|  |  |  | 			 *	on this other face UV | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			lambda = closest_to_line_v2(closest_point, pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			if (lambda < 0.0f) lambda = 0.0f; | 
					
						
							|  |  |  | 			if (lambda > 1.0f) lambda = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sub_v2_v2v2(dir_vec, tface[target_face].uv[target_uv2], tface[target_face].uv[target_uv1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mul_v2_fl(dir_vec, lambda); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			copy_v2_v2(pixel, tface[target_face].uv[target_uv1]); | 
					
						
							|  |  |  | 			add_v2_v2(pixel, dir_vec); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			pixel[0] = (pixel[0] * (float)w) - 0.5f; | 
					
						
							|  |  |  | 			pixel[1] = (pixel[1] * (float)h) - 0.5f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			final_pixel[0] = (int)floor(pixel[0]); | 
					
						
							|  |  |  | 			final_pixel[1] = (int)floor(pixel[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* If current pixel uv is outside of texture	*/ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			if (final_pixel[0] < 0 || final_pixel[0] >= w) return OUT_OF_TEXTURE; | 
					
						
							|  |  |  | 			if (final_pixel[1] < 0 || final_pixel[1] >= h) return OUT_OF_TEXTURE; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			final_index = final_pixel[0] + w * final_pixel[1]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* If we ended up to our origin point ( mesh has smaller than pixel sized faces)	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (final_index == (px + w * py)) return NOT_FOUND; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			/* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces)	*/ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			if (tempPoints[final_index].face_index != target_face) return NOT_FOUND; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *	If final point is an "edge pixel", use it's "real" neighbor instead | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			if (tempPoints[final_index].neighbour_pixel != -1) final_index = cPoint->neighbour_pixel; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return final_index; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Create a surface for uv image sequence format | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Antialias jitter point relative coords	*/ | 
					
						
							|  |  |  | 	float jitter5sample[10] =  {0.0f, 0.0f, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		                        -0.2f, -0.4f, | 
					
						
							|  |  |  | 		                        0.2f, 0.4f, | 
					
						
							|  |  |  | 		                        0.4f, -0.2f, | 
					
						
							|  |  |  | 		                        -0.4f, 0.3f}; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	int ty; | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	int w, h; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	int numOfFaces; | 
					
						
							| 
									
										
										
										
											2012-01-11 08:51:06 +00:00
										 |  |  | 	char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	int active_points = 0; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int error = 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	PaintSurfaceData *sData; | 
					
						
							|  |  |  | 	DynamicPaintCanvasSettings *canvas = surface->canvas; | 
					
						
							|  |  |  | 	DerivedMesh *dm = canvas->dm; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	PaintUVPoint *tempPoints = NULL; | 
					
						
							|  |  |  | 	Vec3f *tempWeights = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	MFace *mface = NULL; | 
					
						
							|  |  |  | 	MTFace *tface = NULL; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	Bounds2D *faceBB = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int *final_index; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	int aa_samples; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (!dm) | 
					
						
							|  |  |  | 		return setError(canvas, N_("Canvas mesh not updated")); | 
					
						
							|  |  |  | 	if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) | 
					
						
							|  |  |  | 		return setError(canvas, N_("Cannot bake non-'image sequence' formats")); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 18:29:01 +00:00
										 |  |  | 	numOfFaces = dm->getNumTessFaces(dm); | 
					
						
							| 
									
										
										
										
											2011-11-11 11:20:46 +00:00
										 |  |  | 	mface = dm->getTessFaceArray(dm); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-23 17:25:25 +00:00
										 |  |  | 	/* get uv map */ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Check for validity	*/ | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (!tface) | 
					
						
							|  |  |  | 		return setError(canvas, N_("No UV data on canvas")); | 
					
						
							|  |  |  | 	if (surface->image_resolution < 16 || surface->image_resolution > 8192) | 
					
						
							|  |  |  | 		return setError(canvas, N_("Invalid resolution")); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	w = h = surface->image_resolution; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Start generating the surface | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i faces.\n", w, h, numOfFaces); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Init data struct */ | 
					
						
							|  |  |  | 	if (surface->data) dynamicPaint_freeSurfaceData(surface); | 
					
						
							|  |  |  | 	sData = surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData"); | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (!surface->data) | 
					
						
							|  |  |  | 		return setError(canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	tempPoints = (struct PaintUVPoint *) MEM_callocN(w * h * sizeof(struct PaintUVPoint), "Temp PaintUVPoint"); | 
					
						
							|  |  |  | 	if (!tempPoints) error = 1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	final_index = (int *) MEM_callocN(w * h * sizeof(int), "Temp UV Final Indexes"); | 
					
						
							|  |  |  | 	if (!final_index) error = 1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	tempWeights = (struct Vec3f *) MEM_mallocN(w * h * aa_samples * sizeof(struct Vec3f), "Temp bWeights"); | 
					
						
							|  |  |  | 	if (!tempWeights) error = 1; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Generate a temporary bounding box array for UV faces to optimize | 
					
						
							|  |  |  | 	 *	the pixel-inside-a-face search. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if (!error) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		faceBB = (struct Bounds2D *) MEM_mallocN(numOfFaces * sizeof(struct Bounds2D), "MPCanvasFaceBB"); | 
					
						
							|  |  |  | 		if (!faceBB) error = 1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if (!error) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (ty = 0; ty < numOfFaces; ty++) { | 
					
						
							|  |  |  | 			int numOfVert = (mface[ty].v4) ? 4 : 3; | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			copy_v2_v2(faceBB[ty].min, tface[ty].uv[0]); | 
					
						
							|  |  |  | 			copy_v2_v2(faceBB[ty].max, tface[ty].uv[0]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 1; i < numOfVert; i++) { | 
					
						
							|  |  |  | 				if (tface[ty].uv[i][0] < faceBB[ty].min[0]) faceBB[ty].min[0] = tface[ty].uv[i][0]; | 
					
						
							|  |  |  | 				if (tface[ty].uv[i][1] < faceBB[ty].min[1]) faceBB[ty].min[1] = tface[ty].uv[i][1]; | 
					
						
							|  |  |  | 				if (tface[ty].uv[i][0] > faceBB[ty].max[0]) faceBB[ty].max[0] = tface[ty].uv[i][0]; | 
					
						
							|  |  |  | 				if (tface[ty].uv[i][1] > faceBB[ty].max[1]) faceBB[ty].max[1] = tface[ty].uv[i][1]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Loop through every pixel and check | 
					
						
							|  |  |  | 	 *	if pixel is uv-mapped on a canvas face. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if (!error) { | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		for (ty = 0; ty < h; ty++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int tx; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (tx = 0; tx < w; tx++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				int i, sample; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				int index = tx + w * ty; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				PaintUVPoint *tPoint = (&tempPoints[index]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				short isInside = 0; /* if point is inside a uv face */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				float d1[2], d2[2], d3[2], point[5][2]; | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 				float dot00, dot01, dot02, dot11, dot12, invDenom, u, v; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/* Init per pixel settings */ | 
					
						
							|  |  |  | 				tPoint->face_index = -1; | 
					
						
							|  |  |  | 				tPoint->neighbour_pixel = -1; | 
					
						
							|  |  |  | 				tPoint->pixel_index = index; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/* Actual pixel center, used when collision is found	*/ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				point[0][0] = ((float)tx + 0.5f) / w; | 
					
						
							|  |  |  | 				point[0][1] = ((float)ty + 0.5f) / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				 * A pixel middle sample isn't enough to find very narrow polygons | 
					
						
							|  |  |  | 				 * So using 4 samples of each corner too | 
					
						
							|  |  |  | 				 */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				point[1][0] = ((float)tx) / w; | 
					
						
							|  |  |  | 				point[1][1] = ((float)ty) / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				point[2][0] = ((float)tx + 1) / w; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				point[2][1] = ((float)ty) / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				point[3][0] = ((float)tx) / w; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				point[3][1] = ((float)ty + 1) / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				point[4][0] = ((float)tx + 1) / w; | 
					
						
							|  |  |  | 				point[4][1] = ((float)ty + 1) / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/* Loop through samples, starting from middle point	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (sample = 0; sample < 5; sample++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					 | 
					
						
							|  |  |  | 					/* Loop through every face in the mesh	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					for (i = 0; i < numOfFaces; i++) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						/* Check uv bb	*/ | 
					
						
							|  |  |  | 						if (faceBB[i].min[0] > (point[sample][0])) continue; | 
					
						
							|  |  |  | 						if (faceBB[i].min[1] > (point[sample][1])) continue; | 
					
						
							|  |  |  | 						if (faceBB[i].max[0] < (point[sample][0])) continue; | 
					
						
							|  |  |  | 						if (faceBB[i].max[1] < (point[sample][1])) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/*  Calculate point inside a triangle check
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						 *	for uv0, 1, 2 */ | 
					
						
							|  |  |  | 						sub_v2_v2v2(d1,  tface[i].uv[2], tface[i].uv[0]);   // uv2 - uv0
 | 
					
						
							|  |  |  | 						sub_v2_v2v2(d2,  tface[i].uv[1], tface[i].uv[0]);   // uv1 - uv0
 | 
					
						
							|  |  |  | 						sub_v2_v2v2(d3,  point[sample], tface[i].uv[0]);    // point - uv0
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						dot00 = d1[0] * d1[0] + d1[1] * d1[1]; | 
					
						
							|  |  |  | 						dot01 = d1[0] * d2[0] + d1[1] * d2[1]; | 
					
						
							|  |  |  | 						dot02 = d1[0] * d3[0] + d1[1] * d3[1]; | 
					
						
							|  |  |  | 						dot11 = d2[0] * d2[0] + d2[1] * d2[1]; | 
					
						
							|  |  |  | 						dot12 = d2[0] * d3[0] + d2[1] * d3[1]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 15:43:09 +00:00
										 |  |  | 						invDenom = (dot00 * dot11 - dot01 * dot01); | 
					
						
							|  |  |  | 						invDenom = invDenom ? 1.0f / invDenom : 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						u = (dot11 * dot02 - dot01 * dot12) * invDenom; | 
					
						
							|  |  |  | 						v = (dot00 * dot12 - dot01 * dot02) * invDenom; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 						if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 1; } /* is inside a triangle */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						/*  If collision wasn't found but the face is a quad
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						 *	do another check for the second half */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 						if ((!isInside) && mface[i].v4) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							/* change d2 to test the other half	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							sub_v2_v2v2(d2,  tface[i].uv[3], tface[i].uv[0]);   // uv3 - uv0
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							/* test again	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							dot00 = d1[0] * d1[0] + d1[1] * d1[1]; | 
					
						
							|  |  |  | 							dot01 = d1[0] * d2[0] + d1[1] * d2[1]; | 
					
						
							|  |  |  | 							dot02 = d1[0] * d3[0] + d1[1] * d3[1]; | 
					
						
							|  |  |  | 							dot11 = d2[0] * d2[0] + d2[1] * d2[1]; | 
					
						
							|  |  |  | 							dot12 = d2[0] * d3[0] + d2[1] * d3[1]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 15:43:09 +00:00
										 |  |  | 							invDenom = (dot00 * dot11 - dot01 * dot01); | 
					
						
							|  |  |  | 							invDenom = invDenom ? 1.0f / invDenom : 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							u = (dot11 * dot02 - dot01 * dot12) * invDenom; | 
					
						
							|  |  |  | 							v = (dot00 * dot12 - dot01 * dot02) * invDenom; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 							if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 2; } /* is inside the second half of the quad */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						 *	If point was inside the face | 
					
						
							|  |  |  | 						 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						if (isInside != 0) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							float uv1co[2], uv2co[2], uv3co[2], uv[2]; | 
					
						
							|  |  |  | 							int j; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							/* Get triagnle uvs	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							if (isInside == 1) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 								copy_v2_v2(uv1co, tface[i].uv[0]); | 
					
						
							|  |  |  | 								copy_v2_v2(uv2co, tface[i].uv[1]); | 
					
						
							|  |  |  | 								copy_v2_v2(uv3co, tface[i].uv[2]); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 								copy_v2_v2(uv1co, tface[i].uv[0]); | 
					
						
							|  |  |  | 								copy_v2_v2(uv2co, tface[i].uv[2]); | 
					
						
							|  |  |  | 								copy_v2_v2(uv3co, tface[i].uv[3]); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							/* Add b-weights per anti-aliasing sample	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (j = 0; j < aa_samples; j++) { | 
					
						
							|  |  |  | 								uv[0] = point[0][0] + jitter5sample[j * 2] / w; | 
					
						
							|  |  |  | 								uv[1] = point[0][1] + jitter5sample[j * 2 + 1] / h; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index * aa_samples + j].v); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* Set surface point face values	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							tPoint->face_index = i;                         /* face index */ | 
					
						
							|  |  |  | 							tPoint->quad = (isInside == 2) ? 1 : 0;     /* quad or tri part*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							/* save vertex indexes	*/ | 
					
						
							| 
									
										
										
										
											2011-12-31 10:28:36 +00:00
										 |  |  | 							tPoint->v1 = mface[i].v1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2; | 
					
						
							|  |  |  | 							tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3; | 
					
						
							| 
									
										
										
										
											2011-11-27 23:41:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							sample = 5; /* make sure we exit sample loop as well */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} /* sample loop */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *	Now loop through every pixel that was left without index | 
					
						
							|  |  |  | 		 *	and find if they have neighboring pixels that have an index. | 
					
						
							|  |  |  | 		 *	If so use that polygon as pixel surface. | 
					
						
							|  |  |  | 		 *	(To avoid seams on uv island edges) | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		for (ty = 0; ty < h; ty++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int tx; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (tx = 0; tx < w; tx++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				int index = tx + w * ty; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				PaintUVPoint *tPoint = (&tempPoints[index]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 				/* If point isn't't on canvas mesh	*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (tPoint->face_index == -1) { | 
					
						
							|  |  |  | 					int u_min, u_max, v_min, v_max; | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 					int u, v, ind; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					float point[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* get loop area	*/ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					u_min = (tx > 0) ? -1 : 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					u_max = (tx < (w - 1)) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					v_min = (ty > 0) ? -1 : 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					v_max = (ty < (h - 1)) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					point[0] = ((float)tx + 0.5f) / w; | 
					
						
							|  |  |  | 					point[1] = ((float)ty + 0.5f) / h; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 					/* search through defined area for neighbor	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					for (u = u_min; u <= u_max; u++) | 
					
						
							|  |  |  | 						for (v = v_min; v <= v_max; v++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							/* if not this pixel itself	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							if (u != 0 || v != 0) { | 
					
						
							|  |  |  | 								ind = (tx + u) + w * (ty + v); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 								/* if neighbor has index	*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 								if (tempPoints[ind].face_index != -1) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									float uv1co[2], uv2co[2], uv3co[2], uv[2]; | 
					
						
							|  |  |  | 									int i = tempPoints[ind].face_index, j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									/* Now calculate pixel data for this pixel as it was on polygon surface */ | 
					
						
							|  |  |  | 									if (!tempPoints[ind].quad) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 										copy_v2_v2(uv1co, tface[i].uv[0]); | 
					
						
							|  |  |  | 										copy_v2_v2(uv2co, tface[i].uv[1]); | 
					
						
							|  |  |  | 										copy_v2_v2(uv3co, tface[i].uv[2]); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									} | 
					
						
							|  |  |  | 									else { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 										copy_v2_v2(uv1co, tface[i].uv[0]); | 
					
						
							|  |  |  | 										copy_v2_v2(uv2co, tface[i].uv[2]); | 
					
						
							|  |  |  | 										copy_v2_v2(uv3co, tface[i].uv[3]); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									/* Add b-weights per anti-aliasing sample	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									for (j = 0; j < aa_samples; j++) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 										uv[0] = point[0] + jitter5sample[j * 2] / w; | 
					
						
							|  |  |  | 										uv[1] = point[1] + jitter5sample[j * 2 + 1] / h; | 
					
						
							|  |  |  | 										barycentric_weights_v2(uv1co, uv2co, uv3co, uv, tempWeights[index * aa_samples + j].v); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									/* Set values	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									tPoint->neighbour_pixel = ind;              // face index
 | 
					
						
							|  |  |  | 									tPoint->quad = tempPoints[ind].quad;        // quad or tri
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									/* save vertex indexes	*/ | 
					
						
							| 
									
										
										
										
											2011-12-31 10:28:36 +00:00
										 |  |  | 									tPoint->v1 = mface[i].v1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2; | 
					
						
							|  |  |  | 									tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									u = u_max + 1;  /* make sure we exit outer loop as well */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									break; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *	When base loop is over convert found neighbor indexes to real ones | 
					
						
							|  |  |  | 		 *	Also count the final number of active surface points | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		for (ty = 0; ty < h; ty++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int tx; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (tx = 0; tx < w; tx++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				int index = tx + w * ty; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				PaintUVPoint *tPoint = (&tempPoints[index]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (tPoint->face_index == -1 && tPoint->neighbour_pixel != -1) tPoint->face_index = tempPoints[tPoint->neighbour_pixel].face_index; | 
					
						
							|  |  |  | 				if (tPoint->face_index != -1) active_points++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-31 10:28:36 +00:00
										 |  |  | 		/*	Generate surface adjacency data. */ | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			int i, cursor = 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			/* Create a temporary array of final indexes (before unassigned
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			 *  pixels have been dropped) */ | 
					
						
							|  |  |  | 			for (i = 0; i < w * h; i++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (tempPoints[i].face_index != -1) { | 
					
						
							|  |  |  | 					final_index[i] = cursor; | 
					
						
							|  |  |  | 					cursor++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* allocate memory */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			sData->total_points = w * h; | 
					
						
							| 
									
										
										
										
											2011-12-31 10:28:36 +00:00
										 |  |  | 			dynamicPaint_initAdjacencyData(surface, 1); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			if (sData->adj_data) { | 
					
						
							|  |  |  | 				PaintAdjData *ed = sData->adj_data; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				unsigned int n_pos = 0; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 				for (ty = 0; ty < h; ty++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					int tx; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 					for (tx = 0; tx < w; tx++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						int i, index = tx + w * ty; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (tempPoints[index].face_index != -1) { | 
					
						
							|  |  |  | 							ed->n_index[final_index[index]] = n_pos; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 							ed->n_num[final_index[index]] = 0; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (i = 0; i < 8; i++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 								/* Try to find a neighboring pixel in defined direction
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								 *  If not found, -1 is returned */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 								int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 								if (n_target >= 0) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									ed->n_target[n_pos] = final_index[n_target]; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 									ed->n_num[final_index[index]]++; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 									n_pos++; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 								else if (n_target == ON_MESH_EDGE || n_target == OUT_OF_TEXTURE) { | 
					
						
							|  |  |  | 									ed->flags[final_index[index]] |= ADJ_ON_MESH_EDGE; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		/* Create final surface data without inactive points */ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ImgSeqFormatData *f_data = MEM_callocN(sizeof(struct ImgSeqFormatData), "ImgSeqFormatData"); | 
					
						
							|  |  |  | 			if (f_data) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				f_data->uv_p = MEM_callocN(active_points * sizeof(struct PaintUVPoint), "PaintUVPoint"); | 
					
						
							|  |  |  | 				f_data->barycentricWeights = MEM_callocN(active_points * aa_samples * sizeof(struct Vec3f), "PaintUVPoint"); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (!f_data->uv_p || !f_data->barycentricWeights) error = 1; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-03-09 03:46:30 +00:00
										 |  |  | 			else { | 
					
						
							|  |  |  | 				error = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			sData->total_points = active_points; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* in case of allocation error, free everything */ | 
					
						
							|  |  |  | 			if (error) { | 
					
						
							|  |  |  | 				if (f_data) { | 
					
						
							|  |  |  | 					if (f_data->uv_p) MEM_freeN(f_data->uv_p); | 
					
						
							|  |  |  | 					if (f_data->barycentricWeights) MEM_freeN(f_data->barycentricWeights); | 
					
						
							|  |  |  | 					MEM_freeN(f_data); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				int index, cursor = 0; | 
					
						
							|  |  |  | 				sData->total_points = active_points; | 
					
						
							|  |  |  | 				sData->format_data = f_data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				for (index = 0; index < (w * h); index++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					if (tempPoints[index].face_index != -1) { | 
					
						
							|  |  |  | 						memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint)); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						memcpy(&f_data->barycentricWeights[cursor * aa_samples], &tempWeights[index * aa_samples], sizeof(Vec3f) * aa_samples); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 						cursor++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (error == 1) | 
					
						
							|  |  |  | 		setError(canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (faceBB) MEM_freeN(faceBB); | 
					
						
							|  |  |  | 	if (tempPoints) MEM_freeN(tempPoints); | 
					
						
							|  |  |  | 	if (tempWeights) MEM_freeN(tempWeights); | 
					
						
							|  |  |  | 	if (final_index) MEM_freeN(final_index); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Init surface type data */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	if (!error) { | 
					
						
							|  |  |  | 		dynamicPaint_allocateSurfaceType(surface); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 		/*  -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 		 *	For debug, output pixel statuses to the color map | 
					
						
							|  |  |  | 		 *	-----------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							|  |  |  | 		for (index = 0; index < sData->total_points; index++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							|  |  |  | 			PaintUVPoint *uvPoint = &((PaintUVPoint *)f_data->uv_p)[index]; | 
					
						
							|  |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							|  |  |  | 			pPoint->alpha = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* Every pixel that is assigned as "edge pixel" gets blue color	*/ | 
					
						
							|  |  |  | 			if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f; | 
					
						
							|  |  |  | 			/* and every pixel that finally got an polygon gets red color	*/ | 
					
						
							|  |  |  | 			if (uvPoint->face_index != -1) pPoint->color[0] = 1.0f; | 
					
						
							|  |  |  | 			/* green color shows pixel face index hash	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (uvPoint->face_index != -1) pPoint->color[1] = (float)(uvPoint->face_index % 255) / 256.0f; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		dynamicPaint_setInitialColor(surface); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (error == 0); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Outputs an image file from uv surface data. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filename, short output_layer) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	int index; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	ImBuf *ibuf = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	/* OpenEXR or PNG	*/ | 
					
						
							| 
									
										
										
										
											2011-11-22 00:35:26 +00:00
										 |  |  | 	int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	char output_file[FILE_MAX]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (!sData->type_data) { | 
					
						
							|  |  |  | 		setError(surface->canvas, N_("Image save failed: invalid surface")); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	/* if selected format is openexr, but current build doesnt support one */ | 
					
						
							|  |  |  | 	#ifndef WITH_OPENEXR
 | 
					
						
							| 
									
										
										
										
											2011-11-22 00:35:26 +00:00
										 |  |  | 	if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 	BLI_strncpy(output_file, filename, sizeof(output_file)); | 
					
						
							| 
									
										
										
										
											2012-12-23 13:57:09 +00:00
										 |  |  | 	BKE_add_image_extension_from_type(output_file, format); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Validate output file path	*/ | 
					
						
							|  |  |  | 	BLI_path_abs(output_file, G.main->name); | 
					
						
							|  |  |  | 	BLI_make_existing_file(output_file); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	/* Init image buffer	*/ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	ibuf = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat); | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 	if (ibuf == NULL) { | 
					
						
							|  |  |  | 		setError(surface->canvas, N_("Image save failed: not enough free memory")); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		int pos = f_data->uv_p[index].pixel_index * 4;  /* image buffer position */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/* Set values of preferred type */ | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		if (output_layer == 1) { | 
					
						
							|  |  |  | 			/* wetmap */ | 
					
						
							|  |  |  | 			if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				PaintPoint *point = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				float value = (point->wetness > 1.0f) ? 1.0f : point->wetness; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				ibuf->rect_float[pos] = value; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 1] = value; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 2] = value; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 3] = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		else if (output_layer == 0) { | 
					
						
							|  |  |  | 			/* Paintmap */ | 
					
						
							|  |  |  | 			if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				PaintPoint *point = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				/* blend wet and dry layers */ | 
					
						
							|  |  |  | 				blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]); | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* Multiply color by alpha if enabled	*/ | 
					
						
							|  |  |  | 				if (surface->flags & MOD_DPAINT_MULALPHA) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					ibuf->rect_float[pos]   *= ibuf->rect_float[pos + 3]; | 
					
						
							|  |  |  | 					ibuf->rect_float[pos + 1] *= ibuf->rect_float[pos + 3]; | 
					
						
							|  |  |  | 					ibuf->rect_float[pos + 2] *= ibuf->rect_float[pos + 3]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			/* displace */ | 
					
						
							|  |  |  | 			else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				float depth = ((float *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				if (surface->depth_clamp) | 
					
						
							|  |  |  | 					depth /= surface->depth_clamp; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				if (surface->disp_type == MOD_DPAINT_DISP_DISPLACE) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					depth = (0.5f - depth / 2.0f); | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				CLAMP(depth, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				ibuf->rect_float[pos] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 1] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 2] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 3] = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			/* waves */ | 
					
						
							|  |  |  | 			else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				PaintWavePoint *wPoint = &((PaintWavePoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				float depth = wPoint->height; | 
					
						
							|  |  |  | 				if (surface->depth_clamp) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					depth /= surface->depth_clamp; | 
					
						
							|  |  |  | 				depth = (0.5f + depth / 2.0f); | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				CLAMP(depth, 0.0f, 1.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				ibuf->rect_float[pos] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 1] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 2] = depth; | 
					
						
							|  |  |  | 				ibuf->rect_float[pos + 3] = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	/* Set output format, png in case exr isn't supported */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	ibuf->ftype = PNG | 95; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | #ifdef WITH_OPENEXR
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	if (format == R_IMF_IMTYPE_OPENEXR) {   /* OpenEXR 32-bit float */ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 		ibuf->ftype = OPENEXR | OPENEXR_COMPRESS; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	/* Save image */ | 
					
						
							|  |  |  | 	IMB_saveiff(ibuf, output_file, IB_rectfloat); | 
					
						
							|  |  |  | 	IMB_freeImBuf(ibuf); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /***************************** Material / Texture Sampling ******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* stores a copy of required materials to allow doing adjustments
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *  without interfering the render/preview */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | typedef struct BrushMaterials { | 
					
						
							|  |  |  | 	Material *mat; | 
					
						
							|  |  |  | 	Material **ob_mats; | 
					
						
							|  |  |  | 	int tot; | 
					
						
							|  |  |  | } BrushMaterials; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* Initialize materials for brush object:
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *  Calculates inverse matrices for linked objects, updates | 
					
						
							|  |  |  |  *  volume caches etc. */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Calculate inverse transformation matrix
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  for this object */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	invert_m4_m4(brushOb->imat, brushOb->obmat); | 
					
						
							|  |  |  | 	copy_m4_m4(brushOb->imat_ren, brushOb->imat); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	/* Now process every material linked to this brush object */ | 
					
						
							|  |  |  | 	if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		int i, tot = (*give_totcolp(brushOb)); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* allocate material pointer array */ | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 		if (tot) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			bMats->ob_mats = MEM_callocN(sizeof(Material *) * (tot), "BrushMaterials"); | 
					
						
							|  |  |  | 			for (i = 0; i < tot; i++) { | 
					
						
							|  |  |  | 				bMats->ob_mats[i] = RE_init_sample_material(give_current_material(brushOb, (i + 1)), scene); | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		bMats->tot = tot; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 		bMats->mat = RE_init_sample_material(ui_mat, scene); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* free all data allocated by dynamicPaint_updateBrushMaterials() */ | 
					
						
							|  |  |  | static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Now process every material linked to this brush object */ | 
					
						
							|  |  |  | 	if (bMats->ob_mats) { | 
					
						
							|  |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < bMats->tot; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 			RE_free_sample_material(bMats->ob_mats[i]); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		MEM_freeN(bMats->ob_mats); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 	else if (bMats->mat) { | 
					
						
							|  |  |  | 		RE_free_sample_material(bMats->mat); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Get material diffuse color and alpha (including linked textures) in given coordinates | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-12-23 01:18:35 +00:00
										 |  |  | static 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) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	Material *mat = bMats->mat; | 
					
						
							| 
									
										
										
										
											2011-11-11 11:20:46 +00:00
										 |  |  | 	MFace *mface = orcoDm->getTessFaceArray(orcoDm); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If no material defined, use the one assigned to the mesh face */ | 
					
						
							|  |  |  | 	if (mat == NULL) { | 
					
						
							|  |  |  | 		if (bMats->ob_mats) { | 
					
						
							|  |  |  | 			int mat_nr = mface[faceIndex].mat_nr; | 
					
						
							|  |  |  | 			if (mat_nr >= (*give_totcolp(brushOb))) return; | 
					
						
							|  |  |  | 			mat = bMats->ob_mats[mat_nr]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (mat == NULL) return;    /* No material assigned */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-03-09 03:46:30 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 	RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /***************************** Ray / Nearest Point Utils ******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*  A modified callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *   userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	To optimize brush detection speed this doesn't calculate hit coordinates or normal. | 
					
						
							|  |  |  |  *	If ray hit the second half of a quad, no[0] is set to 1.0f. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | static void mesh_faces_spherecast_dp(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; | 
					
						
							|  |  |  | 	MVert *vert = data->vert; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	MFace *face = data->face + index; | 
					
						
							|  |  |  | 	short quad = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float *t0, *t1, *t2, *t3; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	t0 = vert[face->v1].co; | 
					
						
							|  |  |  | 	t1 = vert[face->v2].co; | 
					
						
							|  |  |  | 	t2 = vert[face->v3].co; | 
					
						
							|  |  |  | 	t3 = face->v4 ? vert[face->v4].co : NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		if (dist >= 0 && dist < hit->dist) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			hit->index = index; | 
					
						
							|  |  |  | 			hit->dist = dist; | 
					
						
							|  |  |  | 			hit->no[0] = (quad) ? 1.0f : 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t1 = t2; | 
					
						
							|  |  |  | 		t2 = t3; | 
					
						
							|  |  |  | 		t3 = NULL; | 
					
						
							|  |  |  | 		quad = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	} while (t2); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A modified callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *  userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	To optimize brush detection speed this doesn't calculate hit normal. | 
					
						
							|  |  |  |  *	If ray hit the second half of a quad, no[0] is set to 1.0f, else 0.0f | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-04-28 08:29:20 +00:00
										 |  |  | static void mesh_faces_nearest_point_dp(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; | 
					
						
							|  |  |  | 	MVert *vert = data->vert; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	MFace *face = data->face + index; | 
					
						
							|  |  |  | 	short quad = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float *t0, *t1, *t2, *t3; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	t0 = vert[face->v1].co; | 
					
						
							|  |  |  | 	t1 = vert[face->v2].co; | 
					
						
							|  |  |  | 	t2 = vert[face->v3].co; | 
					
						
							|  |  |  | 	t3 = face->v4 ? vert[face->v4].co : NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		float nearest_tmp[3], dist; | 
					
						
							|  |  |  | 		int vertex, edge; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		if (dist < nearest->dist) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			nearest->index = index; | 
					
						
							|  |  |  | 			nearest->dist = dist; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			copy_v3_v3(nearest->co, nearest_tmp); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			nearest->no[0] = (quad) ? 1.0f : 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t1 = t2; | 
					
						
							|  |  |  | 		t2 = t3; | 
					
						
							|  |  |  | 		t3 = NULL; | 
					
						
							|  |  |  | 		quad = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	} while (t2); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /***************************** Brush Painting Calls ******************************/ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-26 20:05:38 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Mix color values to canvas point. | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-09-26 20:05:38 +00:00
										 |  |  |  * \param surface canvas surface | 
					
						
							|  |  |  |  * \param index surface point index | 
					
						
							|  |  |  |  * \param paintFlags paint object flags | 
					
						
							|  |  |  |  * \param paintColor,Alpha,Wetness to be mixed paint values | 
					
						
							|  |  |  |  * \param timescale value used to adjust time dependent | 
					
						
							|  |  |  |  * operations when using substeps | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-12 22:13:38 +00:00
										 |  |  | static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, | 
					
						
							|  |  |  |                                         const float paintColor[3], float *paintAlpha, float *paintWetness, float *timescale) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	PaintPoint *pPoint = &((PaintPoint *)surface->data->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Add paint	*/ | 
					
						
							|  |  |  | 	if (!(paintFlags & MOD_DPAINT_ERASE)) { | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 		float mix[4]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		float temp_alpha = (*paintAlpha) * ((paintFlags & MOD_DPAINT_ABS_ALPHA) ? 1.0f : (*timescale)); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		/* mix brush color with wet layer color */ | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 		blendColors(pPoint->e_color, pPoint->e_alpha, paintColor, temp_alpha, mix); | 
					
						
							|  |  |  | 		copy_v3_v3(pPoint->e_color, mix); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 		/* mix wetness and alpha depending on selected alpha mode */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		if (paintFlags & MOD_DPAINT_ABS_ALPHA) { | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 			/* update values to the brush level unless theyre higher already */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			if (pPoint->e_alpha < (*paintAlpha)) pPoint->e_alpha = (*paintAlpha); | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 			if (pPoint->wetness < (*paintWetness)) pPoint->wetness = (*paintWetness); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 			float wetness = (*paintWetness); | 
					
						
							|  |  |  | 			CLAMP(wetness, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 			pPoint->e_alpha = mix[3]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			pPoint->wetness = pPoint->wetness * (1.0f - wetness) + wetness; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (pPoint->wetness < MIN_WETNESS) pPoint->wetness = MIN_WETNESS; | 
					
						
							| 
									
										
										
										
											2011-11-02 11:32:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		pPoint->state = DPAINT_PAINT_NEW; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	/* Erase paint	*/ | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		float a_ratio, a_highest; | 
					
						
							|  |  |  | 		float wetness; | 
					
						
							|  |  |  | 		float invFact = 1.0f - (*paintAlpha); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *	Make highest alpha to match erased value | 
					
						
							|  |  |  | 		 *	but maintain alpha ratio | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		if (paintFlags & MOD_DPAINT_ABS_ALPHA) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			a_highest = (pPoint->e_alpha > pPoint->alpha) ? pPoint->e_alpha : pPoint->alpha; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			if (a_highest > invFact) { | 
					
						
							|  |  |  | 				a_ratio = invFact / a_highest; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				pPoint->e_alpha *= a_ratio; | 
					
						
							|  |  |  | 				pPoint->alpha *= a_ratio; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			pPoint->e_alpha -= (*paintAlpha) * (*timescale); | 
					
						
							|  |  |  | 			if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f; | 
					
						
							|  |  |  | 			pPoint->alpha -= (*paintAlpha) * (*timescale); | 
					
						
							|  |  |  | 			if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		wetness = (1.0f - (*paintWetness)) * pPoint->e_alpha; | 
					
						
							|  |  |  | 		if (pPoint->wetness > wetness) pPoint->wetness = wetness; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* applies given brush intersection value for wave surface */ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrushSettings *brush, float isect_height) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	float isect_change = isect_height - wPoint->brush_isect; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	int hit = 0; | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	/* intersection marked regardless of brush type or hit */ | 
					
						
							|  |  |  | 	wPoint->brush_isect = isect_height; | 
					
						
							|  |  |  | 	wPoint->state = DPAINT_WAVE_ISECT_CHANGED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	isect_height *= brush->wave_factor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* determine hit depending on wave_factor */ | 
					
						
							|  |  |  | 	if (brush->wave_factor > 0.0f && wPoint->height > isect_height) | 
					
						
							|  |  |  | 		hit = 1; | 
					
						
							|  |  |  | 	else if (brush->wave_factor < 0.0f && wPoint->height < isect_height) | 
					
						
							|  |  |  | 		hit = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hit) { | 
					
						
							|  |  |  | 		if (brush->wave_type == MOD_DPAINT_WAVEB_DEPTH) { | 
					
						
							|  |  |  | 			wPoint->height = isect_height; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			wPoint->state = DPAINT_WAVE_OBSTACLE; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			wPoint->velocity = 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (brush->wave_type == MOD_DPAINT_WAVEB_FORCE) | 
					
						
							|  |  |  | 			wPoint->velocity = isect_height; | 
					
						
							|  |  |  | 		else if (brush->wave_type == MOD_DPAINT_WAVEB_REFLECT) | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			wPoint->state = DPAINT_WAVE_REFLECT_ONLY; | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 		else if (brush->wave_type == MOD_DPAINT_WAVEB_CHANGE) { | 
					
						
							|  |  |  | 			if (isect_change < 0.0f) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				wPoint->height += isect_change * brush->wave_factor; | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	add brush results to the surface data depending on surface type | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned int index, DynamicPaintBrushSettings *brush, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |                                          float paint[3], float influence, float depth, float vel_factor, float timescale) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	float strength; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* apply influence scale */ | 
					
						
							|  |  |  | 	influence *= surface->influence_scale; | 
					
						
							|  |  |  | 	depth *= surface->influence_scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	strength = influence * brush->alpha; | 
					
						
							|  |  |  | 	CLAMP(strength, 0.0f, 1.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Sample velocity colorband if required */ | 
					
						
							|  |  |  | 	if (brush->flags & (MOD_DPAINT_VELOCITY_ALPHA | MOD_DPAINT_VELOCITY_COLOR | MOD_DPAINT_VELOCITY_DEPTH)) { | 
					
						
							|  |  |  | 		float coba_res[4]; | 
					
						
							|  |  |  | 		vel_factor /= brush->max_velocity; | 
					
						
							|  |  |  | 		CLAMP(vel_factor, 0.0f, 1.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (do_colorband(brush->vel_ramp, vel_factor, coba_res)) { | 
					
						
							|  |  |  | 			if (brush->flags & MOD_DPAINT_VELOCITY_COLOR) { | 
					
						
							|  |  |  | 				paint[0] = coba_res[0]; | 
					
						
							|  |  |  | 				paint[1] = coba_res[1]; | 
					
						
							|  |  |  | 				paint[2] = coba_res[2]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (brush->flags & MOD_DPAINT_VELOCITY_ALPHA) | 
					
						
							|  |  |  | 				strength *= coba_res[3]; | 
					
						
							|  |  |  | 			if (brush->flags & MOD_DPAINT_VELOCITY_DEPTH) | 
					
						
							|  |  |  | 				depth *= coba_res[3]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	/* mix paint surface */ | 
					
						
							|  |  |  | 	if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float paintWetness = brush->wetness * strength; | 
					
						
							|  |  |  | 		float paintAlpha = strength; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		dynamicPaint_mixPaintColors(surface, index, brush->flags, paint, &paintAlpha, &paintWetness, ×cale); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	/* displace surface */ | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { | 
					
						
							|  |  |  | 		float *value = (float *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) | 
					
						
							|  |  |  | 			depth = value[index] + depth; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (surface->depth_clamp) { | 
					
						
							|  |  |  | 			CLAMP(depth, 0.0f - surface->depth_clamp, surface->depth_clamp); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (brush->flags & MOD_DPAINT_ERASE) { | 
					
						
							|  |  |  | 			value[index] *= (1.0f - strength); | 
					
						
							|  |  |  | 			if (value[index] < 0.0f) value[index] = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			if (value[index] < depth) value[index] = depth; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	/* vertex weight group surface */ | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { | 
					
						
							|  |  |  | 		float *value = (float *)sData->type_data; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (brush->flags & MOD_DPAINT_ERASE) { | 
					
						
							|  |  |  | 			value[index] *= (1.0f - strength); | 
					
						
							|  |  |  | 			if (value[index] < 0.0f) value[index] = 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			if (value[index] < strength) value[index] = strength; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* wave surface */ | 
					
						
							|  |  |  | 	else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { | 
					
						
							|  |  |  | 		if (brush->wave_clamp) { | 
					
						
							|  |  |  | 			CLAMP(depth, 0.0f - brush->wave_clamp, brush->wave_clamp); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		dynamicPaint_mixWaveHeight(&((PaintWavePoint *)sData->type_data)[index], | 
					
						
							|  |  |  | 		                           brush, 0.0f - depth); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* doing velocity based painting */ | 
					
						
							|  |  |  | 	if (sData->bData->brush_velocity) { | 
					
						
							|  |  |  | 		sData->bData->brush_velocity[index * 4 + 3] *= influence; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* checks whether surface and brush bounds intersect depending on brush type */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush, float brush_radius) | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (brush->collision == MOD_DPAINT_COL_VOLUME) | 
					
						
							|  |  |  | 		return boundsIntersect(b1, b2); | 
					
						
							|  |  |  | 	else if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		return boundsIntersectDist(b1, b2, brush_radius); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	else return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | /* calculate velocity for mesh vertices */ | 
					
						
							|  |  |  | static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	float prev_obmat[4][4]; | 
					
						
							|  |  |  | 	DerivedMesh *dm_p, *dm_c; | 
					
						
							|  |  |  | 	MVert *mvert_p, *mvert_c; | 
					
						
							|  |  |  | 	int numOfVerts_p, numOfVerts_c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float cur_sfra = scene->r.subframe; | 
					
						
							|  |  |  | 	int cur_fra = scene->r.cfra; | 
					
						
							|  |  |  | 	float prev_sfra = cur_sfra - timescale; | 
					
						
							|  |  |  | 	int prev_fra = cur_fra; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (prev_sfra < 0.0f) { | 
					
						
							|  |  |  | 		prev_sfra += 1.0f; | 
					
						
							|  |  |  | 		prev_fra = cur_fra - 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* previous frame dm */ | 
					
						
							|  |  |  | 	scene->r.cfra = prev_fra; | 
					
						
							|  |  |  | 	scene->r.subframe = prev_sfra; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 	subframe_updateObject(scene, ob, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2012-01-29 21:59:47 +00:00
										 |  |  | 	dm_p = CDDM_copy(brush->dm); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	numOfVerts_p = dm_p->getNumVerts(dm_p); | 
					
						
							|  |  |  | 	mvert_p = dm_p->getVertArray(dm_p); | 
					
						
							|  |  |  | 	copy_m4_m4(prev_obmat, ob->obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* current frame dm */ | 
					
						
							|  |  |  | 	scene->r.cfra = cur_fra; | 
					
						
							|  |  |  | 	scene->r.subframe = cur_sfra; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 	subframe_updateObject(scene, ob, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	dm_c = brush->dm; | 
					
						
							|  |  |  | 	numOfVerts_c = dm_c->getNumVerts(dm_c); | 
					
						
							|  |  |  | 	mvert_c = dm_p->getVertArray(dm_c); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	(*brushVel) = (struct Vec3f *) MEM_mallocN(numOfVerts_c * sizeof(Vec3f), "Dynamic Paint brush velocity"); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (!(*brushVel)) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if mesh is constructive -> num of verts has changed,
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  only use current frame derived mesh */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (numOfVerts_p != numOfVerts_c) | 
					
						
							|  |  |  | 		mvert_p = mvert_c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate speed */ | 
					
						
							|  |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; i < numOfVerts_c; i++) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		float p1[3], p2[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		copy_v3_v3(p1, mvert_p[i].co); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		mul_m4_v3(prev_obmat, p1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		copy_v3_v3(p2, mvert_c[i].co); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		mul_m4_v3(ob->obmat, p2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		sub_v3_v3v3((*brushVel)[i].v, p2, p1); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		mul_v3_fl((*brushVel)[i].v, 1.0f / timescale); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dm_p->release(dm_p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* calculate velocity for object center point */ | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, Vec3f *brushVel, float timescale) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float prev_obmat[4][4]; | 
					
						
							|  |  |  | 	float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float cur_sfra = scene->r.subframe; | 
					
						
							|  |  |  | 	int cur_fra = scene->r.cfra; | 
					
						
							|  |  |  | 	float prev_sfra = cur_sfra - timescale; | 
					
						
							|  |  |  | 	int prev_fra = cur_fra; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (prev_sfra < 0.0f) { | 
					
						
							|  |  |  | 		prev_sfra += 1.0f; | 
					
						
							|  |  |  | 		prev_fra = cur_fra - 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* previous frame dm */ | 
					
						
							|  |  |  | 	scene->r.cfra = prev_fra; | 
					
						
							|  |  |  | 	scene->r.subframe = prev_sfra; | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 	subframe_updateObject(scene, ob, 0, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	copy_m4_m4(prev_obmat, ob->obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* current frame dm */ | 
					
						
							|  |  |  | 	scene->r.cfra = cur_fra; | 
					
						
							|  |  |  | 	scene->r.subframe = cur_sfra; | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 	subframe_updateObject(scene, ob, 0, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate speed */ | 
					
						
							|  |  |  | 	mul_m4_v3(prev_obmat, prev_loc); | 
					
						
							|  |  |  | 	mul_m4_v3(ob->obmat, cur_loc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 	sub_v3_v3v3(brushVel->v, cur_loc, prev_loc); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	mul_v3_fl(brushVel->v, 1.0f / timescale); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Paint a brush object mesh to the surface | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-11-10 12:28:26 +00:00
										 |  |  | static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, | 
					
						
							|  |  |  |                                   DynamicPaintBrushSettings *brush, | 
					
						
							|  |  |  |                                   Object *brushOb, | 
					
						
							|  |  |  |                                   BrushMaterials *bMats, | 
					
						
							|  |  |  |                                   Scene *scene, | 
					
						
							|  |  |  |                                   float timescale) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	DerivedMesh *dm = NULL; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	Vec3f *brushVelocity = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	MVert *mvert = NULL; | 
					
						
							|  |  |  | 	MFace *mface = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (brush->flags & MOD_DPAINT_USES_VELOCITY) | 
					
						
							|  |  |  | 		dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (!brush->dm) return 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		BVHTreeFromMesh treeData = {0}; | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 		float avg_brushNor[3] = {0.0f}; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		float brush_radius = brush->paint_distance * surface->radius_scale; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		int numOfVerts; | 
					
						
							|  |  |  | 		int ii; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		Bounds3D mesh_bb = {0}; | 
					
						
							|  |  |  | 		VolumeGrid *grid = bData->grid; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-29 21:59:47 +00:00
										 |  |  | 		dm = CDDM_copy(brush->dm); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		mvert = dm->getVertArray(dm); | 
					
						
							| 
									
										
										
										
											2011-11-11 11:20:46 +00:00
										 |  |  | 		mface = dm->getTessFaceArray(dm); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		numOfVerts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/*	Transform collider vertices to global space
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *	(Faster than transforming per surface point | 
					
						
							|  |  |  | 		 *	coordinates and normals to object space) */ | 
					
						
							|  |  |  | 		for (ii = 0; ii < numOfVerts; ii++) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			mul_m4_v3(brushOb->obmat, mvert[ii].co); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			boundInsert(&mesh_bb, mvert[ii].co); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 			/* for proximity project calculate average normal */ | 
					
						
							|  |  |  | 			if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) { | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 				float nor[3]; | 
					
						
							|  |  |  | 				normal_short_to_float_v3(nor, mvert[ii].no); | 
					
						
							|  |  |  | 				mul_mat3_m4_v3(brushOb->obmat, nor); | 
					
						
							|  |  |  | 				normalize_v3(nor); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				add_v3_v3(avg_brushNor, nor); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 		if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			mul_v3_fl(avg_brushNor, 1.0f / (float)numOfVerts); | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 			/* instead of null vector use positive z */ | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 			if (!(MIN3(avg_brushNor[0], avg_brushNor[1], avg_brushNor[2]))) | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 				avg_brushNor[2] = 1.0f; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				normalize_v3(avg_brushNor); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		/* check bounding box collision */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius)) { | 
					
						
							|  |  |  | 			/* Build a bvh tree from transformed vertices	*/ | 
					
						
							|  |  |  | 			if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8)) { | 
					
						
							|  |  |  | 				int c_index; | 
					
						
							|  |  |  | 				int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* loop through space partitioning grid */ | 
					
						
							|  |  |  | 				for (c_index = 0; c_index < total_cells; c_index++) { | 
					
						
							|  |  |  | 					int id; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					/* check grid cell bounding box */ | 
					
						
							|  |  |  | 					if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius)) | 
					
						
							|  |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					/* loop through cell points and process brush */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					for (id = 0; id < grid->s_num[c_index]; id++) { | 
					
						
							|  |  |  | 						int index = grid->t_index[grid->s_pos[c_index] + id]; | 
					
						
							|  |  |  | 						int ss, samples = bData->s_num[index]; | 
					
						
							|  |  |  | 						float total_sample = (float)samples; | 
					
						
							|  |  |  | 						float brushStrength = 0.0f; /* brush influence factor */ | 
					
						
							|  |  |  | 						float depth = 0.0f; /* brush intersection depth */ | 
					
						
							|  |  |  | 						float velocity_val = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						float paintColor[3] = {0.0f}; | 
					
						
							|  |  |  | 						int numOfHits = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* for image sequence anti-aliasing, use gaussian factors */ | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 						if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							total_sample = gaussianTotal; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						/* Supersampling	*/ | 
					
						
							|  |  |  | 						for (ss = 0; ss < samples; ss++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							float ray_start[3], ray_dir[3]; | 
					
						
							|  |  |  | 							float sample_factor = 0.0f; | 
					
						
							|  |  |  | 							float sampleStrength = 0.0f; | 
					
						
							|  |  |  | 							BVHTreeRayHit hit; | 
					
						
							|  |  |  | 							BVHTreeNearest nearest; | 
					
						
							|  |  |  | 							short hit_found = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* volume sample */ | 
					
						
							|  |  |  | 							float volume_factor = 0.0f; | 
					
						
							|  |  |  | 							/* proximity sample */ | 
					
						
							|  |  |  | 							float proximity_factor = 0.0f; | 
					
						
							|  |  |  | 							float prox_colorband[4] = {0.0f}; | 
					
						
							|  |  |  | 							int inner_proximity = (brush->flags & MOD_DPAINT_INVERSE_PROX && | 
					
						
							|  |  |  | 							                       brush->collision == MOD_DPAINT_COL_VOLDIST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* hit data	*/ | 
					
						
							|  |  |  | 							float hitCoord[3]; | 
					
						
							|  |  |  | 							int hitFace = -1; | 
					
						
							|  |  |  | 							short hitQuad = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* Supersampling factor	*/ | 
					
						
							|  |  |  | 							if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) | 
					
						
							|  |  |  | 								sample_factor = gaussianFactors[ss]; | 
					
						
							|  |  |  | 							else | 
					
						
							|  |  |  | 								sample_factor = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* Get current sample position in world coordinates	*/ | 
					
						
							|  |  |  | 							copy_v3_v3(ray_start, bData->realCoord[bData->s_pos[index] + ss].v); | 
					
						
							|  |  |  | 							copy_v3_v3(ray_dir, bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* a simple hack to minimize chance of ray leaks at identical ray <-> edge locations */ | 
					
						
							|  |  |  | 							add_v3_fl(ray_start, 0.001f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							hit.index = -1; | 
					
						
							|  |  |  | 							hit.dist = 9999; | 
					
						
							|  |  |  | 							nearest.index = -1; | 
					
						
							|  |  |  | 							nearest.dist = brush_radius * brush_radius; /* find_nearest uses squared distance */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* Check volume collision	*/ | 
					
						
							|  |  |  | 							if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST) | 
					
						
							|  |  |  | 								if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1) { | 
					
						
							|  |  |  | 									/* We hit a triangle, now check if collision point normal is facing the point	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									/*	For optimization sake, hit point normal isn't calculated in ray cast loop	*/ | 
					
						
							|  |  |  | 									int v1 = mface[hit.index].v1, v2 = mface[hit.index].v2, v3 = mface[hit.index].v3, quad = (hit.no[0] == 1.0f); | 
					
						
							|  |  |  | 									float dot; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 									if (quad) { v2 = mface[hit.index].v3; v3 = mface[hit.index].v4; } | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									normal_tri_v3(hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co); | 
					
						
							|  |  |  | 									dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									/*  If ray and hit face normal are facing same direction
 | 
					
						
							|  |  |  | 									 *	hit point is inside a closed mesh. */ | 
					
						
							|  |  |  | 									if (dot >= 0) { | 
					
						
							|  |  |  | 										float dist = hit.dist; | 
					
						
							|  |  |  | 										int f_index = hit.index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 										/* Also cast a ray in opposite direction to make sure
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 										 * point is at least surrounded by two brush faces */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 										negate_v3(ray_dir); | 
					
						
							|  |  |  | 										hit.index = -1; | 
					
						
							|  |  |  | 										hit.dist = 9999; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 										BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 										if (hit.index != -1) { | 
					
						
							|  |  |  | 											/* Add factor on supersample filter	*/ | 
					
						
							|  |  |  | 											volume_factor = 1.0f; | 
					
						
							|  |  |  | 											hit_found = HIT_VOLUME; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 											/* Mark hit info */ | 
					
						
							|  |  |  | 											madd_v3_v3v3fl(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */ | 
					
						
							|  |  |  | 											depth += dist * sample_factor; | 
					
						
							|  |  |  | 											hitFace = f_index; | 
					
						
							|  |  |  | 											hitQuad = quad; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							/* Check proximity collision	*/ | 
					
						
							|  |  |  | 							if ((brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) && | 
					
						
							|  |  |  | 							    (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX))) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								float proxDist = -1.0f; | 
					
						
							| 
									
										
										
										
											2012-12-02 16:01:06 +00:00
										 |  |  | 								float hitCo[3] = {0.0f, 0.0f, 0.0f}; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								short hQuad; | 
					
						
							|  |  |  | 								int face; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* if inverse prox and no hit found, skip this sample */ | 
					
						
							|  |  |  | 								if (inner_proximity && !hit_found) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* If pure distance proximity, find the nearest point on the mesh */ | 
					
						
							|  |  |  | 								if (!(brush->flags & MOD_DPAINT_PROX_PROJECT)) { | 
					
						
							|  |  |  | 									if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) { | 
					
						
							|  |  |  | 										proxDist = sqrtf(nearest.dist); | 
					
						
							|  |  |  | 										copy_v3_v3(hitCo, nearest.co); | 
					
						
							|  |  |  | 										hQuad = (nearest.no[0] == 1.0f); | 
					
						
							|  |  |  | 										face = nearest.index; | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-09-10 08:55:44 +00:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								else { /* else cast a ray in defined projection direction */ | 
					
						
							|  |  |  | 									float proj_ray[3] = {0.0f}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									if (brush->ray_dir == MOD_DPAINT_RAY_CANVAS) { | 
					
						
							|  |  |  | 										copy_v3_v3(proj_ray, bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 										negate_v3(proj_ray); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									else if (brush->ray_dir == MOD_DPAINT_RAY_BRUSH_AVG) { | 
					
						
							|  |  |  | 										copy_v3_v3(proj_ray, avg_brushNor); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									else { /* MOD_DPAINT_RAY_ZPLUS */ | 
					
						
							|  |  |  | 										proj_ray[2] = 1.0f; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									hit.index = -1; | 
					
						
							|  |  |  | 									hit.dist = brush_radius; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									/* Do a face normal directional raycast, and use that distance	*/ | 
					
						
							|  |  |  | 									if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1) { | 
					
						
							|  |  |  | 										proxDist = hit.dist; | 
					
						
							|  |  |  | 										madd_v3_v3v3fl(hitCo, ray_start, proj_ray, hit.dist); /* Calculate final hit coordinates */ | 
					
						
							|  |  |  | 										hQuad = (hit.no[0] == 1.0f); | 
					
						
							|  |  |  | 										face = hit.index; | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								/* If a hit was found, calculate required values	*/ | 
					
						
							|  |  |  | 								if (proxDist >= 0.0f && proxDist <= brush_radius) { | 
					
						
							|  |  |  | 									proximity_factor = proxDist / brush_radius; | 
					
						
							|  |  |  | 									CLAMP(proximity_factor, 0.0f, 1.0f); | 
					
						
							|  |  |  | 									if (!inner_proximity) | 
					
						
							|  |  |  | 										proximity_factor = 1.0f - proximity_factor; | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									hit_found = HIT_PROXIMITY; | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 									/* if no volume hit, use prox point face info */ | 
					
						
							|  |  |  | 									if (hitFace == -1) { | 
					
						
							|  |  |  | 										copy_v3_v3(hitCoord, hitCo); | 
					
						
							|  |  |  | 										hitQuad = hQuad; | 
					
						
							|  |  |  | 										hitFace = face; | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							/* mix final sample strength depending on brush settings */ | 
					
						
							|  |  |  | 							if (hit_found) { | 
					
						
							|  |  |  | 								/* if "negate volume" enabled, negate all factors within volume*/ | 
					
						
							|  |  |  | 								if (brush->collision == MOD_DPAINT_COL_VOLDIST && brush->flags & MOD_DPAINT_NEGATE_VOLUME) { | 
					
						
							|  |  |  | 									volume_factor = 1.0f - volume_factor; | 
					
						
							|  |  |  | 									if (inner_proximity) | 
					
						
							|  |  |  | 										proximity_factor = 1.0f - proximity_factor; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-11-11 10:46:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								/* apply final sample depending on final hit type */ | 
					
						
							|  |  |  | 								if (hit_found == HIT_VOLUME) { | 
					
						
							|  |  |  | 									sampleStrength = volume_factor; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else if (hit_found == HIT_PROXIMITY) { | 
					
						
							|  |  |  | 									/* apply falloff curve to the proximity_factor */ | 
					
						
							|  |  |  | 									if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, (1.0f - proximity_factor), prox_colorband)) | 
					
						
							|  |  |  | 										proximity_factor = prox_colorband[3]; | 
					
						
							|  |  |  | 									else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_CONSTANT) | 
					
						
							|  |  |  | 										proximity_factor = (!inner_proximity || brush->flags & MOD_DPAINT_NEGATE_VOLUME) ? 1.0f : 0.0f; | 
					
						
							|  |  |  | 									/* apply sample */ | 
					
						
							|  |  |  | 									sampleStrength = proximity_factor; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-11-11 10:46:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								sampleStrength *= sample_factor; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2012-07-07 22:51:57 +00:00
										 |  |  | 							else { | 
					
						
							|  |  |  | 								continue; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							/* velocity brush, only do on main sample */ | 
					
						
							|  |  |  | 							if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss == 0 && brushVelocity) { | 
					
						
							|  |  |  | 								int v1, v2, v3; | 
					
						
							|  |  |  | 								float weights[4]; | 
					
						
							|  |  |  | 								float brushPointVelocity[3]; | 
					
						
							|  |  |  | 								float velocity[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								if (!hitQuad) { | 
					
						
							|  |  |  | 									v1 = mface[hitFace].v1; | 
					
						
							|  |  |  | 									v2 = mface[hitFace].v2; | 
					
						
							|  |  |  | 									v3 = mface[hitFace].v3; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else { | 
					
						
							|  |  |  | 									v1 = mface[hitFace].v2; | 
					
						
							|  |  |  | 									v2 = mface[hitFace].v3; | 
					
						
							|  |  |  | 									v3 = mface[hitFace].v4; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								/* calculate barycentric weights for hit point */ | 
					
						
							|  |  |  | 								interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								/* simple check based on brush surface velocity,
 | 
					
						
							|  |  |  | 								 *  todo: perhaps implement something that handles volume movement as well */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 							 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								/* interpolate vertex speed vectors to get hit point velocity */ | 
					
						
							|  |  |  | 								interp_v3_v3v3v3(brushPointVelocity, | 
					
						
							|  |  |  | 								                 brushVelocity[v1].v, | 
					
						
							|  |  |  | 								                 brushVelocity[v2].v, | 
					
						
							|  |  |  | 								                 brushVelocity[v3].v, weights); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* substract canvas point velocity */ | 
					
						
							|  |  |  | 								if (bData->velocity) { | 
					
						
							|  |  |  | 									sub_v3_v3v3(velocity, brushPointVelocity, bData->velocity[index].v); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else { | 
					
						
							|  |  |  | 									copy_v3_v3(velocity, brushPointVelocity); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								velocity_val = len_v3(velocity); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* if brush has smudge enabled store brush velocity */ | 
					
						
							|  |  |  | 								if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && | 
					
						
							|  |  |  | 								    brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									copy_v3_v3(&bData->brush_velocity[index * 4], velocity); | 
					
						
							|  |  |  | 									mul_v3_fl(&bData->brush_velocity[index * 4], 1.0f / velocity_val); | 
					
						
							|  |  |  | 									bData->brush_velocity[index * 4 + 3] = velocity_val; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							/*
 | 
					
						
							|  |  |  | 							 *	Process hit color and alpha | 
					
						
							|  |  |  | 							 */ | 
					
						
							|  |  |  | 							if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							|  |  |  | 								float sampleColor[3]; | 
					
						
							|  |  |  | 								float alpha_factor = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								sampleColor[0] = brush->r; | 
					
						
							|  |  |  | 								sampleColor[1] = brush->g; | 
					
						
							|  |  |  | 								sampleColor[2] = brush->b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* Get material+textures color on hit point if required	*/ | 
					
						
							|  |  |  | 								if (brush_usesMaterial(brush, scene)) | 
					
						
							|  |  |  | 									dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index] + ss].v, hitCoord, hitFace, hitQuad, brush->dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								/* Sample proximity colorband if required	*/ | 
					
						
							|  |  |  | 								if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) { | 
					
						
							|  |  |  | 									if (!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) { | 
					
						
							|  |  |  | 										sampleColor[0] = prox_colorband[0]; | 
					
						
							|  |  |  | 										sampleColor[1] = prox_colorband[1]; | 
					
						
							|  |  |  | 										sampleColor[2] = prox_colorband[2]; | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								/* Add AA sample */ | 
					
						
							|  |  |  | 								paintColor[0] += sampleColor[0]; | 
					
						
							|  |  |  | 								paintColor[1] += sampleColor[1]; | 
					
						
							|  |  |  | 								paintColor[2] += sampleColor[2]; | 
					
						
							|  |  |  | 								sampleStrength *= alpha_factor; | 
					
						
							|  |  |  | 								numOfHits++; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							/* apply sample strength */ | 
					
						
							|  |  |  | 							brushStrength += sampleStrength; | 
					
						
							|  |  |  | 						} // end supersampling
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						/* if any sample was inside paint range	*/ | 
					
						
							|  |  |  | 						if (brushStrength > 0.0f || depth > 0.0f) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							/* apply supersampling results	*/ | 
					
						
							|  |  |  | 							if (samples > 1) { | 
					
						
							|  |  |  | 								brushStrength /= total_sample; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							CLAMP(brushStrength, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							|  |  |  | 								/* Get final pixel color and alpha	*/ | 
					
						
							|  |  |  | 								paintColor[0] /= numOfHits; | 
					
						
							|  |  |  | 								paintColor[1] /= numOfHits; | 
					
						
							|  |  |  | 								paintColor[2] /= numOfHits; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							/* get final object space depth */ | 
					
						
							|  |  |  | 							else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 							         surface->type == MOD_DPAINT_SURFACE_T_WAVE) | 
					
						
							|  |  |  | 							{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 								depth /= bData->bNormal[index].normal_scale * total_sample; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							dynamicPaint_updatePointData(surface, index, brush, paintColor, brushStrength, depth, velocity_val, timescale); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* free bvh tree */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		free_bvhtree_from_mesh(&treeData); | 
					
						
							|  |  |  | 		dm->release(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	/* free brush velocity data */ | 
					
						
							|  |  |  | 	if (brushVelocity) | 
					
						
							|  |  |  | 		MEM_freeN(brushVelocity); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Paint a particle system to the surface | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-11-10 12:28:26 +00:00
										 |  |  | static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, | 
					
						
							|  |  |  |                                        ParticleSystem *psys, | 
					
						
							|  |  |  |                                        DynamicPaintBrushSettings *brush, | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  |                                        float timescale) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	ParticleSettings *part = psys->part; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	ParticleData *pa = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							|  |  |  | 	VolumeGrid *grid = bData->grid;  | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	KDTree *tree; | 
					
						
							|  |  |  | 	int particlesAdded = 0; | 
					
						
							|  |  |  | 	int invalidParticles = 0; | 
					
						
							|  |  |  | 	int p = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float solidradius = surface->radius_scale * ((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius); | 
					
						
							|  |  |  | 	float smooth = brush->particle_smooth * surface->radius_scale; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float range = solidradius + smooth; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	float particle_timestep = 0.04f * part->timetweak; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 10:46:26 +00:00
										 |  |  | 	Bounds3D part_bb = {0}; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	if (psys->totpart < 1) return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Build a kd-tree to optimize distance search | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	tree = BLI_kdtree_new(psys->totpart); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* loop through particles and insert valid ones	to the tree	*/ | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 	for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Proceed only if particle is active	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) continue; | 
					
						
							|  |  |  | 		else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) continue; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		else if (pa->flag & PARS_UNEXIST) continue; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*	for debug purposes check if any NAN particle proceeds
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *	For some reason they get past activity check, this should rule most of them out	*/ | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 		if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) { invalidParticles++; continue; } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		/* make sure particle is close enough to canvas */ | 
					
						
							|  |  |  | 		if (!boundIntersectPoint(&grid->grid_bounds, pa->state.co, range)) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		BLI_kdtree_insert(tree, p, pa->state.co, NULL); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* calc particle system bounds */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		boundInsert(&part_bb, pa->state.co); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		particlesAdded++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	if (invalidParticles) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		printf("Warning: Invalid particle(s) found!\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If no suitable particles were found, exit	*/ | 
					
						
							|  |  |  | 	if (particlesAdded < 1) { | 
					
						
							|  |  |  | 		BLI_kdtree_free(tree); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 	/* begin thread safe malloc */ | 
					
						
							|  |  |  | 	BLI_begin_threaded_malloc(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	/* only continue if particle bb is close enough to canvas bb */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		int c_index; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* balance tree	*/ | 
					
						
							|  |  |  | 		BLI_kdtree_balance(tree); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* loop through space partitioning grid */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (c_index = 0; c_index < total_cells; c_index++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int id; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			/* check cell bounding box */ | 
					
						
							|  |  |  | 			if (!grid->s_num[c_index] || | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			    !boundsIntersectDist(&grid->bounds[c_index], &part_bb, range)) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* loop through cell points */ | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (id = 0; id < grid->s_num[c_index]; id++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				int index = grid->t_index[grid->s_pos[c_index] + id]; | 
					
						
							|  |  |  | 				float disp_intersect = 0.0f; | 
					
						
							|  |  |  | 				float radius = 0.0f; | 
					
						
							|  |  |  | 				float strength = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				float velocity_val = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				int part_index = -1; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				 *	With predefined radius, there is no variation between particles. | 
					
						
							|  |  |  | 				 *	It's enough to just find the nearest one. | 
					
						
							|  |  |  | 				 */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					KDTreeNearest nearest; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 					float smooth_range, part_solidradius; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* Find nearest particle and get distance to it	*/ | 
					
						
							|  |  |  | 					BLI_kdtree_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* if outside maximum range, no other particle can influence either */ | 
					
						
							|  |  |  | 					if (nearest.dist > range) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 					if (brush->flags & MOD_DPAINT_PART_RAD) { | 
					
						
							|  |  |  | 						/* use particles individual size */ | 
					
						
							|  |  |  | 						ParticleData *pa = psys->particles + nearest.index; | 
					
						
							|  |  |  | 						part_solidradius = pa->size; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							|  |  |  | 						part_solidradius = solidradius; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					radius = part_solidradius + smooth; | 
					
						
							|  |  |  | 					if (nearest.dist < radius) { | 
					
						
							|  |  |  | 						/* distances inside solid radius has maximum influence -> dist = 0	*/ | 
					
						
							|  |  |  | 						smooth_range = (nearest.dist - part_solidradius); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						if (smooth_range < 0.0f) smooth_range = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 						/* do smoothness if enabled	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						if (smooth) smooth_range /= smooth; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 						strength = 1.0f - smooth_range; | 
					
						
							|  |  |  | 						disp_intersect = radius - nearest.dist; | 
					
						
							|  |  |  | 						part_index = nearest.index; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				/* If using random per particle radius and closest particle didn't give max influence	*/ | 
					
						
							|  |  |  | 				if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) { | 
					
						
							|  |  |  | 					/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					 *	If we use per particle radius, we have to sample all particles | 
					
						
							|  |  |  | 					 *	within max radius range | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 					KDTreeNearest *nearest; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					int n, particles = 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					float smooth_range = smooth * (1.0f - strength), dist; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					/* calculate max range that can have particles with higher influence than the nearest one */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					float max_range = smooth - strength * smooth + solidradius; | 
					
						
							| 
									
										
										
										
											2012-12-02 16:01:06 +00:00
										 |  |  | 					/* Make gcc happy! */ | 
					
						
							|  |  |  | 					dist = max_range; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 					particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					/* Find particle that produces highest influence */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					for (n = 0; n < particles; n++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						ParticleData *pa = psys->particles + nearest[n].index; | 
					
						
							|  |  |  | 						float s_range; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						/* skip if out of range */ | 
					
						
							|  |  |  | 						if (nearest[n].dist > (pa->size + smooth)) | 
					
						
							|  |  |  | 							continue; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						/* update hit data */ | 
					
						
							|  |  |  | 						s_range = nearest[n].dist - pa->size; | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 						/* skip if higher influence is already found */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						if (smooth_range < s_range) | 
					
						
							|  |  |  | 							continue; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						/* update hit data */ | 
					
						
							|  |  |  | 						smooth_range = s_range; | 
					
						
							|  |  |  | 						dist = nearest[n].dist; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						part_index = nearest[n].index; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						/* If inside solid range and no disp depth required, no need to seek further */ | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 						if ( (s_range < 0.0f) && | 
					
						
							|  |  |  | 						     (surface->type != MOD_DPAINT_SURFACE_T_DISPLACE) && | 
					
						
							|  |  |  | 						     (surface->type != MOD_DPAINT_SURFACE_T_WAVE)) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 							break; | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 					if (nearest) MEM_freeN(nearest); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					/* now calculate influence for this particle */ | 
					
						
							| 
									
										
										
										
											2011-08-28 16:36:47 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						float rad = radius + smooth, str; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						if ((rad - dist) > disp_intersect) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 							disp_intersect = radius - dist; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 							radius = rad; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* do smoothness if enabled	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						if (smooth_range < 0.0f) smooth_range = 0.0f; | 
					
						
							|  |  |  | 						if (smooth) smooth_range /= smooth; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						str = 1.0f - smooth_range; | 
					
						
							|  |  |  | 						/* if influence is greater, use this one	*/ | 
					
						
							|  |  |  | 						if (str > strength) strength = str; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 				if (strength > 0.001f) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					float paintColor[4] = {0.0f}; | 
					
						
							|  |  |  | 					float depth = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					/* apply velocity */ | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 					if ((brush->flags & MOD_DPAINT_USES_VELOCITY) && (part_index != -1)) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						float velocity[3]; | 
					
						
							|  |  |  | 						ParticleData *pa = psys->particles + part_index; | 
					
						
							|  |  |  | 						mul_v3_v3fl(velocity, pa->state.vel, particle_timestep); | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						/* substract canvas point velocity */ | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 						if (bData->velocity) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 							sub_v3_v3(velocity, bData->velocity[index].v); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						velocity_val = len_v3(velocity); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 						/* store brush velocity for smudge */ | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 						if ( (surface->type == MOD_DPAINT_SURFACE_T_PAINT) && | 
					
						
							|  |  |  | 						     (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity)) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							copy_v3_v3(&bData->brush_velocity[index * 4], velocity); | 
					
						
							|  |  |  | 							mul_v3_fl(&bData->brush_velocity[index * 4], 1.0f / velocity_val); | 
					
						
							|  |  |  | 							bData->brush_velocity[index * 4 + 3] = velocity_val; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 						copy_v3_v3(paintColor, &brush->r); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-12-01 18:49:42 +00:00
										 |  |  | 					else if ( (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) || | 
					
						
							|  |  |  | 					          (surface->type == MOD_DPAINT_SURFACE_T_WAVE)) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						/* get displace depth	*/ | 
					
						
							| 
									
										
										
										
											2011-11-11 12:00:08 +00:00
										 |  |  | 						disp_intersect = (1.0f - sqrtf(disp_intersect / radius)) * radius; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 						depth = (radius - disp_intersect) / bData->bNormal[index].normal_scale; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						if (depth < 0.0f) depth = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-22 16:16:14 +00:00
										 |  |  | 	BLI_end_threaded_malloc(); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	BLI_kdtree_free(tree); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* paint a single point of defined proximity radius to the surface */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  |                                          Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale) | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-08 12:05:34 +00:00
										 |  |  | 	int index; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	float brush_radius = brush->paint_distance * surface->radius_scale; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	Vec3f brushVel; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 	if (brush->flags & MOD_DPAINT_USES_VELOCITY) | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 		dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *	Loop through every surface point | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		float distance = len_v3v3(pointCoord, bData->realCoord[bData->s_pos[index]].v); | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 		float colorband[4] = {0.0f}; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		float strength; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		if (distance > brush_radius) continue; | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		/* Smooth range or color ramp	*/ | 
					
						
							|  |  |  | 		if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH || | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 		    brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 			strength = 1.0f - distance / brush_radius; | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 			CLAMP(strength, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-03-09 03:46:30 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			strength = 1.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		if (strength >= 0.001f) { | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 			float paintColor[3] = {0.0f}; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			float depth = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 			float velocity_val = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			/* material */ | 
					
						
							| 
									
										
										
										
											2011-11-09 15:46:53 +00:00
										 |  |  | 			if (brush_usesMaterial(brush, scene)) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				float alpha_factor = 1.0f; | 
					
						
							|  |  |  | 				float hit_coord[3]; | 
					
						
							|  |  |  | 				MVert *mvert = brush->dm->getVertArray(brush->dm); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				/* use dummy coord of first vertex */ | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 				copy_v3_v3(hit_coord, mvert[0].co); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				mul_m4_v3(brushOb->obmat, hit_coord); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 			/* color ramp */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, (1.0f - strength), colorband)) | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 				strength = colorband[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			if (brush->flags & MOD_DPAINT_USES_VELOCITY) { | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 				float velocity[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* substract canvas point velocity */ | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 				if (bData->velocity) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 					sub_v3_v3v3(velocity, brushVel.v, bData->velocity[index].v); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 					copy_v3_v3(velocity, brushVel.v); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 				velocity_val = len_v3(velocity); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				/* store brush velocity for smudge */ | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 				if (surface->type == MOD_DPAINT_SURFACE_T_PAINT &&  | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				    brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					copy_v3_v3(&bData->brush_velocity[index * 4], velocity); | 
					
						
							|  |  |  | 					mul_v3_fl(&bData->brush_velocity[index * 4], 1.0f / velocity_val); | 
					
						
							|  |  |  | 					bData->brush_velocity[index * 4 + 3] = velocity_val; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 				    !(brush->flags & MOD_DPAINT_RAMP_ALPHA)) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 					paintColor[0] = colorband[0]; | 
					
						
							|  |  |  | 					paintColor[1] = colorband[1]; | 
					
						
							|  |  |  | 					paintColor[2] = colorband[2]; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-11-09 15:46:53 +00:00
										 |  |  | 					if (!brush_usesMaterial(brush, scene)) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						paintColor[0] = brush->r; | 
					
						
							|  |  |  | 						paintColor[1] = brush->g; | 
					
						
							|  |  |  | 						paintColor[2] = brush->b; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-07-10 16:08:26 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			         surface->type == MOD_DPAINT_SURFACE_T_WAVE) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* get displace depth	*/ | 
					
						
							|  |  |  | 				float disp_intersect = (1.0f - sqrtf((brush_radius - distance) / brush_radius)) * brush_radius; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				depth = (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (depth < 0.0f) depth = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /***************************** Dynamic Paint Step / Baking ******************************/ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Calculate current frame distances and directions for adjacency data | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, int force_init) | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintAdjData *adj_data = sData->adj_data; | 
					
						
							|  |  |  | 	Vec3f *realCoord = bData->realCoord; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	int index; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (bData->bNeighs) MEM_freeN(bData->bNeighs); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets * sizeof(struct BakeAdjPoint), "PaintEffectBake"); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	if (!bNeighs) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		int numOfNeighs = adj_data->n_num[index]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 			int n_index = adj_data->n_index[index] + i; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int t_index = adj_data->n_target[n_index]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* dir vec */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			sub_v3_v3v3(bNeighs[n_index].dir, realCoord[bData->s_pos[t_index]].v, realCoord[bData->s_pos[index]].v); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			/* dist */ | 
					
						
							|  |  |  | 			bNeighs[n_index].dist = len_v3(bNeighs[n_index].dir); | 
					
						
							|  |  |  | 			/* normalize dir */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			if (bNeighs[n_index].dist) mul_v3_fl(bNeighs[n_index].dir, 1.0f / bNeighs[n_index].dist); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate average values (single thread) */ | 
					
						
							|  |  |  | 	bData->average_dist = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		int i; | 
					
						
							|  |  |  | 		int numOfNeighs = adj_data->n_num[index]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 			bData->average_dist += (double)bNeighs[adj_data->n_index[index] + i].dist; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bData->average_dist  /= adj_data->total_targets; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | /* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force  */ | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs = sData->bData->bNeighs; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	int numOfNeighs = sData->adj_data->n_num[index]; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	closest_id[0] = closest_id[1] = -1; | 
					
						
							|  |  |  | 	closest_d[0] = closest_d[1] = -1.0f; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* find closest neigh */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 		int n_index = sData->adj_data->n_index[index] + i; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		float dir_dot = dot_v3v3(bNeighs[n_index].dir, force); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 07:24:48 +00:00
										 |  |  | 		if (dir_dot > closest_d[0] && dir_dot > 0.0f) { closest_d[0] = dir_dot; closest_id[0] = n_index; } | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (closest_d[0] < 0.0f) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* find second closest neigh */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 		int n_index = sData->adj_data->n_index[index] + i; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		float dir_dot = dot_v3v3(bNeighs[n_index].dir, force); | 
					
						
							|  |  |  | 		float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (n_index == closest_id[0]) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 		/* only accept neighbor at "other side" of the first one in relation to force dir
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  so make sure angle between this and closest neigh is greater than first angle */ | 
					
						
							|  |  |  | 		if (dir_dot > closest_d[1] && closest_dot < closest_d[0] && dir_dot > 0.0f) { | 
					
						
							|  |  |  | 			closest_d[1] = dir_dot; closest_id[1] = n_index; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if two valid neighs found, calculate how force effect is divided
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  evenly between them (so that d[0]+d[1] = 1.0)*/ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	if (closest_id[1] != -1) { | 
					
						
							|  |  |  | 		float force_proj[3]; | 
					
						
							|  |  |  | 		float tangent[3]; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		float neigh_diff = acosf(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir)); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		float force_intersect; | 
					
						
							|  |  |  | 		float temp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-24 23:22:34 +00:00
										 |  |  | 		/* project force vector on the plane determined by these two neighbor points
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		 *  and calculate relative force angle from it*/ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir); | 
					
						
							|  |  |  | 		normalize_v3(tangent); | 
					
						
							|  |  |  | 		force_intersect = dot_v3v3(force, tangent); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		madd_v3_v3v3fl(force_proj, force, tangent, (-1.0f) * force_intersect); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		normalize_v3(force_proj); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  | 		/* get drip factor based on force dir in relation to angle between those neighbors */ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		temp = dot_v3v3(bNeighs[closest_id[0]].dir, force_proj); | 
					
						
							|  |  |  | 		CLAMP(temp, -1.0f, 1.0f); /* float precision might cause values > 1.0f that return infinite */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		closest_d[1] = acosf(temp) / neigh_diff; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		closest_d[0] = 1.0f - closest_d[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* and multiply depending on how deeply force intersects surface */ | 
					
						
							|  |  |  | 		temp = fabs(force_intersect); | 
					
						
							|  |  |  | 		CLAMP(temp, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:42:12 +00:00
										 |  |  | 		mul_v2_fl(closest_d, acosf(temp) / (float)M_PI_2); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 		/* if only single neighbor, still linearize force intersection effect */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:42:12 +00:00
										 |  |  | 		closest_d[0] = 1.0f - acosf(closest_d[0]) / (float)M_PI_2; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, float timescale) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs = sData->bData->bNeighs; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	int index, steps, step; | 
					
						
							|  |  |  | 	float eff_scale, max_velocity = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!sData->adj_data) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* find max velocity */ | 
					
						
							|  |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float vel = bData->brush_velocity[index * 4 + 3]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		if (vel > max_velocity) max_velocity = vel; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 	steps = (int)ceil(max_velocity / bData->average_dist * timescale); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	CLAMP(steps, 0, 12); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	eff_scale = brush->smudge_strength / (float)steps * timescale; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (step = 0; step < steps; step++) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for (index = 0; index < sData->total_points; index++) { | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							|  |  |  | 			float smudge_str = bData->brush_velocity[index * 4 + 3]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			/* force targets */ | 
					
						
							|  |  |  | 			int closest_id[2]; | 
					
						
							|  |  |  | 			float closest_d[2]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (!smudge_str) continue; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/* get force affect points */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			surface_determineForceTargetPoints(sData, index, &bData->brush_velocity[index * 4], closest_d, closest_id); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* Apply movement towards those two points */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < 2; i++) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				int n_index = closest_id[i]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (n_index != -1 && closest_d[i] > 0.0f) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					float dir_dot = closest_d[i], dir_factor; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					float speed_scale = eff_scale * smudge_str / bNeighs[n_index].dist; | 
					
						
							|  |  |  | 					PaintPoint *ePoint = &((PaintPoint *)sData->type_data)[sData->adj_data->n_target[n_index]]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* just skip if angle is too extreme */ | 
					
						
							|  |  |  | 					if (dir_dot <= 0.0f) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					dir_factor = dir_dot * speed_scale; | 
					
						
							|  |  |  | 					if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* mix new color and alpha */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					ePoint->alpha = ePoint->alpha * (1.0f - dir_factor) + pPoint->alpha * dir_factor; | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-31 13:01:06 +00:00
										 |  |  | 					/* smudge "wet layer" */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					ePoint->e_alpha = ePoint->e_alpha * (1.0f - dir_factor) + pPoint->e_alpha * dir_factor; | 
					
						
							|  |  |  | 					pPoint->wetness *= (1.0f - dir_factor); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  |  *	Prepare data required by effects for current frame. | 
					
						
							|  |  |  |  *	Returns number of steps required | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale) | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	double average_force = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float shrink_speed = 0.0f, spread_speed = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	float fastest_effect, avg_dist; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int steps; | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							|  |  |  | 	Vec3f *realCoord = bData->realCoord; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Init force data if required */ | 
					
						
							|  |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { | 
					
						
							|  |  |  | 		float vel[3] = {0}; | 
					
						
							|  |  |  | 		ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* allocate memory for force data (dir vector + strength) */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		*force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces"); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (*force) { | 
					
						
							|  |  |  | 			#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				float forc[3] = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* apply force fields */ | 
					
						
							|  |  |  | 				if (effectors) { | 
					
						
							|  |  |  | 					EffectedPoint epoint; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 					pd_point_from_loc(scene, realCoord[bData->s_pos[index]].v, vel, index, &epoint); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					epoint.vel_to_sec = 1.0f; | 
					
						
							|  |  |  | 					pdDoEffectors(effectors, NULL, surface->effector_weights, &epoint, forc, NULL); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* if global gravity is enabled, add it too */ | 
					
						
							|  |  |  | 				if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) | 
					
						
							|  |  |  | 					/* also divide by 10 to about match default grav
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					 *  with default force strength (1.0) */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 					madd_v3_v3fl(forc, scene->physics_settings.gravity,  | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					             surface->effector_weights->global_gravity * surface->effector_weights->weight[0] / 10.f); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				/* add surface point velocity and acceleration if enabled */ | 
					
						
							|  |  |  | 				if (bData->velocity) { | 
					
						
							|  |  |  | 					if (surface->drip_vel) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						madd_v3_v3fl(forc, bData->velocity[index].v, surface->drip_vel * (-1.0f)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* acceleration */ | 
					
						
							|  |  |  | 					if (bData->prev_velocity && surface->drip_acc) { | 
					
						
							|  |  |  | 						float acc[3]; | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 						copy_v3_v3(acc, bData->velocity[index].v); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						sub_v3_v3(acc, bData->prev_velocity[index].v); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						madd_v3_v3fl(forc, acc, surface->drip_acc * (-1.0f)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/* force strength */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				(*force)[index * 4 + 3] = len_v3(forc); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				/* normalize and copy */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if ((*force)[index * 4 + 3]) mul_v3_fl(forc, 1.0f / (*force)[index * 4 + 3]); | 
					
						
							|  |  |  | 				copy_v3_v3(&((*force)[index * 4]), forc); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			/* calculate average values (single thread) */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				average_force += (*force)[index * 4 + 3]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			average_force /= sData->total_points; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		pdEndEffectors(&effectors); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-26 20:05:38 +00:00
										 |  |  | 	/* Get number of required steps using average point distance
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	 *  so that just a few ultra close pixels wont up substeps to max */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* adjust number of required substep by fastest active effect */ | 
					
						
							|  |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) | 
					
						
							|  |  |  | 		spread_speed = surface->spread_speed; | 
					
						
							|  |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) | 
					
						
							|  |  |  | 		shrink_speed = surface->shrink_speed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 	fastest_effect = max_fff(spread_speed, shrink_speed, average_force); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	avg_dist = bData->average_dist * CANVAS_REL_SIZE / getSurfaceDimension(sData); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	steps = (int)ceil(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 	CLAMP(steps, 1, 20); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return steps; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  *	Processes active effect step. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps) | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs = sData->bData->bNeighs; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float distance_scale = getSurfaceDimension(sData) / CANVAS_REL_SIZE; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int index; | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | 	timescale /= steps; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	if (!sData->adj_data) return; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 *	Spread Effect | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * surface->spread_speed * timescale; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Copy current surface to the previous points array to read unmodified values	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint)); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			int numOfNeighs = sData->adj_data->n_num[index]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			/*  Only reads values from the surface copy (prevPoint[]),
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 			 *	so this one is thread safe */ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 			/*	Loop through neighboring points	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 				int n_index = sData->adj_data->n_index[index] + i; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 				float w_factor; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				float speed_scale = (bNeighs[n_index].dist < eff_scale) ? 1.0f : eff_scale / bNeighs[n_index].dist; | 
					
						
							|  |  |  | 				float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f)) * 0.25f * surface->color_spread_speed; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				/* do color mixing */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				/* Only continue if surrounding point has higher wetness */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (ePoint->wetness < pPoint->wetness || ePoint->wetness < MIN_WETNESS) continue; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-30 06:12:47 +00:00
										 |  |  | 				w_factor = 1.0f / numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				CLAMP(w_factor, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				/* mix new wetness and color */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				pPoint->wetness = (1.0f - w_factor) * pPoint->wetness + w_factor * ePoint->wetness; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 				pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 *	Shrink Effect | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * surface->shrink_speed * timescale; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Copy current surface to the previous points array to read unmodified values	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint)); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			int numOfNeighs = sData->adj_data->n_num[index]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			float totalAlpha = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 				int n_index = sData->adj_data->n_index[index] + i; | 
					
						
							|  |  |  | 				float speed_scale = (bNeighs[n_index].dist < eff_scale) ? 1.0f : eff_scale / bNeighs[n_index].dist; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				float a_factor, ea_factor, w_factor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				totalAlpha += ePoint->e_alpha; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 				/* Check if neighboring point has lower alpha,
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 				 *  if so, decrease this point's alpha as well*/ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (pPoint->alpha <= 0.0f && pPoint->e_alpha <= 0.0f && pPoint->wetness <= 0.0f) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* decrease factor for dry paint alpha */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				a_factor = (1.0f - ePoint->alpha) / numOfNeighs * (pPoint->alpha - ePoint->alpha) * speed_scale; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (a_factor < 0.0f) a_factor = 0.0f; | 
					
						
							|  |  |  | 				/* decrease factor for wet paint alpha */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				ea_factor = (1.0f - ePoint->e_alpha) / 8 * (pPoint->e_alpha - ePoint->e_alpha) * speed_scale; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (ea_factor < 0.0f) ea_factor = 0.0f; | 
					
						
							|  |  |  | 				/* decrease factor for paint wetness */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				w_factor = (1.0f - ePoint->wetness) / 8 * (pPoint->wetness - ePoint->wetness) * speed_scale; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				if (w_factor < 0.0f) w_factor = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-24 17:40:02 +00:00
										 |  |  | 				pPoint->alpha -= a_factor; | 
					
						
							|  |  |  | 				if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f; | 
					
						
							|  |  |  | 				pPoint->e_alpha -= ea_factor; | 
					
						
							|  |  |  | 				if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f; | 
					
						
							|  |  |  | 				pPoint->wetness -= w_factor; | 
					
						
							|  |  |  | 				if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 *	Drip Effect | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * timescale / 2.0f; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		/* Copy current surface to the previous points array to read unmodified values	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		for (index = 0; index < sData->total_points; index++) { | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			PaintPoint *pPoint_prev = &prevPoint[index]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			int closest_id[2]; | 
					
						
							|  |  |  | 			float closest_d[2]; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			/* adjust drip speed depending on wetness */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 			float w_factor = pPoint_prev->wetness - 0.025f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			if (w_factor <= 0) continue; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 			CLAMP(w_factor, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			/* get force affect points */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			surface_determineForceTargetPoints(sData, index, &force[index * 4], closest_d, closest_id); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			/* Apply movement towards those two points */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < 2; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				int n_index = closest_id[i]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (n_index != -1 && closest_d[i] > 0.0f) { | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					float dir_dot = closest_d[i], dir_factor, a_factor; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					float speed_scale = eff_scale * force[index * 4 + 3] / bNeighs[n_index].dist; | 
					
						
							|  |  |  | 					PaintPoint *ePoint = &((PaintPoint *)sData->type_data)[sData->adj_data->n_target[n_index]]; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					float e_wet = ePoint->wetness; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 					/* just skip if angle is too extreme */ | 
					
						
							|  |  |  | 					if (dir_dot <= 0.0f) continue; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor; | 
					
						
							|  |  |  | 					if (dir_factor > 0.5f) dir_factor = 0.5f; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-17 14:43:20 +00:00
										 |  |  | 					/* mix new wetness */ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 					ePoint->wetness += dir_factor; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* mix new color */ | 
					
						
							|  |  |  | 					a_factor = dir_factor / pPoint_prev->wetness; | 
					
						
							|  |  |  | 					CLAMP(a_factor, 0.0f, 1.0f); | 
					
						
							|  |  |  | 					mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor); | 
					
						
							|  |  |  | 					/* dripping is supposed to preserve alpha level */ | 
					
						
							|  |  |  | 					if (pPoint_prev->e_alpha > ePoint->e_alpha) { | 
					
						
							|  |  |  | 						ePoint->e_alpha += a_factor * pPoint_prev->e_alpha; | 
					
						
							|  |  |  | 						if (ePoint->e_alpha > pPoint_prev->e_alpha) | 
					
						
							|  |  |  | 							ePoint->e_alpha = pPoint_prev->e_alpha; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					/* decrease paint wetness on current point */ | 
					
						
							|  |  |  | 					pPoint->wetness -= (ePoint->wetness - e_wet); | 
					
						
							|  |  |  | 					CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	BakeAdjPoint *bNeighs = sData->bData->bNeighs; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	int index; | 
					
						
							|  |  |  | 	int steps, ss; | 
					
						
							|  |  |  | 	float dt, min_dist, damp_factor; | 
					
						
							|  |  |  | 	float wave_speed = surface->wave_speed; | 
					
						
							|  |  |  | 	double average_dist = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 	const float canvas_size = getSurfaceDimension(sData); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	float wave_scale = CANVAS_REL_SIZE / canvas_size; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate memory */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points * sizeof(PaintWavePoint), "Temp previous points for wave simulation"); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	if (!prevPoint) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate average neigh distance (single thread) */ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 		int numOfNeighs = sData->adj_data->n_num[index]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 			average_dist += bNeighs[sData->adj_data->n_index[index] + i].dist; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	average_dist  *= wave_scale / sData->adj_data->total_targets; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* determine number of required steps */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	steps = (int)ceil((WAVE_TIME_FAC * timescale * surface->wave_timescale) / (average_dist / wave_speed / 3)); | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	CLAMP(steps, 1, 20); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	timescale /= steps; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* apply simulation values for final timescale */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	dt = WAVE_TIME_FAC * timescale * surface->wave_timescale; | 
					
						
							|  |  |  | 	min_dist = wave_speed * dt * 1.5f; | 
					
						
							|  |  |  | 	damp_factor = pow((1.0f - surface->wave_damping), timescale * surface->wave_timescale); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (ss = 0; ss < steps; ss++) { | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* copy previous frame data */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(PaintWavePoint)); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		#pragma omp parallel for schedule(static)
 | 
					
						
							|  |  |  | 		for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintWavePoint *wPoint = &((PaintWavePoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			int numOfNeighs = sData->adj_data->n_num[index]; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			float force = 0.0f, avg_dist = 0.0f, avg_height = 0.0f; | 
					
						
							|  |  |  | 			int numOfN = 0, numOfRN = 0; | 
					
						
							|  |  |  | 			int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 			if (wPoint->state > 0) continue; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* calculate force from surrounding points */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (i = 0; i < numOfNeighs; i++) { | 
					
						
							|  |  |  | 				int n_index = sData->adj_data->n_index[index] + i; | 
					
						
							|  |  |  | 				float dist = bNeighs[n_index].dist * wave_scale; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				PaintWavePoint *tPoint = &prevPoint[sData->adj_data->n_target[n_index]]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (!dist || tPoint->state > 0) continue; | 
					
						
							|  |  |  | 				if (dist < min_dist) dist = min_dist; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				avg_dist += dist; | 
					
						
							|  |  |  | 				numOfN++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* count average height for edge points for open borders */ | 
					
						
							|  |  |  | 				if (!(sData->adj_data->flags[sData->adj_data->n_target[n_index]] & ADJ_ON_MESH_EDGE)) { | 
					
						
							|  |  |  | 					avg_height += tPoint->height; | 
					
						
							|  |  |  | 					numOfRN++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				force += (tPoint->height - wPoint->height) / (dist * dist); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			avg_dist = (numOfN) ? avg_dist / numOfN : 0.0f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (surface->flags & MOD_DPAINT_WAVE_OPEN_BORDERS && | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 			    sData->adj_data->flags[index] & ADJ_ON_MESH_EDGE) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				/* if open borders, apply a fake height to keep waves going on */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				avg_height = (numOfRN) ? avg_height / numOfRN : 0.0f; | 
					
						
							|  |  |  | 				wPoint->height = (dt * wave_speed * avg_height + wPoint->height * avg_dist) / (avg_dist + dt * wave_speed); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			/* else do wave eq */ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			else { | 
					
						
							|  |  |  | 				/* add force towards zero height based on average dist */ | 
					
						
							|  |  |  | 				if (avg_dist) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					force += (0.0f - wPoint->height) * surface->wave_spring / (avg_dist * avg_dist) / 2.0f; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* change point velocity */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				wPoint->velocity += force * dt * wave_speed * wave_speed; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 				/* damping */ | 
					
						
							|  |  |  | 				wPoint->velocity *= damp_factor; | 
					
						
							|  |  |  | 				/* and new height */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				wPoint->height += wPoint->velocity * dt; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	/* reset state */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		PaintWavePoint *wPoint = &((PaintWavePoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 		/* if there wasnt any brush intersection, clear isect height */ | 
					
						
							|  |  |  | 		if (wPoint->state == DPAINT_WAVE_NONE) { | 
					
						
							|  |  |  | 			wPoint->brush_isect = 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		wPoint->state = DPAINT_WAVE_NONE; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(prevPoint); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | /* Do dissolve and fading effects */ | 
					
						
							| 
									
										
										
										
											2011-08-21 19:03:47 +00:00
										 |  |  | static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float timescale) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	int index; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/* Do drying dissolve effects */ | 
					
						
							|  |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			/* drying */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 			if (surface->flags & MOD_DPAINT_USE_DRYING) { | 
					
						
							|  |  |  | 				if (pPoint->wetness >= MIN_WETNESS) { | 
					
						
							|  |  |  | 					int i; | 
					
						
							|  |  |  | 					float dry_ratio, f_color[4]; | 
					
						
							|  |  |  | 					float p_wetness = pPoint->wetness; | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 					value_dissolve(&pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG)); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					if (pPoint->wetness < surface->color_dry_threshold) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						dry_ratio = pPoint->wetness / p_wetness; | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 						 *	Slowly "shift" paint from wet layer to dry layer as it drys: | 
					
						
							|  |  |  | 						 */ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 						/* make sure alpha values are within proper range */ | 
					
						
							|  |  |  | 						CLAMP(pPoint->alpha, 0.0f, 1.0f); | 
					
						
							|  |  |  | 						CLAMP(pPoint->e_alpha, 0.0f, 1.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* get current final blended color of these layers */ | 
					
						
							|  |  |  | 						blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); | 
					
						
							|  |  |  | 						/* reduce wet layer alpha by dry factor */ | 
					
						
							|  |  |  | 						pPoint->e_alpha *= dry_ratio; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* now calculate new alpha for dry layer that keeps final blended color unchanged */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						pPoint->alpha = (f_color[3] - pPoint->e_alpha) / (1.0f - pPoint->e_alpha); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 						/* for each rgb component, calculate a new dry layer color that keeps the final blend color
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 						 *  with these new alpha values. (wet layer color doesnt change)*/ | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 						if (pPoint->alpha) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 							for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 								pPoint->color[i] = (f_color[i] * f_color[3] - pPoint->e_color[i] * pPoint->e_alpha) / (pPoint->alpha * (1.0f - pPoint->e_alpha)); | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-11-05 07:39:59 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 					pPoint->state = DPAINT_PAINT_WET; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				/* in case of just dryed paint, just mix it to the dry layer and mark it empty */ | 
					
						
							|  |  |  | 				else if (pPoint->state > 0) { | 
					
						
							|  |  |  | 					float f_color[4]; | 
					
						
							|  |  |  | 					blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); | 
					
						
							|  |  |  | 					copy_v3_v3(pPoint->color, f_color); | 
					
						
							|  |  |  | 					pPoint->alpha = f_color[3]; | 
					
						
							|  |  |  | 					/* clear wet layer */ | 
					
						
							|  |  |  | 					pPoint->wetness = 0.0f; | 
					
						
							|  |  |  | 					pPoint->e_alpha = 0.0f; | 
					
						
							|  |  |  | 					pPoint->state = DPAINT_PAINT_DRY; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			if (surface->flags & MOD_DPAINT_DISSOLVE) { | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 				value_dissolve(&pPoint->alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 				value_dissolve(&pPoint->e_alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 		/* dissolve for float types */ | 
					
						
							|  |  |  | 		else if (surface->flags & MOD_DPAINT_DISSOLVE && | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		         (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 		          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			float *point = &((float *)sData->type_data)[index]; | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 			/* log or linear */ | 
					
						
							| 
									
										
										
										
											2012-11-04 06:21:09 +00:00
										 |  |  | 			value_dissolve(point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); | 
					
						
							| 
									
										
										
										
											2011-06-18 18:41:20 +00:00
										 |  |  | 			if (*point < 0.0f) *point = 0.0f; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							|  |  |  | 	DerivedMesh *dm = surface->canvas->dm; | 
					
						
							|  |  |  | 	MVert *mvert = dm->getVertArray(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int numOfVerts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!bData->prev_verts) return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	/* matrix comparison */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		int j; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (j = 0; j < 4; j++) | 
					
						
							|  |  |  | 			if (bData->prev_obmat[i][j] != ob->obmat[i][j]) return 1; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* vertices */ | 
					
						
							|  |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (i = 0; i < numOfVerts; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		int j; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		for (j = 0; j < 3; j++) | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			if (bData->prev_verts[i].co[j] != mvert[i].co[j]) { | 
					
						
							|  |  |  | 				ret = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 10:46:26 +00:00
										 |  |  | static int surface_needsVelocityData(DynamicPaintSurface *surface, Scene *scene) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 	if (surface_getBrushFlags(surface, scene) & BRUSH_USES_VELOCITY) | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int surface_needsAccelerationData(DynamicPaintSurface *surface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | /* Prepare for surface step by creating PaintBakeNormal data */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *scene, Object *ob) | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							|  |  |  | 	PaintAdjData *adj_data = sData->adj_data; | 
					
						
							|  |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							|  |  |  | 	DerivedMesh *dm = surface->canvas->dm; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	int index, new_bdata = 0; | 
					
						
							| 
									
										
										
										
											2011-11-11 10:46:26 +00:00
										 |  |  | 	int do_velocity_data = surface_needsVelocityData(surface, scene); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	int do_accel_data = surface_needsAccelerationData(surface); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int canvasNumOfVerts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 	MVert *mvert = dm->getVertArray(dm); | 
					
						
							|  |  |  | 	Vec3f *canvas_verts; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	if (bData) { | 
					
						
							|  |  |  | 		int surface_moved = dynamicPaint_surfaceHasMoved(surface, ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* get previous speed for accelertaion */ | 
					
						
							|  |  |  | 		if (do_accel_data && bData->prev_velocity && bData->velocity) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* reset speed vectors */ | 
					
						
							|  |  |  | 		if (do_velocity_data && bData->velocity && (bData->clear || !surface_moved)) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			memset(bData->velocity, 0, sData->total_points * sizeof(Vec3f)); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* if previous data exists and mesh hasn't moved, no need to recalc */ | 
					
						
							|  |  |  | 		if (!surface_moved) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	canvas_verts = (struct Vec3f *) MEM_mallocN(canvasNumOfVerts * sizeof(struct Vec3f), "Dynamic Paint transformed canvas verts"); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	if (!canvas_verts) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	/* allocate memory if required */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	if (!bData) { | 
					
						
							|  |  |  | 		sData->bData = bData = (struct PaintBakeData *) MEM_callocN(sizeof(struct PaintBakeData), "Dynamic Paint bake data"); | 
					
						
							|  |  |  | 		if (!bData) { | 
					
						
							|  |  |  | 			if (canvas_verts) MEM_freeN(canvas_verts); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Init bdata */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		bData->bNormal = (struct PaintBakeNormal *) MEM_mallocN(sData->total_points * sizeof(struct PaintBakeNormal), "Dynamic Paint step data"); | 
					
						
							|  |  |  | 		bData->s_pos = MEM_mallocN(sData->total_points * sizeof(unsigned int), "Dynamic Paint bData s_pos"); | 
					
						
							|  |  |  | 		bData->s_num = MEM_mallocN(sData->total_points * sizeof(unsigned int), "Dynamic Paint bData s_num"); | 
					
						
							|  |  |  | 		bData->realCoord = (struct Vec3f *) MEM_mallocN(surface_totalSamples(surface) * sizeof(Vec3f), "Dynamic Paint point coords"); | 
					
						
							|  |  |  | 		bData->prev_verts = MEM_mallocN(canvasNumOfVerts * sizeof(MVert), "Dynamic Paint bData prev_verts"); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* if any allocation failed, free everything */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		if (!bData->bNormal || !bData->s_pos || !bData->s_num || !bData->realCoord || !canvas_verts) { | 
					
						
							|  |  |  | 			if (bData->bNormal) MEM_freeN(bData->bNormal); | 
					
						
							|  |  |  | 			if (bData->s_pos) MEM_freeN(bData->s_pos); | 
					
						
							|  |  |  | 			if (bData->s_num) MEM_freeN(bData->s_num); | 
					
						
							|  |  |  | 			if (bData->realCoord) MEM_freeN(bData->realCoord); | 
					
						
							|  |  |  | 			if (canvas_verts) MEM_freeN(canvas_verts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 			return setError(surface->canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		new_bdata = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (do_velocity_data && !bData->velocity) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		bData->velocity = (struct Vec3f *) MEM_callocN(sData->total_points * sizeof(Vec3f), "Dynamic Paint velocity"); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (do_accel_data && !bData->prev_velocity) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		bData->prev_velocity = (struct Vec3f *) MEM_mallocN(sData->total_points * sizeof(Vec3f), "Dynamic Paint prev velocity"); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		/* copy previous vel */ | 
					
						
							|  |  |  | 		if (bData->prev_velocity && bData->velocity) | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f)); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 *	Make a transformed copy of canvas derived mesh vertices to avoid recalculation. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 	bData->mesh_bounds.valid = 0; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (index = 0; index < canvasNumOfVerts; index++) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 		copy_v3_v3(canvas_verts[index].v, mvert[index].co); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		mul_m4_v3(ob->obmat, canvas_verts[index].v); | 
					
						
							| 
									
										
										
										
											2011-11-16 18:32:28 +00:00
										 |  |  | 		boundInsert(&bData->mesh_bounds, canvas_verts[index].v); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 *	Prepare each surface point for a new step | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	#pragma omp parallel for schedule(static)
 | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	for (index = 0; index < sData->total_points; index++) { | 
					
						
							| 
									
										
										
										
											2011-12-17 16:22:08 +00:00
										 |  |  | 		float prev_point[3] = {0.0f, 0.0f, 0.0f}; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		if (do_velocity_data && !new_bdata) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 		 *	Calculate current 3D-position and normal of each surface point | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | 
					
						
							|  |  |  | 			float n1[3], n2[3], n3[3]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							|  |  |  | 			PaintUVPoint *tPoint = &((PaintUVPoint *)f_data->uv_p)[index]; | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | 			int ss; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			bData->s_num[index] = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			bData->s_pos[index] = index * bData->s_num[index]; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | 			/* per sample coordinates */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (ss = 0; ss < bData->s_num[index]; ss++) { | 
					
						
							|  |  |  | 				interp_v3_v3v3v3(bData->realCoord[bData->s_pos[index] + ss].v, | 
					
						
							| 
									
										
										
										
											2012-04-29 17:11:40 +00:00
										 |  |  | 				                 canvas_verts[tPoint->v1].v, | 
					
						
							|  |  |  | 				                 canvas_verts[tPoint->v2].v, | 
					
						
							|  |  |  | 				                 canvas_verts[tPoint->v3].v, | 
					
						
							|  |  |  | 				                 f_data->barycentricWeights[index * bData->s_num[index] + ss].v); | 
					
						
							| 
									
										
										
										
											2011-06-17 18:04:56 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* Calculate current pixel surface normal	*/ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			normal_short_to_float_v3(n1, mvert[tPoint->v1].no); | 
					
						
							|  |  |  | 			normal_short_to_float_v3(n2, mvert[tPoint->v2].no); | 
					
						
							|  |  |  | 			normal_short_to_float_v3(n3, mvert[tPoint->v3].no); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 17:11:40 +00:00
										 |  |  | 			interp_v3_v3v3v3(bData->bNormal[index].invNorm, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			                 n1, n2, n3, f_data->barycentricWeights[index * bData->s_num[index]].v); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			mul_mat3_m4_v3(ob->obmat, bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 			normalize_v3(bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 			negate_v3(bData->bNormal[index].invNorm); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			int ss; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			if (surface->flags & MOD_DPAINT_ANTIALIAS && adj_data) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				bData->s_num[index] = adj_data->n_num[index] + 1; | 
					
						
							|  |  |  | 				bData->s_pos[index] = adj_data->n_index[index] + index; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				bData->s_num[index] = 1; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 				bData->s_pos[index] = index; | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			/* calculate position for each sample */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			for (ss = 0; ss < bData->s_num[index]; ss++) { | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				/* first sample is always point center */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				copy_v3_v3(bData->realCoord[bData->s_pos[index] + ss].v, canvas_verts[index].v); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				if (ss > 0) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					int t_index = adj_data->n_index[index] + (ss - 1); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 					/* get vertex position at 1/3 of each neigh edge */ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 					mul_v3_fl(bData->realCoord[bData->s_pos[index] + ss].v, 2.0f / 3.0f); | 
					
						
							|  |  |  | 					madd_v3_v3fl(bData->realCoord[bData->s_pos[index] + ss].v, canvas_verts[adj_data->n_target[t_index]].v, 1.0f / 3.0f); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* normal */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			normal_short_to_float_v3(bData->bNormal[index].invNorm, mvert[index].no); | 
					
						
							|  |  |  | 			mul_mat3_m4_v3(ob->obmat, bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 			normalize_v3(bData->bNormal[index].invNorm); | 
					
						
							|  |  |  | 			negate_v3(bData->bNormal[index].invNorm); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* Prepare surface normal directional scale to easily convert
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 		 *  brush intersection amount between global and local space */ | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 		    surface->type == MOD_DPAINT_SURFACE_T_WAVE) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			float temp_nor[3]; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | 
					
						
							|  |  |  | 				normal_short_to_float_v3(temp_nor, mvert[index].no); | 
					
						
							|  |  |  | 				normalize_v3(temp_nor); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				float n1[3], n2[3], n3[3]; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | 
					
						
							|  |  |  | 				PaintUVPoint *tPoint = &((PaintUVPoint *)f_data->uv_p)[index]; | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				normal_short_to_float_v3(n1, mvert[tPoint->v1].no); | 
					
						
							|  |  |  | 				normal_short_to_float_v3(n2, mvert[tPoint->v2].no); | 
					
						
							|  |  |  | 				normal_short_to_float_v3(n3, mvert[tPoint->v3].no); | 
					
						
							|  |  |  | 				interp_v3_v3v3v3(temp_nor, | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				                 n1, n2, n3, f_data->barycentricWeights[index * bData->s_num[index]].v); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			mul_v3_v3(temp_nor, ob->size); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			bData->bNormal[index].normal_scale = len_v3(temp_nor); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* calculate speed vector */ | 
					
						
							|  |  |  | 		if (do_velocity_data && !new_bdata && !bData->clear) { | 
					
						
							| 
									
										
										
										
											2011-10-28 14:46:09 +00:00
										 |  |  | 			sub_v3_v3v3(bData->velocity[index].v, bData->realCoord[bData->s_pos[index]].v, prev_point); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	MEM_freeN(canvas_verts); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* generate surface space partitioning grid */ | 
					
						
							|  |  |  | 	surfaceGenerateGrid(surface); | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 	/* calculate current frame adjacency point distances and global dirs */ | 
					
						
							|  |  |  | 	dynamicPaint_prepareAdjacencyData(surface, 0); | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 	/* Copy current frame vertices to check against in next frame */ | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	copy_m4_m4(bData->prev_obmat, ob->obmat); | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 	memcpy(bData->prev_verts, mvert, canvasNumOfVerts * sizeof(MVert)); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	bData->clear = 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  * Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PaintSurfaceData *sData = surface->data; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	PaintBakeData *bData = sData->bData; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	DynamicPaintCanvasSettings *canvas = surface->canvas; | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	int ret = 1; | 
					
						
							| 
									
										
										
										
											2012-09-11 02:18:27 +00:00
										 |  |  | 	if (sData->total_points < 1) return 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	dynamicPaint_surfacePreStep(surface, timescale); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  | 	 * Loop through surface's target paint objects and do painting | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		Base *base = NULL; | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  | 		GroupObject *go = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		Object *brushObj = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		ModifierData *md = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/* backup current scene frame */ | 
					
						
							|  |  |  | 		int scene_frame = scene->r.cfra; | 
					
						
							|  |  |  | 		float scene_subframe = scene->r.subframe; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 		/* either from group or from all objects */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (surface->brush_group) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			go = surface->brush_group->gobject.first; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			base = scene->base.first; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		while (base || go) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			brushObj = NULL; | 
					
						
							|  |  |  | 			/* select object */ | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 			if (surface->brush_group) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				if (go->ob) brushObj = go->ob; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				brushObj = base->object; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 			if (!brushObj) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				/* skip item */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 				if (surface->brush_group) go = go->next; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				else base = base->next; | 
					
						
							| 
									
										
										
										
											2012-05-19 13:55:54 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			/* next item */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 			if (surface->brush_group) | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 				go = go->next; | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 				base = base->next; | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			/* check if target has an active dp modifier	*/ | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 				DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				/* make sure we're dealing with a brush	*/ | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 				if (pmd2->brush) { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					DynamicPaintBrushSettings *brush = pmd2->brush; | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					BrushMaterials bMats = {0}; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					/* calculate brush speed vectors if required */ | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 					if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 						bData->brush_velocity = MEM_callocN(sData->total_points * sizeof(float) * 4, "Dynamic Paint brush velocity"); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						/* init adjacency data if not already */ | 
					
						
							|  |  |  | 						if (!sData->adj_data) | 
					
						
							|  |  |  | 							dynamicPaint_initAdjacencyData(surface, 1); | 
					
						
							|  |  |  | 						if (!bData->bNeighs) | 
					
						
							| 
									
										
										
										
											2012-01-24 17:28:50 +00:00
										 |  |  | 							dynamicPaint_prepareAdjacencyData(surface, 1); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* update object data on this subframe */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					if (subframe) { | 
					
						
							|  |  |  | 						scene_setSubframe(scene, subframe); | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 						subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* Prepare materials if required	*/ | 
					
						
							| 
									
										
										
										
											2011-11-09 15:46:53 +00:00
										 |  |  | 					if (brush_usesMaterial(brush, scene)) | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 						dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* Apply brush on the surface depending on it's collision type */ | 
					
						
							|  |  |  | 					/* Particle brush: */ | 
					
						
							|  |  |  | 					if (brush->collision == MOD_DPAINT_COL_PSYS) { | 
					
						
							| 
									
										
										
										
											2012-10-27 17:19:55 +00:00
										 |  |  | 						if (brush->psys && brush->psys->part && ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) && | 
					
						
							| 
									
										
										
										
											2012-05-20 19:49:27 +00:00
										 |  |  | 						    psys_check_enabled(brushObj, brush->psys)) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							/* Paint a particle system */ | 
					
						
							| 
									
										
										
										
											2012-05-05 14:33:36 +00:00
										 |  |  | 							BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM); | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 							dynamicPaint_paintParticles(surface, brush->psys, brush, timescale); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* Object center distance: */ | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 					else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) { | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 						dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale); | 
					
						
							| 
									
										
										
										
											2011-07-08 11:03:37 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* Mesh volume/proximity: */ | 
					
						
							|  |  |  | 					else if (brushObj != ob) { | 
					
						
							| 
									
										
										
										
											2011-11-10 13:00:27 +00:00
										 |  |  | 						dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 					/* free temp material data */ | 
					
						
							| 
									
										
										
										
											2011-11-09 15:46:53 +00:00
										 |  |  | 					if (brush_usesMaterial(brush, scene)) | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 						dynamicPaint_freeBrushMaterials(&bMats); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 					/* reset object to it's original state */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 					if (subframe) { | 
					
						
							|  |  |  | 						scene->r.cfra = scene_frame; | 
					
						
							|  |  |  | 						scene->r.subframe = scene_subframe; | 
					
						
							| 
									
										
										
										
											2013-03-22 17:08:55 +00:00
										 |  |  | 						subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene)); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/* process special brush effects, like smudge */ | 
					
						
							|  |  |  | 					if (bData->brush_velocity) { | 
					
						
							| 
									
										
										
										
											2011-11-20 10:52:25 +00:00
										 |  |  | 						if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE) | 
					
						
							| 
									
										
										
										
											2011-08-04 07:09:21 +00:00
										 |  |  | 							dynamicPaint_doSmudge(surface, brush, timescale); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 						MEM_freeN(bData->brush_velocity); | 
					
						
							|  |  |  | 						bData->brush_velocity = NULL; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	/* surfaces operations that use adjacency data */ | 
					
						
							| 
									
										
										
										
											2012-03-07 04:53:43 +00:00
										 |  |  | 	if (sData->adj_data && bData->bNeighs) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 		/* wave type surface simulation step */ | 
					
						
							|  |  |  | 		if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { | 
					
						
							|  |  |  | 			dynamicPaint_doWaveStep(surface, timescale); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		/* paint surface effects */ | 
					
						
							| 
									
										
										
										
											2012-03-07 04:53:43 +00:00
										 |  |  | 		if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT) { | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			int steps = 1, s; | 
					
						
							|  |  |  | 			PaintPoint *prevPoint; | 
					
						
							|  |  |  | 			float *force = NULL; | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			/* Allocate memory for surface previous points to read unchanged values from	*/ | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			prevPoint = MEM_mallocN(sData->total_points * sizeof(struct PaintPoint), "PaintSurfaceDataCopy"); | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 			if (!prevPoint) | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 				return setError(canvas, N_("Not enough free memory")); | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			/* Prepare effects and get number of required steps */ | 
					
						
							|  |  |  | 			steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale); | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 			for (s = 0; s < steps; s++) { | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 				dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 			/* Free temporary effect data	*/ | 
					
						
							|  |  |  | 			if (prevPoint) MEM_freeN(prevPoint); | 
					
						
							|  |  |  | 			if (force) MEM_freeN(force); | 
					
						
							| 
									
										
										
										
											2011-07-02 18:06:39 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-27 07:30:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  * Calculate a single frame and included subframes for surface | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-10-13 20:00:22 +00:00
										 |  |  | int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame) | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	float timescale = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 	/* apply previous displace on derivedmesh if incremental surface */ | 
					
						
							|  |  |  | 	if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) | 
					
						
							| 
									
										
										
										
											2012-01-16 17:18:07 +00:00
										 |  |  | 		dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm); | 
					
						
							| 
									
										
										
										
											2011-08-05 09:31:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-22 18:37:30 +00:00
										 |  |  | 	/* update bake data */ | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	dynamicPaint_generateBakeData(surface, scene, cObject);  | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	/* don't do substeps for first frame */ | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 	if (surface->substeps && (frame != surface->start_frame)) { | 
					
						
							|  |  |  | 		int st; | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 		timescale = 1.0f / (surface->substeps + 1); | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 16:04:15 +00:00
										 |  |  | 		for (st = 1; st <= surface->substeps; st++) { | 
					
						
							| 
									
										
										
										
											2012-05-12 16:11:34 +00:00
										 |  |  | 			float subframe = ((float) st) / (surface->substeps + 1); | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 			if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe)) return 0; | 
					
						
							| 
									
										
										
										
											2011-05-24 07:08:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-16 10:41:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-03 18:31:48 +00:00
										 |  |  | 	return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f); | 
					
						
							| 
									
										
										
										
											2011-11-10 17:43:37 +00:00
										 |  |  | } |