[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [38620] branches/soc-2011-carrot/source: Dynamic Paint:

Miika Hamalainen miika.hamalainen at kolumbus.fi
Fri Jul 22 20:37:30 CEST 2011


Revision: 38620
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=38620
Author:   miikah
Date:     2011-07-22 18:37:30 +0000 (Fri, 22 Jul 2011)
Log Message:
-----------
Dynamic Paint:
* Surface bake data is no longer recalculated every frame, but only when surface mesh has moved/transformed. Results in multiple times better performance on high resolution surfaces when using sub-steps or surface is still.
* Heavily optimized particle brushes when random particle size enabled. Up to 10x speedup with large radius particles.
* Added an additional "grid" space partitioning structure for surfaces.
* Added bounding box checks for brushes.
* Smaller overall optimization.
* Further OpenMP parallelization.
* Added physics tab link to modifier panel.
* Fix: "Point Density" texture cache wasn't properly updated. Brushes can now use Point Density textures as well.
* Fix: Paint dissolve resulted in black color.
* Fix: KD-tree checkups weren't completely thread safe. Fixes possible crash with OpenMP enabled particle brushes.
* Fix: When brush was set to use a specific material, it was saved incorrectly and resulted in potential crashes on next load.

Modified Paths:
--------------
    branches/soc-2011-carrot/source/blender/blenkernel/BKE_dynamicpaint.h
    branches/soc-2011-carrot/source/blender/blenkernel/intern/dynamicpaint.c
    branches/soc-2011-carrot/source/blender/blenlib/BLI_kdtree.h
    branches/soc-2011-carrot/source/blender/blenlib/intern/BLI_kdtree.c
    branches/soc-2011-carrot/source/blender/blenloader/intern/readfile.c
    branches/soc-2011-carrot/source/blender/blenloader/intern/writefile.c
    branches/soc-2011-carrot/source/blender/editors/interface/interface_templates.c
    branches/soc-2011-carrot/source/blender/makesdna/DNA_dynamicpaint_types.h
    branches/soc-2011-carrot/source/blender/modifiers/intern/MOD_dynamicpaint.c
    branches/soc-2011-carrot/source/blender/render/intern/include/pointdensity.h
    branches/soc-2011-carrot/source/blender/render/intern/source/pointdensity.c
    branches/soc-2011-carrot/source/blenderplayer/bad_level_call_stubs/stubs.c

Modified: branches/soc-2011-carrot/source/blender/blenkernel/BKE_dynamicpaint.h
===================================================================
--- branches/soc-2011-carrot/source/blender/blenkernel/BKE_dynamicpaint.h	2011-07-22 18:29:17 UTC (rev 38619)
+++ branches/soc-2011-carrot/source/blender/blenkernel/BKE_dynamicpaint.h	2011-07-22 18:37:30 UTC (rev 38620)
@@ -17,6 +17,7 @@
 #include "DNA_dynamicpaint_types.h"
 
 struct PaintEffectData;
+struct PaintBakeData;
 
 /* Actual surface point	*/
 typedef struct PaintSurfaceData {
@@ -27,6 +28,7 @@
 	/* point neighbor data */
 	struct PaintAdjData *adj_data;
 
+	struct PaintBakeData *bData;
 	unsigned int total_points;
 
 } PaintSurfaceData;

Modified: branches/soc-2011-carrot/source/blender/blenkernel/intern/dynamicpaint.c
===================================================================
--- branches/soc-2011-carrot/source/blender/blenkernel/intern/dynamicpaint.c	2011-07-22 18:29:17 UTC (rev 38619)
+++ branches/soc-2011-carrot/source/blender/blenkernel/intern/dynamicpaint.c	2011-07-22 18:37:30 UTC (rev 38620)
@@ -81,11 +81,16 @@
 
 /* to read object material color	*/
 #include "DNA_texture_types.h"
+#include "../render/intern/include/pointdensity.h"
 #include "../render/intern/include/render_types.h"
 #include "../render/intern/include/voxeldata.h"
 #include "DNA_material_types.h"
 #include "RE_render_ext.h"
 
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
 #define DPOUTPUT_JPEG 0
 #define DPOUTPUT_PNG 1
 #define DPOUTPUT_OPENEXR 2
@@ -113,31 +118,54 @@
 
 /***************************** Internal Structs ***************************/
 
-typedef struct FaceAdv {
-	float no[3];
-	float no_q[3];
-} FaceAdv;
-
-typedef struct BB2d {
+typedef struct Bounds2D {
 	float min[2], max[2];
-} BB2d;
+} Bounds2D;
 
+typedef struct Bounds3D {
+	float min[3], max[3];
+} Bounds3D;
+
+typedef struct VolumeGrid {
+	int x,y,z;
+	Bounds3D grid_bounds;
+
+	Bounds3D *bounds;	/* (x*y*z) precalculated grid cell bounds */
+	unsigned int *s_pos; /* (x*y*z) search indexses */
+	unsigned int *s_num; /* (x*y*z) number of points */
+	unsigned int *t_index; /* actual point index,
+						   access: (s_pos+s_num) */
+} VolumeGrid;
+
 typedef struct Vec3f {
 	float v[3];
 } Vec3f;
 
+typedef struct BakeNeighPoint {
+	float dir[3];	/* vector pointing towards this neighbour */
+	float dist;		/* distance to */
+} BakeNeighPoint;
+
 /* Surface data used while processing a frame	*/
-typedef struct PaintBakePoint {
-	float invNorm[3];  /* current pixel world-space inverted normal. depends on face shading mode */
+typedef struct PaintBakeNormal {
+	float invNorm[3];  /* current pixel world-space inverted normal */
 	float normal_scale; /* normal directional scale for displace mapping */
-} PaintBakePoint;
+} PaintBakeNormal;
 
+/* Temp surface data used to process a frame */
 typedef struct PaintBakeData {
-	PaintBakePoint *bPoint;
-	unsigned int *s_index;		/* index to start reading point sample realcoords */
+	PaintBakeNormal *bNormal;
+	unsigned int *s_pos;		/* index to start reading point sample realCoord */
 	unsigned int *s_num;	/* num of samples for each point */
-	float *realCoord;  /* current pixel center world-space coordinates * numOfSamples
-					   *  ordered as (s_index+sample_num)*3*/
+	Vec3f *realCoord;  /* current pixel center world-space coordinates * numOfSamples
+					   *  ordered as (s_pos+sample_num)*/
+
+	BakeNeighPoint *bNeighs; /* current frame neighbour distances, if required */
+	VolumeGrid *grid;	/* space partitioning grid to optimize brush checks */
+
+	MVert *prev_verts;	/* copy of previous frame vertices. used observe surface movement */
+	float prev_obmat[4][4]; /* previous frame object matrix */
+
 } PaintBakeData;
 
 /* UV Image sequence format point	*/
@@ -161,12 +189,7 @@
 	float previous_vel[3];
 } EffVelPoint;
 
