Radical simplification of the wind effect on hair, since the previous
approach does not work very well. Using a cross section estimate still causes large oscillations due to varying hair force based on angles. It also requires a sensible hair thickness value (particle radius) which is difficult to control and visualize at this point. The new model is based purely on per-vertex forces, which seems to be much more stable. It's also somewhat justified by the fact that each hair vertex represents a certain mass. Conflicts: source/blender/physics/intern/BPH_mass_spring.cpp
This commit is contained in:
@@ -497,6 +497,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
|
|||||||
|
|
||||||
/* Hair has only edges */
|
/* Hair has only edges */
|
||||||
if (cloth->numfaces == 0) {
|
if (cloth->numfaces == 0) {
|
||||||
|
#if 0
|
||||||
ClothHairData *hairdata = clmd->hairdata;
|
ClothHairData *hairdata = clmd->hairdata;
|
||||||
ClothHairData *hair_ij, *hair_kl;
|
ClothHairData *hair_ij, *hair_kl;
|
||||||
|
|
||||||
@@ -508,6 +509,16 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
|
|||||||
BPH_mass_spring_force_edge_wind(data, spring->ij, spring->kl, hair_ij->radius, hair_kl->radius, winvec);
|
BPH_mass_spring_force_edge_wind(data, spring->ij, spring->kl, hair_ij->radius, hair_kl->radius, winvec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ClothHairData *hairdata = clmd->hairdata;
|
||||||
|
|
||||||
|
vert = cloth->verts;
|
||||||
|
for (i = 0; i < cloth->numverts; i++, vert++) {
|
||||||
|
ClothHairData *hair = &hairdata[i];
|
||||||
|
|
||||||
|
BPH_mass_spring_force_vertex_wind(data, i, hair->radius, winvec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
MEM_freeN(winvec);
|
MEM_freeN(winvec);
|
||||||
}
|
}
|
||||||
|
@@ -112,6 +112,8 @@ void BPH_mass_spring_force_extern(struct Implicit_Data *data, int i, const float
|
|||||||
void BPH_mass_spring_force_face_wind(struct Implicit_Data *data, int v1, int v2, int v3, int v4, const float (*winvec)[3]);
|
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 */
|
/* Wind force, acting on an edge */
|
||||||
void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, float radius1, float radius2, const float (*winvec)[3]);
|
void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, float radius1, float radius2, const float (*winvec)[3]);
|
||||||
|
/* Wind force, acting on a vertex */
|
||||||
|
void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
|
||||||
/* Linear spring force between two points */
|
/* Linear spring force between two points */
|
||||||
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
|
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
|
||||||
float stiffness, float damping, bool no_compress, float clamp_force,
|
float stiffness, float damping, bool no_compress, float clamp_force,
|
||||||
|
@@ -1493,11 +1493,22 @@ void BPH_mass_spring_force_edge_wind(Implicit_Data *data, int v1, int v2, float
|
|||||||
add_v3_v3(data->F[v1], f);
|
add_v3_v3(data->F[v1], f);
|
||||||
|
|
||||||
world_to_root_v3(data, v2, win, winvec[v2]);
|
world_to_root_v3(data, v2, win, winvec[v2]);
|
||||||
/* use -length to invert edge direction */
|
|
||||||
edge_wind_vertex(dir, length, radius2, win, f, dfdx, dfdv);
|
edge_wind_vertex(dir, length, radius2, win, f, dfdx, dfdv);
|
||||||
add_v3_v3(data->F[v2], f);
|
add_v3_v3(data->F[v2], f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BPH_mass_spring_force_vertex_wind(Implicit_Data *data, int v, float UNUSED(radius), const float (*winvec)[3])
|
||||||
|
{
|
||||||
|
const float density = 0.01f; /* XXX arbitrary value, corresponds to effect of air density */
|
||||||
|
|
||||||
|
float wind[3];
|
||||||
|
float f[3];
|
||||||
|
|
||||||
|
world_to_root_v3(data, v, wind, winvec[v]);
|
||||||
|
mul_v3_v3fl(f, wind, density);
|
||||||
|
add_v3_v3(data->F[v], f);
|
||||||
|
}
|
||||||
|
|
||||||
BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
|
BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
|
||||||
{
|
{
|
||||||
// dir is unit length direction, rest is spring's restlength, k is spring constant.
|
// dir is unit length direction, rest is spring's restlength, k is spring constant.
|
||||||
|
Reference in New Issue
Block a user