Merge branch 'hair_immediate_fixes' into gooseberry

Conflicts:
	source/blender/physics/intern/BPH_mass_spring.cpp
This commit is contained in:
Lukas Tönne 2014-11-09 13:11:05 +01:00
parent be24adc9ef
commit 046510fcf9
3 changed files with 342 additions and 75 deletions

View File

@ -472,25 +472,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "int", "voxel_res")) {
Object *ob;
ModifierData *md;
for (ob = main->object.first; ob; ob = ob->id.next) {
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
clmd->sim_parms->voxel_res = 32;
}
else if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *pmd = (ParticleSystemModifierData*) md;
if (pmd->psys->clmd) {
pmd->psys->clmd->sim_parms->voxel_res = 32;
}
}
}
}
}
if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "float", "bending_damping")) {
Object *ob;

View File

@ -527,62 +527,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
}
#if 0
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;
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;
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(clmd->sim_parms->voxel_res, gmin, gmax);
vert = cloth->verts;
for (i = 0; i < numverts; i++, vert++) {
float x[3], v[3];
if (vert->solver_index < 0) {
copy_v3_v3(x, vert->x);
copy_v3_v3(v, vert->v);
}
else {
BPH_mass_spring_get_motion_state(data, vert->solver_index, x, v);
}
BPH_hair_volume_add_vertex(vertex_grid, x, v);
}
BPH_hair_volume_normalize_vertex_grid(vertex_grid);
vert = cloth->verts;
for (i = 0; i < numverts; 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);
}
}
#endif
/* returns active vertexes' motion state, or original location the vertex is disabled */
BLI_INLINE bool cloth_get_grid_location(Implicit_Data *data, float cell_scale, const float cell_offset[3],
ClothVertex *vert, int index, float x[3], float v[3])
@ -836,6 +781,326 @@ static void cloth_continuum_step(ClothModifierData *clmd, float dt)
}
}
#if 0
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;
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;
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(clmd->sim_parms->voxel_res, gmin, gmax);
vert = cloth->verts;
for (i = 0; i < numverts; i++, vert++) {
float x[3], v[3];
if (vert->solver_index < 0) {
copy_v3_v3(x, vert->x);
copy_v3_v3(v, vert->v);
}
else {
BPH_mass_spring_get_motion_state(data, vert->solver_index, x, v);
}
BPH_hair_volume_add_vertex(vertex_grid, x, v);
}
BPH_hair_volume_normalize_vertex_grid(vertex_grid);
vert = cloth->verts;
for (i = 0; i < numverts; 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);
}
}
#endif
/* returns active vertexes' motion state, or original location the vertex is disabled */
BLI_INLINE bool cloth_get_grid_location(Implicit_Data *data, float cell_scale, const float cell_offset[3],
ClothVertex *vert, float x[3], float v[3])
{
bool is_motion_state;
if (vert->solver_index < 0) {
copy_v3_v3(x, vert->x);
copy_v3_v3(v, vert->v);
is_motion_state = false;
}
else {
BPH_mass_spring_get_position(data, vert->solver_index, x);
BPH_mass_spring_get_new_velocity(data, vert->solver_index, v);
is_motion_state = true;
}
mul_v3_fl(x, cell_scale);
add_v3_v3(x, cell_offset);
return is_motion_state;
}
/* returns next spring forming a continous hair sequence */
BLI_INLINE LinkNode *hair_spring_next(LinkNode *spring_link)
{
ClothSpring *spring = (ClothSpring *)spring_link->link;
LinkNode *next = spring_link->next;
if (next) {
ClothSpring *next_spring = (ClothSpring *)next->link;
if (next_spring->type == CLOTH_SPRING_TYPE_STRUCTURAL && next_spring->kl == spring->ij)
return next;
}
return NULL;
}
/* XXX this is nasty: cloth meshes do not explicitly store
* the order of hair segments!
* We have to rely on the spring build function for now,
* which adds structural springs in reverse order:
* (3,4), (2,3), (1,2)
* This is currently the only way to figure out hair geometry inside this code ...
*/
static LinkNode *cloth_continuum_add_hair_segments(HairGrid *grid, const float cell_scale, const float cell_offset[3], Cloth *cloth, LinkNode *spring_link)
{
Implicit_Data *data = cloth->implicit;
LinkNode *next_spring_link = NULL; /* return value */
ClothSpring *spring1, *spring2, *spring3;
ClothVertex *verts = cloth->verts;
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, vert3, x3, v3);
vert4 = &verts[spring3->ij];
cloth_get_grid_location(data, cell_scale, cell_offset, vert4, 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];
cloth_get_grid_location(data, cell_scale, cell_offset, vert4, x4, v4);
sub_v3_v3v3(dir3, x4, x3);
normalize_v3(dir3);
}
else {
spring3 = NULL;
vert4 = NULL;
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);
}
/* last segment */
spring1 = spring2;
spring2 = spring3;
spring3 = NULL;
vert3 = vert4;
vert4 = NULL;
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);
zero_v3(x4); zero_v3(v4);
copy_v3_v3(dir1, dir2);
copy_v3_v3(dir2, dir3);
zero_v3(dir3);
BPH_hair_volume_add_segment(grid, x1, v1, x2, v2, x3, v3, x4, v4,
spring1 ? dir1 : NULL,
dir2,
NULL);
return next_spring_link;
}
static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
{
#if 0
Implicit_Data *data = cloth->implicit;
int numverts = cloth->numverts;
ClothVertex *vert;
int i;
for (i = 0, vert = cloth->verts; i < numverts; 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)
*/
BPH_hair_volume_grid_geometry(grid, &cellsize, NULL, gmin, NULL);
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;
if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL)
link = cloth_continuum_add_hair_segments(grid, cell_scale, cell_offset, cloth, link);
else
link = link->next;
}
#endif
BPH_hair_volume_normalize_vertex_grid(grid);
}
static void cloth_continuum_step(ClothModifierData *clmd, float dt)
{
ClothSimSettings *parms = clmd->sim_parms;
Cloth *cloth = clmd->clothObject;
Implicit_Data *data = cloth->implicit;
int numverts = cloth->numverts;
ClothVertex *vert;
const float fluid_factor = 0.95f; /* blend between PIC and FLIP methods */
float smoothfac = parms->velocity_smooth;
float pressfac = parms->pressure;
float minpress = parms->pressure_threshold;
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);
hair_get_boundbox(clmd, gmin, gmax);
/* gather velocities & density */
if (smoothfac > 0.0f || pressfac > 0.0f) {
HairGrid *grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
BPH_hair_volume_set_debug_data(grid, clmd->debug_data);
cloth_continuum_fill_grid(grid, cloth);
/* main hair continuum solver */
BPH_hair_volume_solve_divergence(grid, dt);
for (i = 0, vert = cloth->verts; i < numverts; i++, vert++) {
float x[3], v[3], nv[3];
if (vert->solver_index < 0)
continue;
/* calculate volumetric velocity influence */
BPH_mass_spring_get_position(data, vert->solver_index, x);
BPH_mass_spring_get_new_velocity(data, vert->solver_index, 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, vert->solver_index, nv);
}
/* store basic grid info in the modifier data */
BPH_hair_volume_grid_geometry(grid, NULL, clmd->hair_grid_res, clmd->hair_grid_min, clmd->hair_grid_max);
#if 0 /* DEBUG hair velocity vector field */
{
const int size = 64;
int i, j;
float offset[3], a[3], b[3];
const int axis = 0;
const float shift = 0.45f;
copy_v3_v3(offset, clmd->hair_grid_min);
zero_v3(a);
zero_v3(b);
offset[axis] = interpf(clmd->hair_grid_max[axis], clmd->hair_grid_min[axis], shift);
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", hash_int_2d(hash_int_2d(i, j), 3111));
if (!is_zero_v3(gvel) || !is_zero_v3(gvel_smooth)) {
BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel, 0.4, 0, 1, "grid velocity", hash_int_2d(hash_int_2d(i, j), 3112));
BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel_smooth, 0.6, 4, 1, "grid velocity", hash_int_2d(hash_int_2d(i, j), 3113));
}
}
}
}
#endif
BPH_hair_volume_free_vertex_grid(grid);
}
}
static void cloth_clear_result(ClothModifierData *clmd)
{
ClothSolverResult *sres = clmd->solver_result;
@ -1019,3 +1284,24 @@ bool BPH_cloth_solver_get_texture_data(Object *UNUSED(ob), ClothModifierData *cl
return true;
}
bool BPH_cloth_solver_get_texture_data(Object *UNUSED(ob), ClothModifierData *clmd, VoxelData *vd)
{
Cloth *cloth = clmd->clothObject;
HairGrid *grid;
float gmin[3], gmax[3];
if (!clmd->clothObject || !clmd->clothObject->implicit)
return false;
hair_get_boundbox(clmd, gmin, gmax);
grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
cloth_continuum_fill_grid(grid, cloth);
BPH_hair_volume_get_texture_data(grid, vd);
BPH_hair_volume_free_vertex_grid(grid);
return true;
}

View File

@ -324,6 +324,7 @@ static void print_sparse_matrix(fmatrix3x3 *m)
}
}
}
#endif
static void print_lvector(lfVector *v, int numverts)
{
@ -380,7 +381,6 @@ static void print_bfmatrix(fmatrix3x3 *m)
MEM_freeN(t);
}
#endif
/* copy 3x3 matrix */
DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3])