-typedef struct BakeNeighPoint {
-	float dir[3];	/* vector pointing towards this neighbour */
-	float dist;		/* distance to */
-} BakeNeighPoint;
 
-
 /* adjacency data flags */
 #define ADJ_ON_MESH_EDGE (1<<0)
 
@@ -316,11 +339,24 @@
 	BLI_uniquename_cb(surfaceDublicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
 }
 
-/* assumes source alpha > 0.0f */
+static int surface_totalSamples(DynamicPaintSurface *surface)
+{
+	if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ &&
+		surface->flags & MOD_DPAINT_ANTIALIAS)
+		return (surface->data->total_points*5);
+	if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
+		surface->flags & MOD_DPAINT_ANTIALIAS && surface->data->adj_data)
+		return (surface->data->total_points+surface->data->adj_data->total_targets);
+
+	return surface->data->total_points;
+}
+
+/* assumes source alpha > 0.0f or results NaN colors */
 static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alpha)
 {
 	float invFact = (s_alpha<t_alpha) ? 1.0f : t_alpha/s_alpha;
 	float factor = 1.0f - invFact;
+
 	/* set initial color depending on existing alpha */
 	t_color[0] = t_color[0]*invFact + s_color[0]*factor;
 	t_color[1] = t_color[1]*invFact + s_color[1]*factor;
@@ -334,6 +370,234 @@
 	t_color[2] = t_color[2]*invFact + s_color[2]*factor;
 }
 
