diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2014-09-18 11:06:25 +0400 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-01-20 11:30:01 +0300 |
commit | 226beb986690046adfdf10a3ed72034fa322ccdb (patch) | |
tree | a9dfd0f16c58d70566368cb9b0c3e695e06e44d9 /source/blender/physics | |
parent | bbae8f88b8f305a8ed85cab718d2a66b476da3c1 (diff) |
Added basic filtering feature for velocity smoothing.
This is part of the original method from "Volumetric Methods for
Simulation and Rendering of Hair". The current filter is a simple box
filter. Other energy-preserving filters such as gaussian filtering
can be implemented later.
The filter size is currently given as a cell count. This is not ideal,
rather it should use a geometrical length value, but this is too
abstract for proper artistical use. Eventually defining the whole grid
in terms of spatial size might work better (possibly using an external
object).
Diffstat (limited to 'source/blender/physics')
-rw-r--r-- | source/blender/physics/intern/BPH_mass_spring.cpp | 3 | ||||
-rw-r--r-- | source/blender/physics/intern/hair_volume.c | 71 | ||||
-rw-r--r-- | source/blender/physics/intern/implicit.h | 1 |
3 files changed, 75 insertions, 0 deletions
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 0fa14fa4eab..4d8f853a16b 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -431,6 +431,9 @@ static void cloth_calc_volume_force(ClothModifierData *clmd) } BPH_hair_volume_normalize_vertex_grid(vertex_grid); + /* apply velocity filter */ + BPH_hair_volume_vertex_grid_filter_box(vertex_grid, clmd->sim_parms->voxel_filter_size); + for (i = 0; i < numverts; i++) { float x[3], v[3], f[3], dfdx[3][3], dfdv[3][3]; diff --git a/source/blender/physics/intern/hair_volume.c b/source/blender/physics/intern/hair_volume.c index 2d5efa8260b..7f9704af9f6 100644 --- a/source/blender/physics/intern/hair_volume.c +++ b/source/blender/physics/intern/hair_volume.c @@ -71,6 +71,8 @@ BLI_INLINE void hair_grid_get_scale(int res, const float gmin[3], const float gm typedef struct HairGridVert { float velocity[3]; float density; + + float velocity_smooth[3]; } HairGridVert; typedef struct HairVertexGrid { @@ -293,6 +295,75 @@ void BPH_hair_volume_normalize_vertex_grid(HairVertexGrid *grid) } } +/* Velocity filter kernel + * See http://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29 + */ + +BLI_INLINE void hair_volume_filter_box_convolute(HairVertexGrid *grid, float invD, const int kernel_size[3], int i, int j, int k) +{ + int res = grid->res; + int p, q, r; + int minp = max_ii(i - kernel_size[0], 0), maxp = min_ii(i + kernel_size[0], res-1); + int minq = max_ii(j - kernel_size[1], 0), maxq = min_ii(j + kernel_size[1], res-1); + int minr = max_ii(k - kernel_size[2], 0), maxr = min_ii(k + kernel_size[2], res-1); + int offset, kernel_offset, kernel_dq, kernel_dr; + HairGridVert *verts; + float *vel_smooth; + + offset = i + (j + k*res)*res; + verts = grid->verts; + vel_smooth = verts[offset].velocity_smooth; + + kernel_offset = minp + (minq + minr*res)*res; + kernel_dq = res; + kernel_dr = res * res; + for (r = minr; r <= maxr; ++r) { + for (q = minq; q <= maxq; ++q) { + for (p = minp; p <= maxp; ++p) { + + madd_v3_v3fl(vel_smooth, verts[kernel_offset].velocity, invD); + + kernel_offset += 1; + } + kernel_offset += kernel_dq; + } + kernel_offset += kernel_dr; + } +} + +void BPH_hair_volume_vertex_grid_filter_box(HairVertexGrid *grid, int kernel_size) +{ + int size = hair_grid_size(grid->res); + int kernel_sizev[3] = {kernel_size, kernel_size, kernel_size}; + int tot; + float invD; + int i, j, k; + + if (kernel_size <= 0) + return; + + tot = kernel_size * 2 + 1; + invD = 1.0f / (float)(tot*tot*tot); + + /* clear values for convolution */ + for (i = 0; i < size; ++i) { + zero_v3(grid->verts[i].velocity_smooth); + } + + for (i = 0; i < grid->res; ++i) { + for (j = 0; j < grid->res; ++j) { + for (k = 0; k < grid->res; ++k) { + hair_volume_filter_box_convolute(grid, invD, kernel_sizev, i, j, k); + } + } + } + + /* apply as new velocity */ + for (i = 0; i < size; ++i) { + copy_v3_v3(grid->verts[i].velocity, grid->verts[i].velocity_smooth); + } +} + HairVertexGrid *BPH_hair_volume_create_vertex_grid(int res, const float gmin[3], const float gmax[3]) { int size = hair_grid_size(res); diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index 28c4cbcf7ae..2945b0787d4 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -155,6 +155,7 @@ void BPH_hair_volume_free_vertex_grid(struct HairVertexGrid *grid); void BPH_hair_volume_add_vertex(struct HairVertexGrid *grid, const float x[3], const float v[3]); void BPH_hair_volume_normalize_vertex_grid(struct HairVertexGrid *grid); +void BPH_hair_volume_vertex_grid_filter_box(struct HairVertexGrid *grid, int kernel_size); void BPH_hair_volume_vertex_grid_forces(struct HairVertexGrid *grid, const float x[3], const float v[3], float smoothfac, float pressurefac, float minpressure, float f[3], float dfdx[3][3], float dfdv[3][3]); |