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:
authorSebastian Parborg <darkdefende@gmail.com>2019-12-09 21:10:55 +0300
committerSebastian Parborg <darkdefende@gmail.com>2019-12-09 21:18:10 +0300
commit62ef59aa0cca736b09192b67cc924180d9c2f9f9 (patch)
treef0f76383b9536a5186abe0072b1a535e587cef22 /source/blender/blenkernel/intern/cloth.c
parente77fdc62b75a3b96e4c3ca5c2fc4025d8091ff99 (diff)
Add the ability to create internal springs to the cloth sim
This can be used to make closed surfaces behave more like a soft body. Reviewed By: Jacques Lucke Differential Revision: http://developer.blender.org/D5788
Diffstat (limited to 'source/blender/blenkernel/intern/cloth.c')
-rw-r--r--source/blender/blenkernel/intern/cloth.c172
1 files changed, 168 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index d80fae29cc8..c26800aefba 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -31,6 +31,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_edgehash.h"
#include "BLI_linklist.h"
@@ -130,6 +131,16 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->eff_force_scale = 1000.0;
clmd->sim_parms->eff_wind_scale = 250.0;
+ /* Internal spring settings */
+ clmd->sim_parms->internal_spring_max_length = 0.0f;
+ clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
+ clmd->sim_parms->internal_tension = 15.0f;
+ clmd->sim_parms->max_internal_tension = 15.0f;
+ clmd->sim_parms->internal_compression = 15.0f;
+ clmd->sim_parms->max_internal_compression = 15.0f;
+ clmd->sim_parms->vgroup_intern = 0;
+ clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL;
+
/* Pressure settings */
clmd->sim_parms->uniform_pressure_force = 0.0f;
clmd->sim_parms->target_volume = 0.0f;
@@ -654,7 +665,7 @@ int cloth_uses_vgroup(ClothModifierData *clmd)
(clmd->coll_parms->vgroup_selfcol > 0)) ||
(clmd->sim_parms->vgroup_pressure > 0) || (clmd->sim_parms->vgroup_struct > 0) ||
(clmd->sim_parms->vgroup_bend > 0) || (clmd->sim_parms->vgroup_shrink > 0) ||
- (clmd->sim_parms->vgroup_mass > 0));
+ (clmd->sim_parms->vgroup_intern > 0) || (clmd->sim_parms->vgroup_mass > 0));
}
/**
@@ -729,8 +740,14 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh)
verts->shrink_factor = dvert->dw[j].weight;
}
+ if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_intern - 1)) {
+ /* Used to define the stiffness weight on the internal spring connected to this vertex.
+ */
+ verts->internal_stiff = dvert->dw[j].weight;
+ }
+
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_pressure - 1)) {
- /* Used to define how much the pressure settings should affect the given vertex */
+ /* Used to define how much the pressure settings should affect the given vertex. */
verts->pressure_factor = dvert->dw[j].weight;
}
}
@@ -1144,6 +1161,11 @@ static void cloth_update_springs(ClothModifierData *clmd)
cloth->verts[spring->ij].bend_stiff) /
2.0f;
}
+ else if (spring->type & CLOTH_SPRING_TYPE_INTERNAL) {
+ spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
+ cloth->verts[spring->ij].internal_stiff) /
+ 2.0f;
+ }
else if (spring->type == CLOTH_SPRING_TYPE_BENDING_HAIR) {
ClothVertex *v1 = &cloth->verts[spring->ij];
ClothVertex *v2 = &cloth->verts[spring->kl];
@@ -1208,8 +1230,8 @@ static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh)
ClothSpring *spring = search->link;
if (spring->type != CLOTH_SPRING_TYPE_SEWING) {
- if (spring->type &
- (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | CLOTH_SPRING_TYPE_BENDING)) {
+ if (spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR |
+ CLOTH_SPRING_TYPE_BENDING | CLOTH_SPRING_TYPE_INTERNAL)) {
shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
}
else {
@@ -1385,6 +1407,85 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop
return true;
}
+static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
+ unsigned int v_idx,
+ RNG *rng,
+ float max_length,
+ float max_diversion,
+ bool check_normal,
+ unsigned int *r_tar_v_idx)
+{
+ float co[3], no[3], new_co[3];
+ float radius;
+
+ copy_v3_v3(co, treedata->vert[v_idx].co);
+ normal_short_to_float_v3(no, treedata->vert[v_idx].no);
+ negate_v3(no);
+
+ float vec_len = sin(max_diversion);
+ float offset[3];
+
+ offset[0] = 0.5f - BLI_rng_get_float(rng);
+ offset[1] = 0.5f - BLI_rng_get_float(rng);
+ offset[2] = 0.5f - BLI_rng_get_float(rng);
+
+ normalize_v3(offset);
+ mul_v3_fl(offset, vec_len);
+ add_v3_v3(no, offset);
+ normalize_v3(no);
+
+ /* Nudge the start point so we do not hit it with the ray. */
+ copy_v3_v3(new_co, no);
+ mul_v3_fl(new_co, FLT_EPSILON);
+ add_v3_v3(new_co, co);
+
+ radius = 0.0f;
+ if (max_length == 0.0f) {
+ max_length = FLT_MAX;
+ }
+
+ BVHTreeRayHit rayhit = {0};
+ rayhit.index = -1;
+ rayhit.dist = max_length;
+
+ BLI_bvhtree_ray_cast(
+ treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
+
+ unsigned int vert_idx = -1;
+ const MLoop *mloop = treedata->loop;
+ const MLoopTri *lt = NULL;
+
+ if (rayhit.index != -1 && rayhit.dist <= max_length) {
+ if (check_normal && dot_v3v3(rayhit.no, no) < 0.0f) {
+ /* We hit a point that points in the same direction as our starting point. */
+ return false;
+ }
+
+ float min_len = FLT_MAX;
+ lt = &treedata->looptri[rayhit.index];
+
+ for (int i = 0; i < 3; i++) {
+ unsigned int tmp_vert_idx = mloop[lt->tri[i]].v;
+ if (tmp_vert_idx == v_idx) {
+ /* We managed to hit ourselves. */
+ return false;
+ }
+
+ float len = len_v3v3(co, rayhit.co);
+ if (len < min_len) {
+ min_len = len;
+ vert_idx = tmp_vert_idx;
+ }
+ }
+
+ *r_tar_v_idx = vert_idx;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
{
Cloth *cloth = clmd->clothObject;
@@ -1431,6 +1532,69 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
}
}
+ bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS);
+
+ if (use_internal_springs) {
+ BVHTreeFromMesh treedata = {NULL};
+ unsigned int tar_v_idx;
+ BLI_bitmap *verts_used = NULL;
+ RNG *rng;
+
+ verts_used = BLI_BITMAP_NEW(mvert_num * mvert_num, __func__);
+ BKE_bvhtree_from_mesh_get(&treedata, mesh, BVHTREE_FROM_LOOPTRI, 2);
+ rng = BLI_rng_new_srandom(0);
+
+ for (int i = 0; i < mvert_num; i++) {
+ if (find_internal_spring_target_vertex(
+ &treedata,
+ i,
+ rng,
+ clmd->sim_parms->internal_spring_max_length,
+ clmd->sim_parms->internal_spring_max_diversion,
+ (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL),
+ &tar_v_idx)) {
+ if (BLI_BITMAP_TEST_BOOL(verts_used, i * mvert_num + tar_v_idx)) {
+ continue;
+ }
+
+ BLI_BITMAP_ENABLE(verts_used, i * mvert_num + tar_v_idx);
+ BLI_BITMAP_ENABLE(verts_used, tar_v_idx * mvert_num + i);
+
+ spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
+
+ if (spring) {
+ spring_verts_ordered_set(spring, i, tar_v_idx);
+
+ shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
+ spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
+ cloth->verts[spring->ij].xrest) *
+ shrink_factor;
+ spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
+ cloth->verts[spring->ij].internal_stiff) /
+ 2.0f;
+ spring->type = CLOTH_SPRING_TYPE_INTERNAL;
+
+ spring->flags = 0;
+
+ BLI_linklist_prepend(&cloth->springs, spring);
+
+ if (spring_ref) {
+ spring_ref[i].spring = spring;
+ }
+ }
+ else {
+ cloth_free_errorsprings(cloth, edgelist, spring_ref);
+ MEM_freeN(verts_used);
+ free_bvhtree_from_mesh(&treedata);
+ return 0;
+ }
+ }
+ }
+ MEM_freeN(verts_used);
+ free_bvhtree_from_mesh(&treedata);
+ BLI_rng_free(rng);
+ }
+
clmd->sim_parms->avg_spring_len = 0.0f;
for (int i = 0; i < mvert_num; i++) {
cloth->verts[i].avg_spring_len = 0.0f;