+static int boundsIntersect(Bounds3D *b1, Bounds3D *b2)
+{
+	int i=2;
+	for (; i>=0; i-=1)
+		if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) return 0;
+	return 1;
+}
+
+static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist)
+{
+	int i=2;
+	for (; i>=0; i-=1)
+		if (!(b1->min[i] <= (b2->max[i]+dist) && b1->max[i] >= (b2->min[i]-dist))) return 0;
+	return 1;
+}
+
+static int boundIntersectPoint(Bounds3D *b, float point[3], float radius)
+{
+	int i=2;
+	for (; i>=0; i-=1)
+		if (!(b->min[i] <= (point[i]+radius) && b->max[i] >= (point[i]-radius))) return 0;
+	return 1;
+}
+
+static void boundInsert(Bounds3D *b, float point[3])
+{
+	int i=2;
+	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];
+	}
+}
+
+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 */
+	grid_bounds = MEM_callocN(sizeof(Bounds3D)*num_of_threads, "Grid Bounds");
+
+	bData->grid = MEM_callocN(sizeof(VolumeGrid), "Surface Grid");
+	grid = bData->grid;
+
+	if (grid && grid_bounds) {
+		int index, error = 0;
+		float dim_factor, volume, dim[3];
+		float tx,ty,tz;
+
+		/* initial values for each thread */
+		for (index = 0; index<num_of_threads; index++) {
+			VECCOPY(grid_bounds[index].min, bData->realCoord[bData->s_pos[0]].v);
+			VECCOPY(grid_bounds[index].max, bData->realCoord[bData->s_pos[0]].v);
+		}
+		VECCOPY(grid->grid_bounds.min, bData->realCoord[bData->s_pos[0]].v);
+		VECCOPY(grid->grid_bounds.max, bData->realCoord[bData->s_pos[0]].v);
+
+		/* calculate canvas dimensions */
+		#pragma omp parallel for schedule(static)
+		for (index = 1; index < sData->total_points; index++) {
+#ifdef _OPENMP
+			int id = omp_get_thread_num();
+			boundInsert(&grid_bounds[id], (bData->realCoord[bData->s_pos[index]].v));
+#else
+			boundInsert(&grid_bounds[0], (bData->realCoord[bData->s_pos[index]].v));
+#endif
+		}
+
+		/* get final dimensions */
+		for (index = 0; index<num_of_threads; index++) {
+			boundInsert(&grid->grid_bounds, grid_bounds[index].min);
+			boundInsert(&grid->grid_bounds, grid_bounds[index].max);
+		}
+
+		dim[0] = grid->grid_bounds.max[0]-grid->grid_bounds.min[0];
+		dim[1] = grid->grid_bounds.max[1]-grid->grid_bounds.min[1];
+		dim[2] = grid->grid_bounds.max[2]-grid->grid_bounds.min[2];
+
+		tx = dim[0];
+		ty = dim[1];
+		tz = dim[2];
+
+		/* deactivate zero axises */
+		if (!tx) {tx=1.0f; axis-=1;}
+		if (!ty) {ty=1.0f; axis-=1;}
+		if (!tz) {tz=1.0f; axis-=1;}
+
+		if (axis == 0)
+			return;
+
+		/* now with values scaled >= 1.0f, calculate scaled grid volume */
+		volume = tx*ty*tz;
+
+		/* determine final grid size by trying to fit average 10.000 points per grid cell */
+		dim_factor = pow(volume / ((double)sData->total_points / 10000.f), 1.0f/axis);
+
+		/* define final grid size using dim_factor, use min 3 for active axises */
+		grid->x = (int)floor(tx / dim_factor);
+		CLAMP(grid->x, (dim[0]) ? 3 : 1, 100);
+		grid->y = (int)floor(ty / dim_factor);
+		CLAMP(grid->y, (dim[1]) ? 3 : 1, 100);
+		grid->z = (int)floor(tz / dim_factor);
+		CLAMP(grid->z, (dim[2]) ? 3 : 1, 100);
+
+		grid_cells = grid->x*grid->y*grid->z;
+
+		//printf("final grid size %i,%i,%i\n", grid->x, grid->y, grid->z);
+
+		/* 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");
+		grid->s_num = MEM_callocN(sizeof(int) * grid_cells*num_of_threads, "Surface Grid Points");
+		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");
+
+		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)
+			for (index = 0; index < sData->total_points; index++) {
+				int x,y,z;
+				x = floor((bData->realCoord[bData->s_pos[index]].v[0] - grid->grid_bounds.min[0])/dim[0]*grid->x);
+				CLAMP(x, 0, grid->x-1);
+				y = floor((bData->realCoord[bData->s_pos[index]].v[1] - grid->grid_bounds.min[1])/dim[1]*grid->y);
+				CLAMP(y, 0, grid->y-1);
+				z = floor((bData->realCoord[bData->s_pos[index]].v[2] - grid->grid_bounds.min[2])/dim[2]*grid->z);
+				CLAMP(z, 0, grid->z-1);
+
+				temp_t_index[index] = x + y * grid->x + z * grid->x*grid->y;
+#ifdef _OPENMP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list