Merge branch 'hair_immediate_fixes' into gooseberry
Conflicts: source/blender/physics/intern/BPH_mass_spring.cpp
This commit is contained in:
parent
be24adc9ef
commit
046510fcf9
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Reference in New Issue