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:
Diffstat (limited to 'source/blender/physics/intern/BPH_mass_spring.cpp')
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp334
1 files changed, 167 insertions, 167 deletions
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index e5724c97bbc..c8932045c52 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -60,7 +60,7 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
{
LinkNode *link;
int nondiag = 0;
-
+
for (link = cloth->springs; link; link = link->next) {
ClothSpring *spring = (ClothSpring *)link->link;
switch (spring->type) {
@@ -68,14 +68,14 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
/* angular bending combines 3 vertices */
nondiag += 3;
break;
-
+
default:
/* all other springs depend on 2 vertices only */
nondiag += 1;
break;
}
}
-
+
return nondiag;
}
@@ -86,25 +86,25 @@ int BPH_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
const float ZERO[3] = {0.0f, 0.0f, 0.0f};
Implicit_Data *id;
unsigned int i, nondiag;
-
+
nondiag = cloth_count_nondiag_blocks(cloth);
cloth->implicit = id = BPH_mass_spring_solver_create(cloth->mvert_num, nondiag);
-
+
for (i = 0; i < cloth->mvert_num; i++) {
BPH_mass_spring_set_vertex_mass(id, i, verts[i].mass);
}
-
+
for (i = 0; i < cloth->mvert_num; i++) {
BPH_mass_spring_set_motion_state(id, i, verts[i].x, ZERO);
}
-
+
return 1;
}
void BPH_cloth_solver_free(ClothModifierData *clmd)
{
Cloth *cloth = clmd->clothObject;
-
+
if (cloth->implicit) {
BPH_mass_spring_solver_free(cloth->implicit);
cloth->implicit = NULL;
@@ -118,7 +118,7 @@ void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
unsigned int mvert_num = cloth->mvert_num, i;
ClothHairData *cloth_hairdata = clmd->hairdata;
Implicit_Data *id = cloth->implicit;
-
+
for (i = 0; i < mvert_num; i++) {
if (cloth_hairdata) {
ClothHairData *root = &cloth_hairdata[i];
@@ -126,7 +126,7 @@ void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
}
else
BPH_mass_spring_set_rest_transform(id, i, I3);
-
+
BPH_mass_spring_set_motion_state(id, i, verts[i].x, verts[i].v);
}
}
@@ -136,22 +136,22 @@ static bool collision_response(ClothModifierData *clmd, CollisionModifierData *c
Cloth *cloth = clmd->clothObject;
int index = collpair->ap1;
bool result = false;
-
+
float v1[3], v2_old[3], v2_new[3], v_rel_old[3], v_rel_new[3];
float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
float margin_distance = (float)collpair->distance - epsilon2;
float mag_v_rel;
-
+
zero_v3(r_impulse);
-
+
if (margin_distance > 0.0f)
return false; /* XXX tested before already? */
-
+
/* only handle static collisions here */
if ( collpair->flag & COLLISION_IN_FUTURE )
return false;
-
+
/* velocity */
copy_v3_v3(v1, cloth->verts[index].v);
collision_get_collider_velocity(v2_old, v2_new, collmd, collpair);
@@ -160,32 +160,32 @@ static bool collision_response(ClothModifierData *clmd, CollisionModifierData *c
sub_v3_v3v3(v_rel_new, v1, v2_new);
/* normal component of the relative velocity */
mag_v_rel = dot_v3v3(v_rel_old, collpair->normal);
-
+
/* only valid when moving toward the collider */
if (mag_v_rel < -ALMOST_ZERO) {
float v_nor_old, v_nor_new;
float v_tan_old[3], v_tan_new[3];
float bounce, repulse;
-
+
/* Collision response based on
* "Simulating Complex Hair with Robust Collision Handling" (Choe, Choi, Ko, ACM SIGGRAPH 2005)
* http://graphics.snu.ac.kr/publications/2005-choe-HairSim/Choe_2005_SCA.pdf
*/
-
+
v_nor_old = mag_v_rel;
v_nor_new = dot_v3v3(v_rel_new, collpair->normal);
-
+
madd_v3_v3v3fl(v_tan_old, v_rel_old, collpair->normal, -v_nor_old);
madd_v3_v3v3fl(v_tan_new, v_rel_new, collpair->normal, -v_nor_new);
-
+
bounce = -v_nor_old * restitution;
-
+
repulse = -margin_distance / dt; /* base repulsion velocity in normal direction */
/* XXX this clamping factor is quite arbitrary ...
* not sure if there is a more scientific approach, but seems to give good results
*/
CLAMP(repulse, 0.0f, 4.0f * bounce);
-
+
if (margin_distance < -epsilon2) {
mul_v3_v3fl(r_impulse, collpair->normal, max_ff(repulse, bounce) - v_nor_new);
}
@@ -193,10 +193,10 @@ static bool collision_response(ClothModifierData *clmd, CollisionModifierData *c
bounce = 0.0f;
mul_v3_v3fl(r_impulse, collpair->normal, repulse - v_nor_new);
}
-
+
result = true;
}
-
+
return result;
}
@@ -211,17 +211,17 @@ static void cloth_setup_constraints(ClothModifierData *clmd, ColliderContacts *c
ClothVertex *verts = cloth->verts;
int mvert_num = cloth->mvert_num;
int i, j, v;
-
+
const float ZERO[3] = {0.0f, 0.0f, 0.0f};
-
+
BPH_mass_spring_clear_constraints(data);
-
+
for (v = 0; v < mvert_num; v++) {
if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) {
/* pinned vertex constraints */
BPH_mass_spring_add_constraint_ndof0(data, v, ZERO); /* velocity is defined externally */
}
-
+
verts[v].impulse_count = 0;
}
@@ -233,21 +233,21 @@ static void cloth_setup_constraints(ClothModifierData *clmd, ColliderContacts *c
float restitution = 0.0f;
int v = collpair->face1;
float impulse[3];
-
+
/* pinned verts handled separately */
if (verts[v].flags & CLOTH_VERT_FLAG_PINNED)
continue;
-
+
/* XXX cheap way of avoiding instability from multiple collisions in the same step
* this should eventually be supported ...
*/
if (verts[v].impulse_count > 0)
continue;
-
+
/* calculate collision response */
if (!collision_response(clmd, ct->collmd, collpair, dt, restitution, impulse))
continue;
-
+
BPH_mass_spring_add_constraint_ndof2(data, v, collpair->normal, impulse);
++verts[v].impulse_count;
}
@@ -267,11 +267,11 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
ClothSpring *spring;
ClothVertex *cv;
int i, steps;
-
+
cv = cloth->verts;
for (i = 0; i < cloth->mvert_num; i++, cv++) {
copy_v3_v3(cos[i], cv->tx);
-
+
if (cv->goal == 1.0f || len_squared_v3v3(initial_cos[i], cv->tx) != 0.0f) {
masses[i] = 1e+10;
}
@@ -279,57 +279,57 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
masses[i] = cv->mass;
}
}
-
+
steps = 55;
for (i=0; i<steps; i++) {
for (node=cloth->springs; node; node=node->next) {
/* ClothVertex *cv1, *cv2; */ /* UNUSED */
int v1, v2;
float len, c, l, vec[3];
-
+
spring = (ClothSpring *)node->link;
- if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR)
+ if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR)
continue;
-
+
v1 = spring->ij; v2 = spring->kl;
/* cv1 = cloth->verts + v1; */ /* UNUSED */
/* cv2 = cloth->verts + v2; */ /* UNUSED */
len = len_v3v3(cos[v1], cos[v2]);
-
+
sub_v3_v3v3(vec, cos[v1], cos[v2]);
normalize_v3(vec);
-
+
c = (len - spring->restlen);
if (c == 0.0f)
continue;
-
+
l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2]));
-
+
mul_v3_fl(vec, -(1.0f / masses[v1]) * l);
add_v3_v3(cos[v1], vec);
-
+
sub_v3_v3v3(vec, cos[v2], cos[v1]);
normalize_v3(vec);
-
+
mul_v3_fl(vec, -(1.0f / masses[v2]) * l);
add_v3_v3(cos[v2], vec);
}
}
-
+
cv = cloth->verts;
for (i = 0; i < cloth->mvert_num; i++, cv++) {
float vec[3];
-
+
/*compute forces*/
sub_v3_v3v3(vec, cos[i], cv->tx);
mul_v3_fl(vec, cv->mass*dt*20.0f);
add_v3_v3(cv->tv, vec);
//copy_v3_v3(cv->tx, cos[i]);
}
-
+
MEM_freeN(cos);
MEM_freeN(masses);
-
+
return 1;
}
@@ -338,21 +338,21 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
Cloth *cloth = clmd->clothObject;
ClothSimSettings *parms = clmd->sim_parms;
Implicit_Data *data = cloth->implicit;
-
+
bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
-
+
s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
-
+
// calculate force of structural + shear springs
if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) {
#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
float k, scaling;
-
+
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
+
scaling = parms->structural + s->stiffness * fabsf(parms->max_struct - parms->structural);
k = scaling / (parms->avg_spring_len + FLT_EPSILON);
-
+
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
// TODO: verify, half verified (couldn't see error)
// sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
@@ -366,50 +366,50 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
#ifdef CLOTH_FORCE_SPRING_BEND
float kb, cb, scaling;
-
+
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
+
scaling = parms->bending + s->stiffness * fabsf(parms->max_bend - parms->bending);
kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
-
+
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
cb = kb * parms->bending_damping;
-
+
BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb);
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) {
#ifdef CLOTH_FORCE_SPRING_BEND
float kb, cb, scaling;
-
+
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
+
/* XXX WARNING: angular bending springs for hair apply stiffness factor as an overall factor, unlike cloth springs!
* this is crap, but needed due to cloth/hair mixing ...
* max_bend factor is not even used for hair, so ...
*/
scaling = s->stiffness * parms->bending;
kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
-
+
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
cb = kb * parms->bending_damping;
-
+
/* XXX assuming same restlen for ij and jk segments here, this can be done correctly for hair later */
BPH_mass_spring_force_spring_bending_angular(data, s->ij, s->kl, s->mn, s->target, kb, cb);
-
+
#if 0
{
float x_kl[3], x_mn[3], v[3], d[3];
-
+
BPH_mass_spring_get_motion_state(data, s->kl, x_kl, v);
BPH_mass_spring_get_motion_state(data, s->mn, x_mn, v);
-
+
BKE_sim_debug_data_add_dot(clmd->debug_data, x_kl, 0.9, 0.9, 0.9, "target", 7980, s->kl);
BKE_sim_debug_data_add_line(clmd->debug_data, x_kl, x_mn, 0.8, 0.8, 0.8, "target", 7981, s->kl);
-
+
copy_v3_v3(d, s->target);
BKE_sim_debug_data_add_vector(clmd->debug_data, x_kl, d, 0.8, 0.8, 0.2, "target", 7982, s->kl);
-
+
// copy_v3_v3(d, s->target_ij);
// BKE_sim_debug_data_add_vector(clmd->debug_data, x, d, 1, 0.4, 0.4, "target", 7983, s->kl);
}
@@ -424,7 +424,7 @@ static void hair_get_boundbox(ClothModifierData *clmd, float gmin[3], float gmax
Implicit_Data *data = cloth->implicit;
unsigned int mvert_num = cloth->mvert_num;
int i;
-
+
INIT_MINMAX(gmin, gmax);
for (i = 0; i < mvert_num; i++) {
float x[3];
@@ -444,7 +444,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
const MVertTri *tri = cloth->tri;
unsigned int mvert_num = cloth->mvert_num;
ClothVertex *vert;
-
+
#ifdef CLOTH_FORCE_GRAVITY
/* global acceleration (gravitation) */
if (clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
@@ -477,7 +477,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
#ifdef CLOTH_FORCE_DRAG
BPH_mass_spring_force_drag(data, drag);
#endif
-
+
/* handle external forces like wind */
if (effectors) {
/* cache per-vertex forces to avoid redundant calculation */
@@ -485,12 +485,12 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
for (i = 0; i < cloth->mvert_num; i++) {
float x[3], v[3];
EffectedPoint epoint;
-
+
BPH_mass_spring_get_motion_state(data, i, x, v);
pd_point_from_loc(clmd->scene, x, v, i, &epoint);
pdDoEffectors(effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL);
}
-
+
for (i = 0; i < cloth->tri_num; i++) {
const MVertTri *vt = &tri[i];
BPH_mass_spring_force_face_wind(data, vt->tri[0], vt->tri[1], vt->tri[2], winvec);
@@ -501,7 +501,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
#if 0
ClothHairData *hairdata = clmd->hairdata;
ClothHairData *hair_ij, *hair_kl;
-
+
for (LinkNode *link = cloth->springs; link; link = link->next) {
ClothSpring *spring = (ClothSpring *)link->link;
if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
@@ -516,7 +516,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
}
#else
ClothHairData *hairdata = clmd->hairdata;
-
+
vert = cloth->verts;
for (i = 0; i < cloth->mvert_num; i++, vert++) {
if (hairdata) {
@@ -531,7 +531,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
MEM_freeN(winvec);
}
-
+
// calculate spring forces
for (LinkNode *link = cloth->springs; link; link = link->next) {
ClothSpring *spring = (ClothSpring *)link->link;
@@ -548,7 +548,7 @@ BLI_INLINE void cloth_get_grid_location(Implicit_Data *data, float cell_scale, c
{
BPH_mass_spring_get_position(data, index, x);
BPH_mass_spring_get_new_velocity(data, index, v);
-
+
mul_v3_fl(x, cell_scale);
add_v3_v3(x, cell_offset);
}
@@ -582,41 +582,41 @@ static LinkNode *cloth_continuum_add_hair_segments(HairGrid *grid, const float c
// ClothVertex *vert3, *vert4;
float x1[3], v1[3], x2[3], v2[3], x3[3], v3[3], x4[3], v4[3];
float dir1[3], dir2[3], dir3[3];
-
+
spring1 = NULL;
spring2 = NULL;
spring3 = (ClothSpring *)spring_link->link;
-
+
zero_v3(x1); zero_v3(v1);
zero_v3(dir1);
zero_v3(x2); zero_v3(v2);
zero_v3(dir2);
-
+
// vert3 = &verts[spring3->kl];
cloth_get_grid_location(data, cell_scale, cell_offset, spring3->kl, x3, v3);
// vert4 = &verts[spring3->ij];
cloth_get_grid_location(data, cell_scale, cell_offset, spring3->ij, x4, v4);
sub_v3_v3v3(dir3, x4, x3);
normalize_v3(dir3);
-
+
while (spring_link) {
/* move on */
spring1 = spring2;
spring2 = spring3;
-
+
// vert3 = vert4;
-
+
copy_v3_v3(x1, x2); copy_v3_v3(v1, v2);
copy_v3_v3(x2, x3); copy_v3_v3(v2, v3);
copy_v3_v3(x3, x4); copy_v3_v3(v3, v4);
-
+
copy_v3_v3(dir1, dir2);
copy_v3_v3(dir2, dir3);
-
+
/* read next segment */
next_spring_link = spring_link->next;
spring_link = hair_spring_next(spring_link);
-
+
if (spring_link) {
spring3 = (ClothSpring *)spring_link->link;
// vert4 = &verts[spring3->ij];
@@ -630,13 +630,13 @@ static LinkNode *cloth_continuum_add_hair_segments(HairGrid *grid, const float c
zero_v3(x4); zero_v3(v4);
zero_v3(dir3);
}
-
+
BPH_hair_volume_add_segment(grid, x1, v1, x2, v2, x3, v3, x4, v4,
spring1 ? dir1 : NULL,
dir2,
spring3 ? dir3 : NULL);
}
-
+
return next_spring_link;
}
@@ -647,17 +647,17 @@ static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
int mvert_num = cloth->mvert_num;
ClothVertex *vert;
int i;
-
+
for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
float x[3], v[3];
-
+
cloth_get_vertex_motion_state(data, vert, x, v);
BPH_hair_volume_add_vertex(grid, x, v);
}
#else
LinkNode *link;
float cellsize, gmin[3], cell_scale, cell_offset[3];
-
+
/* scale and offset for transforming vertex locations into grid space
* (cell size is 0..1, gmin becomes origin)
*/
@@ -665,7 +665,7 @@ static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
cell_scale = cellsize > 0.0f ? 1.0f / cellsize : 0.0f;
mul_v3_v3fl(cell_offset, gmin, cell_scale);
negate_v3(cell_offset);
-
+
link = cloth->springs;
while (link) {
ClothSpring *spring = (ClothSpring *)link->link;
@@ -685,7 +685,7 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
Implicit_Data *data = cloth->implicit;
int mvert_num = cloth->mvert_num;
ClothVertex *vert;
-
+
const float fluid_factor = 0.95f; /* blend between PIC and FLIP methods */
float smoothfac = parms->velocity_smooth;
/* XXX FIXME arbitrary factor!!! this should be based on some intuitive value instead,
@@ -695,42 +695,42 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
float density_strength = parms->density_strength;
float gmin[3], gmax[3];
int i;
-
+
/* clear grid info */
zero_v3_int(clmd->hair_grid_res);
zero_v3(clmd->hair_grid_min);
zero_v3(clmd->hair_grid_max);
clmd->hair_grid_cellsize = 0.0f;
-
+
hair_get_boundbox(clmd, gmin, gmax);
-
+
/* gather velocities & density */
if (smoothfac > 0.0f || density_strength > 0.0f) {
HairGrid *grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
-
+
cloth_continuum_fill_grid(grid, cloth);
-
+
/* main hair continuum solver */
BPH_hair_volume_solve_divergence(grid, dt, density_target, density_strength);
-
+
for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
float x[3], v[3], nv[3];
-
+
/* calculate volumetric velocity influence */
BPH_mass_spring_get_position(data, i, x);
BPH_mass_spring_get_new_velocity(data, i, v);
-
+
BPH_hair_volume_grid_velocity(grid, x, v, fluid_factor, nv);
-
+
interp_v3_v3v3(nv, v, nv, smoothfac);
-
+
/* apply on hair data */
BPH_mass_spring_set_new_velocity(data, i, nv);
}
-
+
/* store basic grid info in the modifier data */
BPH_hair_volume_grid_geometry(grid, &clmd->hair_grid_cellsize, clmd->hair_grid_res, clmd->hair_grid_min, clmd->hair_grid_max);
-
+
#if 0 /* DEBUG hair velocity vector field */
{
const int size = 64;
@@ -738,26 +738,26 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
float offset[3], a[3], b[3];
const int axis = 0;
const float shift = 0.0f;
-
+
copy_v3_v3(offset, clmd->hair_grid_min);
zero_v3(a);
zero_v3(b);
-
+
offset[axis] = shift * clmd->hair_grid_cellsize;
a[(axis+1) % 3] = clmd->hair_grid_max[(axis+1) % 3] - clmd->hair_grid_min[(axis+1) % 3];
b[(axis+2) % 3] = clmd->hair_grid_max[(axis+2) % 3] - clmd->hair_grid_min[(axis+2) % 3];
-
+
BKE_sim_debug_data_clear_category(clmd->debug_data, "grid velocity");
for (j = 0; j < size; ++j) {
for (i = 0; i < size; ++i) {
float x[3], v[3], gvel[3], gvel_smooth[3], gdensity;
-
+
madd_v3_v3v3fl(x, offset, a, (float)i / (float)(size-1));
madd_v3_v3fl(x, b, (float)j / (float)(size-1));
zero_v3(v);
-
+
BPH_hair_volume_grid_interpolate(grid, x, &gdensity, gvel, gvel_smooth, NULL, NULL);
-
+
// BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity, 0.7, 0.3, 1, "grid density", i, j, 3111);
if (!is_zero_v3(gvel) || !is_zero_v3(gvel_smooth)) {
float dvel[3];
@@ -770,7 +770,7 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
float col0[3] = {0.0, 0.0, 0.0};
float col1[3] = {0.0, 1.0, 0.0};
float col[3];
-
+
interp_v3_v3v3(col, col0, col1, CLAMPIS(gdensity * clmd->sim_parms->density_strength, 0.0, 1.0));
// BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity * clmd->sim_parms->density_strength, 0, 1, 0.4, "grid velocity", i, j, 3115);
// BKE_sim_debug_data_add_dot(clmd->debug_data, x, col[0], col[1], col[2], "grid velocity", i, j, 3115);
@@ -782,7 +782,7 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
}
}
#endif
-
+
BPH_hair_volume_free_vertex_grid(grid);
}
}
@@ -795,7 +795,7 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
Implicit_Data *data = cloth->implicit;
int mvert_num = cloth->mvert_num;
ClothVertex *vert;
-
+
/* 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;
@@ -803,17 +803,17 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
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(clmd->sim_parms->voxel_res, gmin, gmax);
-
+
vert = cloth->verts;
for (i = 0; i < mvert_num; i++, vert++) {
float x[3], v[3];
-
+
if (vert->solver_index < 0) {
copy_v3_v3(x, vert->x);
copy_v3_v3(v, vert->v);
@@ -824,21 +824,21 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
BPH_hair_volume_add_vertex(vertex_grid, x, v);
}
BPH_hair_volume_normalize_vertex_grid(vertex_grid);
-
+
vert = cloth->verts;
for (i = 0; i < mvert_num; i++, vert++) {
float x[3], v[3], f[3], dfdx[3][3], dfdv[3][3];
-
+
if (vert->solver_index < 0)
continue;
-
+
/* calculate volumetric forces */
BPH_mass_spring_get_motion_state(data, vert->solver_index, 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, vert->solver_index, f, dfdx, dfdv);
}
-
+
BPH_hair_volume_free_vertex_grid(vertex_grid);
}
}
@@ -854,33 +854,33 @@ static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, Lis
ClothVertex *verts = cloth->verts;
int mvert_num = cloth->mvert_num;
const float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
-
+
bool do_extra_solve;
int i;
-
+
if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED))
return;
if (!clmd->clothObject->bvhtree)
return;
-
+
// update verts to current positions
for (i = 0; i < mvert_num; i++) {
BPH_mass_spring_get_new_position(id, i, verts[i].tx);
-
+
sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
copy_v3_v3(verts[i].v, verts[i].tv);
}
-
+
#if 0 /* unused */
for (i=0, cv=cloth->verts; i<cloth->mvert_num; i++, cv++) {
copy_v3_v3(initial_cos[i], cv->tx);
}
#endif
-
+
// call collision function
// TODO: check if "step" or "step+dt" is correct - dg
do_extra_solve = cloth_bvh_objcollision(ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale);
-
+
// copy corrected positions back to simulation
for (i = 0; i < mvert_num; i++) {
float curx[3];
@@ -888,41 +888,41 @@ static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, Lis
// correct velocity again, just to be sure we had to change it due to adaptive collisions
sub_v3_v3v3(verts[i].tv, verts[i].tx, curx);
}
-
+
if (do_extra_solve) {
// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
-
+
for (i = 0; i < mvert_num; i++) {
-
+
float newv[3];
-
+
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
continue;
-
+
BPH_mass_spring_set_new_position(id, i, verts[i].tx);
mul_v3_v3fl(newv, verts[i].tv, spf);
BPH_mass_spring_set_new_velocity(id, i, newv);
}
}
-
+
// X = Xnew;
BPH_mass_spring_apply_result(id);
-
+
if (do_extra_solve) {
ImplicitSolverResult result;
-
+
/* initialize forces to zero */
BPH_mass_spring_clear_forces(id);
-
+
// calculate forces
cloth_calc_force(clmd, frame, effectors, step);
-
+
// calculate new velocity and position
BPH_mass_spring_solve_velocities(id, dt, &result);
// cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
-
+
/* note: positions are advanced only once in the main solver step! */
-
+
BPH_mass_spring_apply_result(id);
}
}
@@ -930,7 +930,7 @@ static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, Lis
static void cloth_clear_result(ClothModifierData *clmd)
{
ClothSolverResult *sres = clmd->solver_result;
-
+
sres->status = 0;
sres->max_error = sres->min_error = sres->avg_error = 0.0f;
sres->max_iterations = sres->min_iterations = 0;
@@ -940,7 +940,7 @@ static void cloth_clear_result(ClothModifierData *clmd)
static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, int steps)
{
ClothSolverResult *sres = clmd->solver_result;
-
+
if (sres->status) { /* already initialized ? */
/* error only makes sense for successful iterations */
if (result->status == BPH_SOLVER_SUCCESS) {
@@ -948,7 +948,7 @@ static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *r
sres->max_error = max_ff(sres->max_error, result->error);
sres->avg_error += result->error / (float)steps;
}
-
+
sres->min_iterations = min_ii(sres->min_iterations, result->iterations);
sres->max_iterations = max_ii(sres->max_iterations, result->iterations);
sres->avg_iterations += (float)result->iterations / (float)steps;
@@ -959,11 +959,11 @@ static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *r
sres->min_error = sres->max_error = result->error;
sres->avg_error += result->error / (float)steps;
}
-
+
sres->min_iterations = sres->max_iterations = result->iterations;
sres->avg_iterations += (float)result->iterations / (float)steps;
}
-
+
sres->status |= result->status;
}
@@ -974,7 +974,7 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
* Bad design, TODO
*/
const bool is_hair = (clmd->hairdata != NULL);
-
+
unsigned int i=0;
float step=0.0f, tf=clmd->sim_parms->timescale;
Cloth *cloth = clmd->clothObject;
@@ -984,13 +984,13 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
Implicit_Data *id = cloth->implicit;
ColliderContacts *contacts = NULL;
int totcolliders = 0;
-
+
BKE_sim_debug_data_clear_category("collision");
-
+
if (!clmd->solver_result)
clmd->solver_result = (ClothSolverResult *)MEM_callocN(sizeof(ClothSolverResult), "cloth solver result");
cloth_clear_result(clmd);
-
+
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { /* do goal stuff */
for (i = 0; i < mvert_num; i++) {
// update velocities with constrained velocities from pinned verts
@@ -1004,22 +1004,22 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
}
}
}
-
+
while (step < tf) {
ImplicitSolverResult result;
-
+
/* copy velocities for collision */
for (i = 0; i < mvert_num; i++) {
BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv);
copy_v3_v3(verts[i].v, verts[i].tv);
}
-
+
if (is_hair) {
/* determine contact points */
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
cloth_find_point_contacts(ob, clmd, 0.0f, tf, &contacts, &totcolliders);
}
-
+
/* setup vertex constraints for pinned vertices and contacts */
cloth_setup_constraints(clmd, contacts, totcolliders, dt);
}
@@ -1027,10 +1027,10 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
/* setup vertex constraints for pinned vertices */
cloth_setup_constraints(clmd, NULL, 0, dt);
}
-
+
/* initialize forces to zero */
BPH_mass_spring_clear_forces(id);
-
+
// damping velocity for artistic reasons
// this is a bad way to do it, should be removed imo - lukas_t
if (clmd->sim_parms->vel_damping != 1.0f) {
@@ -1041,26 +1041,26 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
BPH_mass_spring_set_velocity(id, i, v);
}
}
-
+
// calculate forces
cloth_calc_force(clmd, frame, effectors, step);
-
+
// calculate new velocity and position
BPH_mass_spring_solve_velocities(id, dt, &result);
cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
-
+
if (is_hair) {
cloth_continuum_step(clmd, dt);
}
-
+
BPH_mass_spring_solve_positions(id, dt);
-
+
if (!is_hair) {
cloth_collision_solve_extra(ob, clmd, effectors, frame, step, dt);
}
-
+
BPH_mass_spring_apply_result(id);
-
+
/* move pinned verts to correct position */
for (i = 0; i < mvert_num; i++) {
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
@@ -1071,23 +1071,23 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
BPH_mass_spring_set_position(id, i, x);
}
}
-
+
BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL);
}
-
+
/* free contact points */
if (contacts) {
cloth_free_contacts(contacts, totcolliders);
}
-
+
step += dt;
}
-
+
/* copy results back to cloth data */
for (i = 0; i < mvert_num; i++) {
BPH_mass_spring_get_motion_state(id, i, verts[i].x, verts[i].v);
copy_v3_v3(verts[i].txold, verts[i].x);
}
-
+
return 1;
}