Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp61
-rw-r--r--source/blender/physics/intern/hair_volume.c218
-rw-r--r--source/blender/physics/intern/implicit.h16
-rw-r--r--source/blender/physics/intern/implicit_blender.c27
4 files changed, 206 insertions, 116 deletions
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 1c45e1ed1f8..568aea6abe3 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -386,6 +386,64 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
}
}
+static void hair_get_boundbox(ClothModifierData *clmd, float gmin[3], float gmax[3])
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ unsigned int numverts = cloth->numverts;
+ int i;
+
+ INIT_MINMAX(gmin, gmax);
+ for (i = 0; i < numverts; i++) {
+ float x[3];
+ BPH_mass_spring_get_motion_state(data, i, x, NULL);
+ DO_MINMAX(x, gmin, gmax);
+ }
+}
+
+static void cloth_calc_volume_force(ClothModifierData *clmd)
+{
+ ClothSimSettings *parms = clmd->sim_parms;
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ int numverts = cloth->numverts;
+
+ /* 2.0f is an experimental value that seems to give good results */
+ float smoothfac = 2.0f * parms->velocity_smooth;
+ float collfac = 2.0f * parms->collider_friction;
+ float pressfac = parms->pressure;
+ float minpress = parms->pressure_threshold;
+ float gmin[3], gmax[3];
+ int i;
+
+ hair_get_boundbox(clmd, gmin, gmax);
+
+ /* gather velocities & density */
+ if (smoothfac > 0.0f || pressfac > 0.0f) {
+ HairVertexGrid *vertex_grid = BPH_hair_volume_create_vertex_grid(gmin, gmax);
+
+ for (i = 0; i < numverts; i++) {
+ float x[3], v[3];
+
+ BPH_mass_spring_get_motion_state(data, i, x, v);
+ BPH_hair_volume_add_vertex(vertex_grid, x, v);
+ }
+ BPH_hair_volume_normalize_vertex_grid(vertex_grid);
+
+ for (i = 0; i < numverts; i++) {
+ float x[3], v[3], f[3], dfdx[3][3], dfdv[3][3];
+
+ /* calculate volumetric forces */
+ BPH_mass_spring_get_motion_state(data, i, x, v);
+ BPH_hair_volume_vertex_grid_forces(vertex_grid, x, v, smoothfac, pressfac, minpress, f, dfdx, dfdv);
+ /* apply on hair data */
+ BPH_mass_spring_force_extern(data, i, f, dfdx, dfdv);
+ }
+
+ BPH_hair_volume_free_vertex_grid(vertex_grid);
+ }
+}
+
static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListBase *effectors, float time)
{
/* Collect forces and derivatives: F, dFdX, dFdV */
@@ -409,8 +467,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
BPH_mass_spring_force_gravity(data, gravity);
#endif
- // XXX TODO
-// hair_volume_forces(clmd, lF, lX, lV, numverts);
+ cloth_calc_volume_force(clmd);
#ifdef CLOTH_FORCE_DRAG
BPH_mass_spring_force_drag(data, drag);
diff --git a/source/blender/physics/intern/hair_volume.c b/source/blender/physics/intern/hair_volume.c
index 5111eac3a48..c129f029873 100644
--- a/source/blender/physics/intern/hair_volume.c
+++ b/source/blender/physics/intern/hair_volume.c
@@ -29,10 +29,12 @@
* \ingroup bph
*/
+#include "MEM_guardedalloc.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#if 0 // XXX TODO
+#include "implicit.h"
/* ================ Volumetric Hair Interaction ================
* adapted from
@@ -52,6 +54,9 @@
* for bigger grids.
*/
+
+static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+
/* 10x10x10 grid gives nice initial results */
static const int hair_grid_res = 10;
@@ -71,6 +76,20 @@ typedef struct HairGridVert {
float density;
} HairGridVert;
+typedef struct HairVertexGrid {
+ HairGridVert *verts;
+ int res;
+ float gmin[3], gmax[3];
+ float scale[3];
+} HairVertexGrid;
+
+typedef struct HairColliderGrid {
+ HairGridVert *verts;
+ int res;
+ float gmin[3], gmax[3];
+ float scale[3];
+} HairColliderGrid;
+
#define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) ( min_ii( max_ii( (int)((vec[axis] - gmin[axis]) / scale[axis]), 0), res-2 ) )
BLI_INLINE int hair_grid_offset(const float vec[3], int res, const float gmin[3], const float scale[3])
@@ -99,7 +118,7 @@ BLI_INLINE int hair_grid_interp_weights(int res, const float gmin[3], const floa
}
BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const float gmin[3], const float scale[3], const float vec[3],
- float *density, float velocity[3], float density_gradient[3])
+ float *density, float velocity[3], float density_gradient[3], float velocity_gradient[3][3])
{
HairGridVert data[8];
float uvw[3], muvw[3];
@@ -126,6 +145,7 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const f
uvw[2]*( muvw[1]*( muvw[0]*data[4].density + uvw[0]*data[5].density ) +
uvw[1]*( muvw[0]*data[6].density + uvw[0]*data[7].density ) );
}
+
if (velocity) {
int k;
for (k = 0; k < 3; ++k) {
@@ -135,6 +155,7 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const f
uvw[1]*( muvw[0]*data[6].velocity[k] + uvw[0]*data[7].velocity[k] ) );
}
}
+
if (density_gradient) {
density_gradient[0] = muvw[1] * muvw[2] * ( data[0].density - data[1].density ) +
uvw[1] * muvw[2] * ( data[2].density - data[3].density ) +
@@ -151,23 +172,14 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const f
muvw[2] * uvw[0] * ( data[2].density - data[6].density ) +
uvw[2] * uvw[0] * ( data[3].density - data[7].density );
}
-}
-
-static void hair_velocity_smoothing(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float smoothfac,
- lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
-{
- int v;
- /* calculate forces */
- for (v = 0; v < numverts; v++) {
- float density, velocity[3];
-
- hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, velocity, NULL);
-
- sub_v3_v3(velocity, lV[v]);
- madd_v3_v3fl(lF[v], velocity, smoothfac);
+
+ if (velocity_gradient) {
+ /* XXX TODO */
+ zero_m3(velocity_gradient);
}
}
+#if 0
static void hair_velocity_collision(const HairGridVert *collgrid, const float gmin[3], const float scale[3], float collfac,
lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
{
@@ -183,34 +195,30 @@ static void hair_velocity_collision(const HairGridVert *collgrid, const float gm
}
}
}
+#endif
-static void hair_pressure_force(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float pressurefac, float minpressure,
- lfVector *lF, lfVector *lX, unsigned int numverts)
+void BPH_hair_volume_vertex_grid_forces(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])
{
- int v;
+ float gdensity, gvelocity[3], ggrad[3], gvelgrad[3][3], gradlen;
- /* calculate forces */
- for (v = 0; v < numverts; v++) {
- float density, gradient[3], gradlen;
-
- hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, NULL, gradient);
-
- gradlen = normalize_v3(gradient) - minpressure;
- if (gradlen < 0.0f)
- continue;
- mul_v3_fl(gradient, gradlen);
-
- madd_v3_v3fl(lF[v], gradient, pressurefac);
+ hair_grid_interpolate(grid->verts, grid->res, grid->gmin, grid->scale, x, &gdensity, gvelocity, ggrad, gvelgrad);
+
+ zero_v3(f);
+ sub_v3_v3(gvelocity, v);
+ mul_v3_v3fl(f, gvelocity, smoothfac);
+
+ gradlen = normalize_v3(ggrad) - minpressure;
+ if (gradlen > 0.0f) {
+ mul_v3_fl(ggrad, gradlen);
+ madd_v3_v3fl(f, ggrad, pressurefac);
}
-}
-
-static void hair_volume_get_boundbox(lfVector *lX, unsigned int numverts, float gmin[3], float gmax[3])
-{
- int i;
- INIT_MINMAX(gmin, gmax);
- for (i = 0; i < numverts; i++)
- DO_MINMAX(lX[i], gmin, gmax);
+ zero_m3(dfdx);
+
+ sub_m3_m3m3(dfdv, gvelgrad, I);
+ mul_m3_fl(dfdv, smoothfac);
}
BLI_INLINE bool hair_grid_point_valid(const float vec[3], float gmin[3], float gmax[3])
@@ -252,66 +260,75 @@ static int hair_grid_weights(int res, const float gmin[3], const float scale[3],
return offset;
}
-static HairGridVert *hair_volume_create_hair_grid(ClothModifierData *clmd, lfVector *lX, lfVector *lV, unsigned int numverts)
+void BPH_hair_volume_add_vertex(HairVertexGrid *grid, const float x[3], const float v[3])
{
- int res = hair_grid_res;
- int size = hair_grid_size(res);
- HairGridVert *hairgrid;
- float gmin[3], gmax[3], scale[3];
- /* 2.0f is an experimental value that seems to give good results */
- float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
- unsigned int v = 0;
- int i = 0;
-
- hair_volume_get_boundbox(lX, numverts, gmin, gmax);
- hair_grid_get_scale(res, gmin, gmax, scale);
-
- hairgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair voxel data");
-
- /* initialize grid */
- for (i = 0; i < size; ++i) {
- zero_v3(hairgrid[i].velocity);
- hairgrid[i].density = 0.0f;
- }
-
- /* gather velocities & density */
- if (smoothfac > 0.0f) {
- for (v = 0; v < numverts; v++) {
- float *V = lV[v];
- float weights[8];
- int di, dj, dk;
- int offset;
-
- if (!hair_grid_point_valid(lX[v], gmin, gmax))
- continue;
-
- offset = hair_grid_weights(res, gmin, scale, lX[v], weights);
-
- for (di = 0; di < 2; ++di) {
- for (dj = 0; dj < 2; ++dj) {
- for (dk = 0; dk < 2; ++dk) {
- int voffset = offset + di + (dj + dk*res)*res;
- int iw = di + dj*2 + dk*4;
-
- hairgrid[voffset].density += weights[iw];
- madd_v3_v3fl(hairgrid[voffset].velocity, V, weights[iw]);
- }
- }
+ int res = grid->res;
+ float weights[8];
+ int di, dj, dk;
+ int offset;
+
+ if (!hair_grid_point_valid(x, grid->gmin, grid->gmax))
+ return;
+
+ offset = hair_grid_weights(res, grid->gmin, grid->scale, x, weights);
+
+ for (di = 0; di < 2; ++di) {
+ for (dj = 0; dj < 2; ++dj) {
+ for (dk = 0; dk < 2; ++dk) {
+ int voffset = offset + di + (dj + dk*res)*res;
+ int iw = di + dj*2 + dk*4;
+
+ grid->verts[voffset].density += weights[iw];
+ madd_v3_v3fl(grid->verts[voffset].velocity, v, weights[iw]);
}
}
}
+}
+void BPH_hair_volume_normalize_vertex_grid(HairVertexGrid *grid)
+{
+ int i, size = hair_grid_size(grid->res);
/* divide velocity with density */
for (i = 0; i < size; i++) {
- float density = hairgrid[i].density;
+ float density = grid->verts[i].density;
if (density > 0.0f)
- mul_v3_fl(hairgrid[i].velocity, 1.0f/density);
+ mul_v3_fl(grid->verts[i].velocity, 1.0f/density);
+ }
+}
+
+HairVertexGrid *BPH_hair_volume_create_vertex_grid(const float gmin[3], const float gmax[3])
+{
+ int res = hair_grid_res;
+ int size = hair_grid_size(res);
+ HairVertexGrid *grid;
+ int i = 0;
+
+ grid = MEM_callocN(sizeof(HairVertexGrid), "hair vertex grid");
+ grid->res = res;
+ copy_v3_v3(grid->gmin, gmin);
+ copy_v3_v3(grid->gmax, gmax);
+ hair_grid_get_scale(res, gmin, gmax, grid->scale);
+ grid->verts = MEM_mallocN(sizeof(HairGridVert) * size, "hair voxel data");
+
+ /* initialize grid */
+ for (i = 0; i < size; ++i) {
+ zero_v3(grid->verts[i].velocity);
+ grid->verts[i].density = 0.0f;
}
- return hairgrid;
+ return grid;
}
+void BPH_hair_volume_free_vertex_grid(HairVertexGrid *grid)
+{
+ if (grid) {
+ if (grid->verts)
+ MEM_freeN(grid->verts);
+ MEM_freeN(grid);
+ }
+}
+#if 0
static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd, lfVector *lX, unsigned int numverts)
{
int res = hair_grid_res;
@@ -381,33 +398,7 @@ static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd,
return collgrid;
}
-
-static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
-{
- HairGridVert *hairgrid, *collgrid;
- float gmin[3], gmax[3], scale[3];
- /* 2.0f is an experimental value that seems to give good results */
- float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
- float collfac = 2.0f * clmd->sim_parms->collider_friction;
- float pressfac = clmd->sim_parms->pressure;
- float minpress = clmd->sim_parms->pressure_threshold;
-
- if (smoothfac <= 0.0f && collfac <= 0.0f && pressfac <= 0.0f)
- return;
-
- hair_volume_get_boundbox(lX, numverts, gmin, gmax);
- hair_grid_get_scale(hair_grid_res, gmin, gmax, scale);
-
- hairgrid = hair_volume_create_hair_grid(clmd, lX, lV, numverts);
- collgrid = hair_volume_create_collision_grid(clmd, lX, numverts);
-
- hair_velocity_smoothing(hairgrid, gmin, scale, smoothfac, lF, lX, lV, numverts);
- hair_velocity_collision(collgrid, gmin, scale, collfac, lF, lX, lV, numverts);
- hair_pressure_force(hairgrid, gmin, scale, pressfac, minpress, lF, lX, numverts);
-
- MEM_freeN(hairgrid);
- MEM_freeN(collgrid);
-}
+#endif
#if 0
bool implicit_hair_volume_get_texture_data(Object *UNUSED(ob), ClothModifierData *clmd, ListBase *UNUSED(effectors), VoxelData *vd)
@@ -478,6 +469,5 @@ bool implicit_hair_volume_get_texture_data(Object *UNUSED(ob), ClothModifierData
return true;
}
-#endif
#endif
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index 25771740def..66ee92f950e 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -126,6 +126,8 @@ void BPH_mass_spring_force_reference_frame(struct Implicit_Data *data, int index
void BPH_mass_spring_force_gravity(struct Implicit_Data *data, const float g[3]);
/* Global drag force (velocity damping) */
void BPH_mass_spring_force_drag(struct Implicit_Data *data, float drag);
+/* Custom external force */
+void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3]);
/* Wind force, acting on a face */
void BPH_mass_spring_force_face_wind(struct Implicit_Data *data, int v1, int v2, int v3, int v4, const float (*winvec)[3]);
/* Wind force, acting on an edge */
@@ -143,6 +145,20 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, int sp
float stiffness, float damping,
float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+/* ======== Hair Volumetric Forces ======== */
+
+struct HairVertexGrid;
+struct HairColliderGrid;
+
+struct HairVertexGrid *BPH_hair_volume_create_vertex_grid(const float gmin[3], const float gmax[3]);
+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_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]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 0c02e648661..60237a76dc6 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -764,6 +764,21 @@ BLI_INLINE void direction_root_to_world(Implicit_Data *data, int index, float r[
mul_v3_m3v3(r, root->rot, v);
}
+BLI_INLINE void matrix_world_to_root(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ RootTransform *root = &data->root[index];
+ float trot[3][3];
+ copy_m3_m3(trot, root->rot);
+ transpose_m3(trot);
+ mul_m3_m3m3(r, trot, m);
+}
+
+BLI_INLINE void matrix_root_to_world(Implicit_Data *data, int index, float r[3][3], float m[3][3])
+{
+ RootTransform *root = &data->root[index];
+ mul_m3_m3m3(r, root->rot, m);
+}
+
/* ================================ */
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
@@ -1367,6 +1382,18 @@ void BPH_mass_spring_force_drag(Implicit_Data *data, float drag)
}
}
+void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3])
+{
+ float tf[3], tdfdx[3][3], tdfdv[3][3];
+ direction_world_to_root(data, i, tf, f);
+ matrix_world_to_root(data, i, tdfdx, dfdx);
+ matrix_world_to_root(data, i, tdfdv, dfdv);
+
+ add_v3_v3(data->F[i], tf);
+ add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, tdfdx);
+ add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, tdfdv);
+}
+
static float calc_nor_area_tri(float nor[3], const float v1[3], const float v2[3], const float v3[3])
{
float n1[3], n2[3];