Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/cloth.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon); | clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh) | static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh) | ||||
| { | { | ||||
| const MLoop *mloop = BKE_mesh_loops(mesh); | |||||
| const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); | const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); | ||||
| const uint mvert_num = mesh->totvert; | const uint mvert_num = mesh->totvert; | ||||
| const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh); | const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh); | ||||
| /* Allocate our vertices. */ | /* Allocate our vertices. */ | ||||
| clmd->clothObject->mvert_num = mvert_num; | clmd->clothObject->mvert_num = mvert_num; | ||||
| clmd->clothObject->verts = MEM_cnew_array<ClothVertex>(clmd->clothObject->mvert_num, __func__); | clmd->clothObject->verts = MEM_cnew_array<ClothVertex>(clmd->clothObject->mvert_num, __func__); | ||||
| if (clmd->clothObject->verts == nullptr) { | if (clmd->clothObject->verts == nullptr) { | ||||
| Show All 16 Lines | |||||
| MEM_malloc_arrayN(looptri_num, sizeof(MVertTri), __func__)); | MEM_malloc_arrayN(looptri_num, sizeof(MVertTri), __func__)); | ||||
| if (clmd->clothObject->tri == nullptr) { | if (clmd->clothObject->tri == nullptr) { | ||||
| cloth_free_modifier(clmd); | cloth_free_modifier(clmd); | ||||
| BKE_modifier_set_error( | BKE_modifier_set_error( | ||||
| ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); | ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); | ||||
| printf("cloth_free_modifier clmd->clothObject->looptri\n"); | printf("cloth_free_modifier clmd->clothObject->looptri\n"); | ||||
| return; | return; | ||||
| } | } | ||||
| BKE_mesh_runtime_verttri_from_looptri(clmd->clothObject->tri, mloop, looptri, looptri_num); | BKE_mesh_runtime_verttri_from_looptri( | ||||
| clmd->clothObject->tri, mesh->corner_verts().data(), looptri, looptri_num); | |||||
| clmd->clothObject->edges = BKE_mesh_edges(mesh); | clmd->clothObject->edges = BKE_mesh_edges(mesh); | ||||
| /* Free the springs since they can't be correct if the vertices | /* Free the springs since they can't be correct if the vertices | ||||
| * changed. | * changed. | ||||
| */ | */ | ||||
| if (clmd->clothObject->springs != nullptr) { | if (clmd->clothObject->springs != nullptr) { | ||||
| MEM_freeN(clmd->clothObject->springs); | MEM_freeN(clmd->clothObject->springs); | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| /* rotate the frame */ | /* rotate the frame */ | ||||
| mul_m3_m3m3(mat, rot, mat); | mul_m3_m3m3(mat, rot, mat); | ||||
| } | } | ||||
| /* Add a shear and a bend spring between two verts within a poly. */ | /* Add a shear and a bend spring between two verts within a poly. */ | ||||
| static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, | static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, | ||||
| LinkNodePair *edgelist, | LinkNodePair *edgelist, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| int i, | int i, | ||||
| int j, | int j, | ||||
| int k) | int k) | ||||
| { | { | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| ClothSpring *spring; | ClothSpring *spring; | ||||
| const MLoop *tmp_loop; | const int *tmp_corner; | ||||
| float shrink_factor; | float shrink_factor; | ||||
| int x, y; | int x, y; | ||||
| /* Combined shear/bend properties. */ | /* Combined shear/bend properties. */ | ||||
| spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | ||||
| if (!spring) { | if (!spring) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| spring_verts_ordered_set( | spring_verts_ordered_set( | ||||
| spring, mloop[mpoly[i].loopstart + j].v, mloop[mpoly[i].loopstart + k].v); | spring, corner_verts[mpoly[i].loopstart + j], corner_verts[mpoly[i].loopstart + k]); | ||||
| shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); | 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) * | spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * | ||||
| shrink_factor; | shrink_factor; | ||||
| spring->type |= CLOTH_SPRING_TYPE_SHEAR; | spring->type |= CLOTH_SPRING_TYPE_SHEAR; | ||||
| spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff + | spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff + | ||||
| cloth->verts[spring->ij].shear_stiff) / | cloth->verts[spring->ij].shear_stiff) / | ||||
| 2.0f; | 2.0f; | ||||
| Show All 15 Lines | |||||
| return false; | return false; | ||||
| } | } | ||||
| spring->pb = static_cast<int *>(MEM_mallocN(sizeof(*spring->pb) * spring->lb, "spring poly")); | spring->pb = static_cast<int *>(MEM_mallocN(sizeof(*spring->pb) * spring->lb, "spring poly")); | ||||
| if (!spring->pb) { | if (!spring->pb) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| tmp_loop = mloop + mpoly[i].loopstart; | tmp_corner = corner_verts + mpoly[i].loopstart; | ||||
| for (x = 0; x < spring->la; x++) { | for (x = 0; x < spring->la; x++) { | ||||
| spring->pa[x] = tmp_loop[j + x].v; | spring->pa[x] = tmp_corner[j + x]; | ||||
| } | } | ||||
| for (x = 0; x <= j; x++) { | for (x = 0; x <= j; x++) { | ||||
| spring->pb[x] = tmp_loop[x].v; | spring->pb[x] = tmp_corner[x]; | ||||
| } | } | ||||
| for (y = k; y < mpoly[i].totloop; x++, y++) { | for (y = k; y < mpoly[i].totloop; x++, y++) { | ||||
| spring->pb[x] = tmp_loop[y].v; | spring->pb[x] = tmp_corner[y]; | ||||
| } | } | ||||
| spring->mn = -1; | spring->mn = -1; | ||||
| spring->restang = cloth_spring_angle( | spring->restang = cloth_spring_angle( | ||||
| cloth->verts, spring->ij, spring->kl, spring->pa, spring->pb, spring->la, spring->lb); | cloth->verts, spring->ij, spring->kl, spring->pa, spring->pb, spring->la, spring->lb); | ||||
| spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff + | spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff + | ||||
| cloth->verts[spring->kl].bend_stiff) / | cloth->verts[spring->kl].bend_stiff) / | ||||
| 2.0f; | 2.0f; | ||||
| } | } | ||||
| BLI_linklist_prepend(&cloth->springs, spring); | BLI_linklist_prepend(&cloth->springs, spring); | ||||
| return true; | return true; | ||||
| } | } | ||||
| BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop *mloop) | BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const int *corner_verts) | ||||
| { | { | ||||
| int *p = static_cast<int *>(MEM_mallocN(sizeof(int) * len, "spring poly")); | int *p = static_cast<int *>(MEM_mallocN(sizeof(int) * len, "spring poly")); | ||||
| if (!p) { | if (!p) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| for (int i = 0; i < len; i++, mloop++) { | for (int i = 0; i < len; i++) { | ||||
| p[i] = mloop->v; | p[i] = corner_verts[i]; | ||||
| } | } | ||||
| *poly = p; | *poly = p; | ||||
| return true; | return true; | ||||
| } | } | ||||
| static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, | static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, | ||||
| Show All 36 Lines | |||||
| BVHTreeRayHit rayhit = {0}; | BVHTreeRayHit rayhit = {0}; | ||||
| rayhit.index = -1; | rayhit.index = -1; | ||||
| rayhit.dist = max_length; | rayhit.dist = max_length; | ||||
| BLI_bvhtree_ray_cast( | BLI_bvhtree_ray_cast( | ||||
| treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata); | treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata); | ||||
| uint vert_idx = -1; | uint vert_idx = -1; | ||||
| const MLoop *mloop = treedata->loop; | const int *corner_verts = treedata->corner_verts; | ||||
| const MLoopTri *lt = nullptr; | const MLoopTri *lt = nullptr; | ||||
| if (rayhit.index != -1 && rayhit.dist <= max_length) { | if (rayhit.index != -1 && rayhit.dist <= max_length) { | ||||
| if (check_normal && dot_v3v3(rayhit.no, no) < 0.0f) { | if (check_normal && dot_v3v3(rayhit.no, no) < 0.0f) { | ||||
| /* We hit a point that points in the same direction as our starting point. */ | /* We hit a point that points in the same direction as our starting point. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| float min_len = FLT_MAX; | float min_len = FLT_MAX; | ||||
| lt = &treedata->looptri[rayhit.index]; | lt = &treedata->looptri[rayhit.index]; | ||||
| for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
| uint tmp_vert_idx = mloop[lt->tri[i]].v; | uint tmp_vert_idx = corner_verts[lt->tri[i]]; | ||||
| if (tmp_vert_idx == v_idx) { | if (tmp_vert_idx == v_idx) { | ||||
| /* We managed to hit ourselves. */ | /* We managed to hit ourselves. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| float len = len_v3v3(co, rayhit.co); | float len = len_v3v3(co, rayhit.co); | ||||
| if (len < min_len) { | if (len < min_len) { | ||||
| min_len = len; | min_len = len; | ||||
| vert_idx = tmp_vert_idx; | vert_idx = tmp_vert_idx; | ||||
| } | } | ||||
| } | } | ||||
| *r_tar_v_idx = vert_idx; | *r_tar_v_idx = vert_idx; | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) | static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) | ||||
| { | { | ||||
| using namespace blender; | |||||
| using namespace blender::bke; | using namespace blender::bke; | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr; | ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr; | ||||
| uint struct_springs = 0, shear_springs = 0, bend_springs = 0, struct_springs_real = 0; | uint struct_springs = 0, shear_springs = 0, bend_springs = 0, struct_springs_real = 0; | ||||
| uint mvert_num = uint(mesh->totvert); | uint mvert_num = uint(mesh->totvert); | ||||
| uint numedges = uint(mesh->totedge); | uint numedges = uint(mesh->totedge); | ||||
| uint numpolys = uint(mesh->totpoly); | uint numpolys = uint(mesh->totpoly); | ||||
| float shrink_factor; | float shrink_factor; | ||||
| const MEdge *medge = BKE_mesh_edges(mesh); | const MEdge *medge = BKE_mesh_edges(mesh); | ||||
| const MPoly *mpoly = BKE_mesh_polys(mesh); | const MPoly *mpoly = BKE_mesh_polys(mesh); | ||||
| const MLoop *mloop = BKE_mesh_loops(mesh); | const Span<int> corner_verts = mesh->corner_verts(); | ||||
| const Span<int> corner_edges = mesh->corner_edges(); | |||||
| int index2 = 0; /* our second vertex index */ | int index2 = 0; /* our second vertex index */ | ||||
| LinkNodePair *edgelist = nullptr; | LinkNodePair *edgelist = nullptr; | ||||
| EdgeSet *edgeset = nullptr; | EdgeSet *edgeset = nullptr; | ||||
| LinkNode *search = nullptr, *search2 = nullptr; | LinkNode *search = nullptr, *search2 = nullptr; | ||||
| BendSpringRef *spring_ref = nullptr; | BendSpringRef *spring_ref = nullptr; | ||||
| /* error handling */ | /* error handling */ | ||||
| if (numedges == 0) { | if (numedges == 0) { | ||||
| ▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | |||||
| if (numpolys) { | if (numpolys) { | ||||
| for (int i = 0; i < numpolys; i++) { | for (int i = 0; i < numpolys; i++) { | ||||
| /* Shear springs. */ | /* Shear springs. */ | ||||
| /* Triangle faces already have shear springs due to structural geometry. */ | /* Triangle faces already have shear springs due to structural geometry. */ | ||||
| if (mpoly[i].totloop > 3) { | if (mpoly[i].totloop > 3) { | ||||
| for (int j = 1; j < mpoly[i].totloop - 1; j++) { | for (int j = 1; j < mpoly[i].totloop - 1; j++) { | ||||
| if (j > 1) { | if (j > 1) { | ||||
| if (cloth_add_shear_bend_spring(clmd, edgelist, mloop, mpoly, i, 0, j)) { | if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts.data(), mpoly, i, 0, j)) { | ||||
| shear_springs++; | shear_springs++; | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| bend_springs++; | bend_springs++; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| for (int k = j + 2; k < mpoly[i].totloop; k++) { | for (int k = j + 2; k < mpoly[i].totloop; k++) { | ||||
| if (cloth_add_shear_bend_spring(clmd, edgelist, mloop, mpoly, i, j, k)) { | if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts.data(), mpoly, i, j, k)) { | ||||
| shear_springs++; | shear_springs++; | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| bend_springs++; | bend_springs++; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Angular bending springs along struct springs. */ | /* Angular bending springs along struct springs. */ | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| const MLoop *ml = mloop + mpoly[i].loopstart; | for (int j = 0; j < mpoly[i].totloop; j++) { | ||||
| const int edge_i = corner_edges[mpoly[i].loopstart + j]; | |||||
| for (int j = 0; j < mpoly[i].totloop; j++, ml++) { | BendSpringRef *curr_ref = &spring_ref[edge_i]; | ||||
| BendSpringRef *curr_ref = &spring_ref[ml->e]; | |||||
| curr_ref->polys++; | curr_ref->polys++; | ||||
| /* First poly found for this edge, store poly index. */ | /* First poly found for this edge, store poly index. */ | ||||
| if (curr_ref->polys == 1) { | if (curr_ref->polys == 1) { | ||||
| curr_ref->index = i; | curr_ref->index = i; | ||||
| } | } | ||||
| /* Second poly found for this edge, add bending data. */ | /* Second poly found for this edge, add bending data. */ | ||||
| else if (curr_ref->polys == 2) { | else if (curr_ref->polys == 2) { | ||||
| spring = curr_ref->spring; | spring = curr_ref->spring; | ||||
| spring->type |= CLOTH_SPRING_TYPE_BENDING; | spring->type |= CLOTH_SPRING_TYPE_BENDING; | ||||
| spring->la = mpoly[curr_ref->index].totloop; | spring->la = mpoly[curr_ref->index].totloop; | ||||
| spring->lb = mpoly[i].totloop; | spring->lb = mpoly[i].totloop; | ||||
| if (!cloth_bend_set_poly_vert_array( | if (!cloth_bend_set_poly_vert_array( | ||||
| &spring->pa, spring->la, &mloop[mpoly[curr_ref->index].loopstart]) || | &spring->pa, spring->la, &corner_verts[mpoly[curr_ref->index].loopstart]) || | ||||
| !cloth_bend_set_poly_vert_array( | !cloth_bend_set_poly_vert_array( | ||||
| &spring->pb, spring->lb, &mloop[mpoly[i].loopstart])) { | &spring->pb, spring->lb, &corner_verts[mpoly[i].loopstart])) { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| return false; | return false; | ||||
| } | } | ||||
| spring->mn = ml->e; | spring->mn = edge_i; | ||||
| spring->restang = cloth_spring_angle(cloth->verts, | spring->restang = cloth_spring_angle(cloth->verts, | ||||
| spring->ij, | spring->ij, | ||||
| spring->kl, | spring->kl, | ||||
| spring->pa, | spring->pa, | ||||
| spring->pb, | spring->pb, | ||||
| spring->la, | spring->la, | ||||
| spring->lb); | spring->lb); | ||||
| ▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | |||||
| /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ | /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ | ||||
| for (int i = 0; i < numedges; i++) { /* struct springs */ | for (int i = 0; i < numedges; i++) { /* struct springs */ | ||||
| BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2); | BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2); | ||||
| } | } | ||||
| for (int i = 0; i < numpolys; i++) { /* edge springs */ | for (int i = 0; i < numpolys; i++) { /* edge springs */ | ||||
| if (mpoly[i].totloop == 4) { | if (mpoly[i].totloop == 4) { | ||||
| BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 0].v, mloop[mpoly[i].loopstart + 2].v); | BLI_edgeset_add( | ||||
| BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 1].v, mloop[mpoly[i].loopstart + 3].v); | edgeset, corner_verts[mpoly[i].loopstart + 0], corner_verts[mpoly[i].loopstart + 2]); | ||||
| BLI_edgeset_add( | |||||
| edgeset, corner_verts[mpoly[i].loopstart + 1], corner_verts[mpoly[i].loopstart + 3]); | |||||
| } | } | ||||
| } | } | ||||
| MEM_SAFE_FREE(spring_ref); | MEM_SAFE_FREE(spring_ref); | ||||
| cloth->numsprings = struct_springs + shear_springs + bend_springs; | cloth->numsprings = struct_springs + shear_springs + bend_springs; | ||||
| cloth_free_edgelist(edgelist, mvert_num); | cloth_free_edgelist(edgelist, mvert_num); | ||||
| Show All 11 Lines | |||||