[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