Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/cloth.cc
- This file was moved from source/blender/blenkernel/intern/cloth.c.
| Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
| static bool cloth_from_object( | static bool cloth_from_object( | ||||
| Object *ob, ClothModifierData *clmd, Mesh *mesh, float framenr, int first); | Object *ob, ClothModifierData *clmd, Mesh *mesh, float framenr, int first); | ||||
| static void cloth_update_springs(ClothModifierData *clmd); | static void cloth_update_springs(ClothModifierData *clmd); | ||||
| static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh); | static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh); | ||||
| static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh); | static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh); | ||||
| static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh); | static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh); | ||||
| static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh); | static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh); | ||||
| typedef struct BendSpringRef { | struct BendSpringRef { | ||||
| int index; | int index; | ||||
| int polys; | int polys; | ||||
| ClothSpring *spring; | ClothSpring *spring; | ||||
| } BendSpringRef; | }; | ||||
| /****************************************************************************** | /****************************************************************************** | ||||
| * | * | ||||
| * External interface called by modifier.cc clothModifier functions. | * External interface called by modifier.cc clothModifier functions. | ||||
| * | * | ||||
| ******************************************************************************/ | ******************************************************************************/ | ||||
| static BVHTree *bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon) | static BVHTree *bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon) | ||||
| { | { | ||||
| if (!clmd) { | if (!clmd) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| if (!cloth) { | if (!cloth) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| ClothVertex *verts = cloth->verts; | ClothVertex *verts = cloth->verts; | ||||
| const MVertTri *vt = cloth->tri; | const MVertTri *vt = cloth->tri; | ||||
| /* in the moment, return zero if no faces there */ | /* in the moment, return zero if no faces there */ | ||||
| if (!cloth->primitive_num) { | if (!cloth->primitive_num) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| /* Create quad-tree with k=26. */ | /* Create quad-tree with k=26. */ | ||||
| BVHTree *bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26); | BVHTree *bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26); | ||||
| /* fill tree */ | /* fill tree */ | ||||
| if (clmd->hairdata == NULL) { | if (clmd->hairdata == nullptr) { | ||||
| for (int i = 0; i < cloth->primitive_num; i++, vt++) { | for (int i = 0; i < cloth->primitive_num; i++, vt++) { | ||||
| float co[3][3]; | float co[3][3]; | ||||
| copy_v3_v3(co[0], verts[vt->tri[0]].xold); | copy_v3_v3(co[0], verts[vt->tri[0]].xold); | ||||
| copy_v3_v3(co[1], verts[vt->tri[1]].xold); | copy_v3_v3(co[1], verts[vt->tri[1]].xold); | ||||
| copy_v3_v3(co[2], verts[vt->tri[2]].xold); | copy_v3_v3(co[2], verts[vt->tri[2]].xold); | ||||
| BLI_bvhtree_insert(bvhtree, i, co[0], 3); | BLI_bvhtree_insert(bvhtree, i, co[0], 3); | ||||
| Show All 21 Lines | |||||
| void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self) | void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self) | ||||
| { | { | ||||
| uint i = 0; | uint i = 0; | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| BVHTree *bvhtree; | BVHTree *bvhtree; | ||||
| ClothVertex *verts = cloth->verts; | ClothVertex *verts = cloth->verts; | ||||
| const MVertTri *vt; | const MVertTri *vt; | ||||
| BLI_assert(!(clmd->hairdata != NULL && self)); | BLI_assert(!(clmd->hairdata != nullptr && self)); | ||||
| if (self) { | if (self) { | ||||
| bvhtree = cloth->bvhselftree; | bvhtree = cloth->bvhselftree; | ||||
| } | } | ||||
| else { | else { | ||||
| bvhtree = cloth->bvhtree; | bvhtree = cloth->bvhtree; | ||||
| } | } | ||||
| if (!bvhtree) { | if (!bvhtree) { | ||||
| return; | return; | ||||
| } | } | ||||
| vt = cloth->tri; | vt = cloth->tri; | ||||
| /* update vertex position in bvh tree */ | /* update vertex position in bvh tree */ | ||||
| if (clmd->hairdata == NULL) { | if (clmd->hairdata == nullptr) { | ||||
| if (verts && vt) { | if (verts && vt) { | ||||
| for (i = 0; i < cloth->primitive_num; i++, vt++) { | for (i = 0; i < cloth->primitive_num; i++, vt++) { | ||||
| float co[3][3], co_moving[3][3]; | float co[3][3], co_moving[3][3]; | ||||
| bool ret; | bool ret; | ||||
| /* copy new locations into array */ | /* copy new locations into array */ | ||||
| if (moving) { | if (moving) { | ||||
| copy_v3_v3(co[0], verts[vt->tri[0]].txold); | copy_v3_v3(co[0], verts[vt->tri[0]].txold); | ||||
| copy_v3_v3(co[1], verts[vt->tri[1]].txold); | copy_v3_v3(co[1], verts[vt->tri[1]].txold); | ||||
| copy_v3_v3(co[2], verts[vt->tri[2]].txold); | copy_v3_v3(co[2], verts[vt->tri[2]].txold); | ||||
| /* update moving positions */ | /* update moving positions */ | ||||
| copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx); | copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx); | ||||
| copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx); | copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx); | ||||
| copy_v3_v3(co_moving[2], verts[vt->tri[2]].tx); | copy_v3_v3(co_moving[2], verts[vt->tri[2]].tx); | ||||
| ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3); | ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(co[0], verts[vt->tri[0]].tx); | copy_v3_v3(co[0], verts[vt->tri[0]].tx); | ||||
| copy_v3_v3(co[1], verts[vt->tri[1]].tx); | copy_v3_v3(co[1], verts[vt->tri[1]].tx); | ||||
| copy_v3_v3(co[2], verts[vt->tri[2]].tx); | copy_v3_v3(co[2], verts[vt->tri[2]].tx); | ||||
| ret = BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 3); | ret = BLI_bvhtree_update_node(bvhtree, i, co[0], nullptr, 3); | ||||
| } | } | ||||
| /* check if tree is already full */ | /* check if tree is already full */ | ||||
| if (ret == false) { | if (ret == false) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| BLI_bvhtree_update_tree(bvhtree); | BLI_bvhtree_update_tree(bvhtree); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (verts) { | if (verts) { | ||||
| const MEdge *edges = cloth->edges; | const MEdge *edges = cloth->edges; | ||||
| for (i = 0; i < cloth->primitive_num; i++) { | for (i = 0; i < cloth->primitive_num; i++) { | ||||
| float co[2][3]; | float co[2][3]; | ||||
| copy_v3_v3(co[0], verts[edges[i].v1].tx); | copy_v3_v3(co[0], verts[edges[i].v1].tx); | ||||
| copy_v3_v3(co[1], verts[edges[i].v2].tx); | copy_v3_v3(co[1], verts[edges[i].v2].tx); | ||||
| if (!BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 2)) { | if (!BLI_bvhtree_update_node(bvhtree, i, co[0], nullptr, 2)) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| BLI_bvhtree_update_tree(bvhtree); | BLI_bvhtree_update_tree(bvhtree); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 14 Lines | |||||
| static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) | static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) | ||||
| { | { | ||||
| PointCache *cache; | PointCache *cache; | ||||
| cache = clmd->point_cache; | cache = clmd->point_cache; | ||||
| /* initialize simulation data if it didn't exist already */ | /* initialize simulation data if it didn't exist already */ | ||||
| if (clmd->clothObject == NULL) { | if (clmd->clothObject == nullptr) { | ||||
| if (!cloth_from_object(ob, clmd, result, framenr, 1)) { | if (!cloth_from_object(ob, clmd, result, framenr, 1)) { | ||||
| BKE_ptcache_invalidate(cache); | BKE_ptcache_invalidate(cache); | ||||
| BKE_modifier_set_error(ob, &(clmd->modifier), "Can't initialize cloth"); | BKE_modifier_set_error(ob, &(clmd->modifier), "Can't initialize cloth"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (clmd->clothObject == NULL) { | if (clmd->clothObject == nullptr) { | ||||
| BKE_ptcache_invalidate(cache); | BKE_ptcache_invalidate(cache); | ||||
| BKE_modifier_set_error(ob, &(clmd->modifier), "Null cloth object"); | BKE_modifier_set_error(ob, &(clmd->modifier), "Null cloth object"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| SIM_cloth_solver_set_positions(clmd); | SIM_cloth_solver_set_positions(clmd); | ||||
| ClothSimSettings *parms = clmd->sim_parms; | ClothSimSettings *parms = clmd->sim_parms; | ||||
| if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE && | if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE && | ||||
| !(parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL)) { | !(parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL)) { | ||||
| SIM_cloth_solver_set_volume(clmd); | SIM_cloth_solver_set_volume(clmd); | ||||
| } | } | ||||
| clmd->clothObject->last_frame = MINFRAME - 1; | clmd->clothObject->last_frame = MINFRAME - 1; | ||||
| clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; | clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static int do_step_cloth( | static int do_step_cloth( | ||||
| Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) | Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) | ||||
| { | { | ||||
| /* simulate 1 frame forward */ | /* simulate 1 frame forward */ | ||||
| ClothVertex *verts = NULL; | ClothVertex *verts = nullptr; | ||||
| Cloth *cloth; | Cloth *cloth; | ||||
| ListBase *effectors = NULL; | ListBase *effectors = nullptr; | ||||
| MVert *mvert; | MVert *mvert; | ||||
| uint i = 0; | uint i = 0; | ||||
| int ret = 0; | int ret = 0; | ||||
| bool vert_mass_changed = false; | bool vert_mass_changed = false; | ||||
| cloth = clmd->clothObject; | cloth = clmd->clothObject; | ||||
| verts = cloth->verts; | verts = cloth->verts; | ||||
| mvert = BKE_mesh_verts_for_write(result); | mvert = BKE_mesh_verts_for_write(result); | ||||
| Show All 10 Lines | for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) { | ||||
| mul_m4_v3(ob->object_to_world, verts->xconst); | mul_m4_v3(ob->object_to_world, verts->xconst); | ||||
| if (vert_mass_changed) { | if (vert_mass_changed) { | ||||
| verts->mass = clmd->sim_parms->mass; | verts->mass = clmd->sim_parms->mass; | ||||
| SIM_mass_spring_set_implicit_vertex_mass(cloth->implicit, i, verts->mass); | SIM_mass_spring_set_implicit_vertex_mass(cloth->implicit, i, verts->mass); | ||||
| } | } | ||||
| } | } | ||||
| effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights, false); | effectors = BKE_effectors_create( | ||||
| depsgraph, ob, nullptr, clmd->sim_parms->effector_weights, false); | |||||
| if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) { | if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) { | ||||
| cloth_update_verts(ob, clmd, result); | cloth_update_verts(ob, clmd, result); | ||||
| } | } | ||||
| /* Support for dynamic vertex groups, changing from frame to frame */ | /* Support for dynamic vertex groups, changing from frame to frame */ | ||||
| cloth_apply_vgroup(clmd, result); | cloth_apply_vgroup(clmd, result); | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | if (framenr == startframe) { | ||||
| clmd->clothObject->last_frame = framenr; | clmd->clothObject->last_frame = framenr; | ||||
| return; | return; | ||||
| } | } | ||||
| /* try to read from cache */ | /* try to read from cache */ | ||||
| bool can_simulate = (framenr == clmd->clothObject->last_frame + 1) && | bool can_simulate = (framenr == clmd->clothObject->last_frame + 1) && | ||||
| !(cache->flag & PTCACHE_BAKED); | !(cache->flag & PTCACHE_BAKED); | ||||
| cache_result = BKE_ptcache_read(&pid, (float)framenr + scene->r.subframe, can_simulate); | cache_result = BKE_ptcache_read(&pid, float(framenr) + scene->r.subframe, can_simulate); | ||||
| if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED || | if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED || | ||||
| (!can_simulate && cache_result == PTCACHE_READ_OLD)) { | (!can_simulate && cache_result == PTCACHE_READ_OLD)) { | ||||
| SIM_cloth_solver_set_positions(clmd); | SIM_cloth_solver_set_positions(clmd); | ||||
| cloth_to_object(ob, clmd, vertexCos); | cloth_to_object(ob, clmd, vertexCos); | ||||
| BKE_ptcache_validate(cache, framenr); | BKE_ptcache_validate(cache, framenr); | ||||
| Show All 35 Lines | void clothModifier_do(ClothModifierData *clmd, | ||||
| } | } | ||||
| cloth_to_object(ob, clmd, vertexCos); | cloth_to_object(ob, clmd, vertexCos); | ||||
| clmd->clothObject->last_frame = framenr; | clmd->clothObject->last_frame = framenr; | ||||
| } | } | ||||
| void cloth_free_modifier(ClothModifierData *clmd) | void cloth_free_modifier(ClothModifierData *clmd) | ||||
| { | { | ||||
| Cloth *cloth = NULL; | Cloth *cloth = nullptr; | ||||
| if (!clmd) { | if (!clmd) { | ||||
| return; | return; | ||||
| } | } | ||||
| cloth = clmd->clothObject; | cloth = clmd->clothObject; | ||||
| if (cloth) { | if (cloth) { | ||||
| SIM_cloth_solver_free(clmd); | SIM_cloth_solver_free(clmd); | ||||
| /* Free the verts. */ | /* Free the verts. */ | ||||
| MEM_SAFE_FREE(cloth->verts); | MEM_SAFE_FREE(cloth->verts); | ||||
| cloth->mvert_num = 0; | cloth->mvert_num = 0; | ||||
| /* Free the springs. */ | /* Free the springs. */ | ||||
| if (cloth->springs != NULL) { | if (cloth->springs != nullptr) { | ||||
| LinkNode *search = cloth->springs; | LinkNode *search = cloth->springs; | ||||
| while (search) { | while (search) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| MEM_SAFE_FREE(spring->pa); | MEM_SAFE_FREE(spring->pa); | ||||
| MEM_SAFE_FREE(spring->pb); | MEM_SAFE_FREE(spring->pb); | ||||
| MEM_freeN(spring); | MEM_freeN(spring); | ||||
| search = search->next; | search = search->next; | ||||
| } | } | ||||
| BLI_linklist_free(cloth->springs, NULL); | BLI_linklist_free(cloth->springs, nullptr); | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| } | } | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| cloth->numsprings = 0; | cloth->numsprings = 0; | ||||
| /* free BVH collision tree */ | /* free BVH collision tree */ | ||||
| if (cloth->bvhtree) { | if (cloth->bvhtree) { | ||||
| BLI_bvhtree_free(cloth->bvhtree); | BLI_bvhtree_free(cloth->bvhtree); | ||||
| } | } | ||||
| if (cloth->bvhselftree) { | if (cloth->bvhselftree) { | ||||
| BLI_bvhtree_free(cloth->bvhselftree); | BLI_bvhtree_free(cloth->bvhselftree); | ||||
| } | } | ||||
| /* we save our faces for collision objects */ | /* we save our faces for collision objects */ | ||||
| if (cloth->tri) { | if (cloth->tri) { | ||||
| MEM_freeN(cloth->tri); | MEM_freeN(cloth->tri); | ||||
| } | } | ||||
| if (cloth->edgeset) { | if (cloth->edgeset) { | ||||
| BLI_edgeset_free(cloth->edgeset); | BLI_edgeset_free(cloth->edgeset); | ||||
| } | } | ||||
| if (cloth->sew_edge_graph) { | if (cloth->sew_edge_graph) { | ||||
| BLI_edgeset_free(cloth->sew_edge_graph); | BLI_edgeset_free(cloth->sew_edge_graph); | ||||
| cloth->sew_edge_graph = NULL; | cloth->sew_edge_graph = nullptr; | ||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| if (clmd->clothObject->facemarks) { | if (clmd->clothObject->facemarks) { | ||||
| MEM_freeN(clmd->clothObject->facemarks); | MEM_freeN(clmd->clothObject->facemarks); | ||||
| } | } | ||||
| #endif | #endif | ||||
| MEM_freeN(cloth); | MEM_freeN(cloth); | ||||
| clmd->clothObject = NULL; | clmd->clothObject = nullptr; | ||||
| } | } | ||||
| } | } | ||||
| void cloth_free_modifier_extern(ClothModifierData *clmd) | void cloth_free_modifier_extern(ClothModifierData *clmd) | ||||
| { | { | ||||
| Cloth *cloth = NULL; | Cloth *cloth = nullptr; | ||||
| if (G.debug & G_DEBUG_SIMDATA) { | if (G.debug & G_DEBUG_SIMDATA) { | ||||
| printf("cloth_free_modifier_extern\n"); | printf("cloth_free_modifier_extern\n"); | ||||
| } | } | ||||
| if (!clmd) { | if (!clmd) { | ||||
| return; | return; | ||||
| } | } | ||||
| cloth = clmd->clothObject; | cloth = clmd->clothObject; | ||||
| if (cloth) { | if (cloth) { | ||||
| if (G.debug & G_DEBUG_SIMDATA) { | if (G.debug & G_DEBUG_SIMDATA) { | ||||
| printf("cloth_free_modifier_extern in\n"); | printf("cloth_free_modifier_extern in\n"); | ||||
| } | } | ||||
| SIM_cloth_solver_free(clmd); | SIM_cloth_solver_free(clmd); | ||||
| /* Free the verts. */ | /* Free the verts. */ | ||||
| MEM_SAFE_FREE(cloth->verts); | MEM_SAFE_FREE(cloth->verts); | ||||
| cloth->mvert_num = 0; | cloth->mvert_num = 0; | ||||
| /* Free the springs. */ | /* Free the springs. */ | ||||
| if (cloth->springs != NULL) { | if (cloth->springs != nullptr) { | ||||
| LinkNode *search = cloth->springs; | LinkNode *search = cloth->springs; | ||||
| while (search) { | while (search) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| MEM_SAFE_FREE(spring->pa); | MEM_SAFE_FREE(spring->pa); | ||||
| MEM_SAFE_FREE(spring->pb); | MEM_SAFE_FREE(spring->pb); | ||||
| MEM_freeN(spring); | MEM_freeN(spring); | ||||
| search = search->next; | search = search->next; | ||||
| } | } | ||||
| BLI_linklist_free(cloth->springs, NULL); | BLI_linklist_free(cloth->springs, nullptr); | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| } | } | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| cloth->numsprings = 0; | cloth->numsprings = 0; | ||||
| /* free BVH collision tree */ | /* free BVH collision tree */ | ||||
| if (cloth->bvhtree) { | if (cloth->bvhtree) { | ||||
| BLI_bvhtree_free(cloth->bvhtree); | BLI_bvhtree_free(cloth->bvhtree); | ||||
| } | } | ||||
| if (cloth->bvhselftree) { | if (cloth->bvhselftree) { | ||||
| BLI_bvhtree_free(cloth->bvhselftree); | BLI_bvhtree_free(cloth->bvhselftree); | ||||
| } | } | ||||
| /* we save our faces for collision objects */ | /* we save our faces for collision objects */ | ||||
| if (cloth->tri) { | if (cloth->tri) { | ||||
| MEM_freeN(cloth->tri); | MEM_freeN(cloth->tri); | ||||
| } | } | ||||
| if (cloth->edgeset) { | if (cloth->edgeset) { | ||||
| BLI_edgeset_free(cloth->edgeset); | BLI_edgeset_free(cloth->edgeset); | ||||
| } | } | ||||
| if (cloth->sew_edge_graph) { | if (cloth->sew_edge_graph) { | ||||
| BLI_edgeset_free(cloth->sew_edge_graph); | BLI_edgeset_free(cloth->sew_edge_graph); | ||||
| cloth->sew_edge_graph = NULL; | cloth->sew_edge_graph = nullptr; | ||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| if (clmd->clothObject->facemarks) { | if (clmd->clothObject->facemarks) { | ||||
| MEM_freeN(clmd->clothObject->facemarks); | MEM_freeN(clmd->clothObject->facemarks); | ||||
| } | } | ||||
| #endif | #endif | ||||
| MEM_freeN(cloth); | MEM_freeN(cloth); | ||||
| clmd->clothObject = NULL; | clmd->clothObject = nullptr; | ||||
| } | } | ||||
| } | } | ||||
| /****************************************************************************** | /****************************************************************************** | ||||
| * | * | ||||
| * Internal functions. | * Internal functions. | ||||
| * | * | ||||
| ******************************************************************************/ | ******************************************************************************/ | ||||
| Show All 36 Lines | static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh) | ||||
| if (!clmd || !mesh) { | if (!clmd || !mesh) { | ||||
| return; | return; | ||||
| } | } | ||||
| int mvert_num = mesh->totvert; | int mvert_num = mesh->totvert; | ||||
| ClothVertex *verts = clmd->clothObject->verts; | ClothVertex *verts = clmd->clothObject->verts; | ||||
| const blender::Span<MDeformVert> dverts = mesh->deform_verts(); | |||||
| if (cloth_uses_vgroup(clmd)) { | if (cloth_uses_vgroup(clmd)) { | ||||
| for (int i = 0; i < mvert_num; i++, verts++) { | for (int i = 0; i < mvert_num; i++, verts++) { | ||||
| /* Reset Goal values to standard */ | /* Reset Goal values to standard */ | ||||
| if (clmd->sim_parms->vgroup_mass > 0) { | if (clmd->sim_parms->vgroup_mass > 0) { | ||||
| verts->goal = clmd->sim_parms->defgoal; | verts->goal = clmd->sim_parms->defgoal; | ||||
| } | } | ||||
| else { | else { | ||||
| verts->goal = 0.0f; | verts->goal = 0.0f; | ||||
| } | } | ||||
| /* Compute base cloth shrink weight */ | /* Compute base cloth shrink weight */ | ||||
| verts->shrink_factor = 0.0f; | verts->shrink_factor = 0.0f; | ||||
| /* Reset vertex flags */ | /* Reset vertex flags */ | ||||
| verts->flags &= ~(CLOTH_VERT_FLAG_PINNED | CLOTH_VERT_FLAG_NOSELFCOLL | | verts->flags &= ~(CLOTH_VERT_FLAG_PINNED | CLOTH_VERT_FLAG_NOSELFCOLL | | ||||
| CLOTH_VERT_FLAG_NOOBJCOLL); | CLOTH_VERT_FLAG_NOOBJCOLL); | ||||
| const MDeformVert *dvert = CustomData_get(&mesh->vdata, i, CD_MDEFORMVERT); | if (!dverts.is_empty()) { | ||||
| if (dvert) { | const MDeformVert *dvert = &dverts[i]; | ||||
| for (int j = 0; j < dvert->totweight; j++) { | for (int j = 0; j < dvert->totweight; j++) { | ||||
| if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass - 1)) { | if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass - 1)) { | ||||
| verts->goal = dvert->dw[j].weight; | verts->goal = dvert->dw[j].weight; | ||||
| /* goalfac= 1.0f; */ /* UNUSED */ | /* goalfac= 1.0f; */ /* UNUSED */ | ||||
| /* Kicking goal factor to simplify things...who uses that anyway? */ | /* Kicking goal factor to simplify things...who uses that anyway? */ | ||||
| // ABS (clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal); | // ABS (clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal); | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, int i1, int i2) | ||||
| * for diagonals when a rectangle transforms into a trapezoid. */ | * for diagonals when a rectangle transforms into a trapezoid. */ | ||||
| return sqrtf(k1 * k2); | return sqrtf(k1 * k2); | ||||
| } | } | ||||
| static bool cloth_from_object( | static bool cloth_from_object( | ||||
| Object *ob, ClothModifierData *clmd, Mesh *mesh, float UNUSED(framenr), int first) | Object *ob, ClothModifierData *clmd, Mesh *mesh, float UNUSED(framenr), int first) | ||||
| { | { | ||||
| int i = 0; | int i = 0; | ||||
| ClothVertex *verts = NULL; | ClothVertex *verts = nullptr; | ||||
| const float(*shapekey_rest)[3] = NULL; | const float(*shapekey_rest)[3] = nullptr; | ||||
| const float tnull[3] = {0, 0, 0}; | const float tnull[3] = {0, 0, 0}; | ||||
| /* If we have a clothObject, free it. */ | /* If we have a clothObject, free it. */ | ||||
| if (clmd->clothObject != NULL) { | if (clmd->clothObject != nullptr) { | ||||
| cloth_free_modifier(clmd); | cloth_free_modifier(clmd); | ||||
| if (G.debug & G_DEBUG_SIMDATA) { | if (G.debug & G_DEBUG_SIMDATA) { | ||||
| printf("cloth_free_modifier cloth_from_object\n"); | printf("cloth_free_modifier cloth_from_object\n"); | ||||
| } | } | ||||
| } | } | ||||
| /* Allocate a new cloth object. */ | /* Allocate a new cloth object. */ | ||||
| clmd->clothObject = MEM_callocN(sizeof(Cloth), "cloth"); | clmd->clothObject = MEM_cnew<Cloth>(__func__); | ||||
| if (clmd->clothObject) { | if (clmd->clothObject) { | ||||
| clmd->clothObject->old_solver_type = 255; | clmd->clothObject->old_solver_type = 255; | ||||
| clmd->clothObject->edgeset = NULL; | clmd->clothObject->edgeset = nullptr; | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject"); | BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* mesh input objects need Mesh */ | /* mesh input objects need Mesh */ | ||||
| if (!mesh) { | if (!mesh) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| cloth_from_mesh(clmd, ob, mesh); | cloth_from_mesh(clmd, ob, mesh); | ||||
| /* create springs */ | /* create springs */ | ||||
| clmd->clothObject->springs = NULL; | clmd->clothObject->springs = nullptr; | ||||
| clmd->clothObject->numsprings = -1; | clmd->clothObject->numsprings = -1; | ||||
| clmd->clothObject->sew_edge_graph = NULL; | clmd->clothObject->sew_edge_graph = nullptr; | ||||
| if (clmd->sim_parms->shapekey_rest && | if (clmd->sim_parms->shapekey_rest && | ||||
| !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) { | !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) { | ||||
| shapekey_rest = CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO); | shapekey_rest = static_cast<const float(*)[3]>( | ||||
| CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO)); | |||||
| } | } | ||||
| MVert *mvert = BKE_mesh_verts_for_write(mesh); | MVert *mvert = BKE_mesh_verts_for_write(mesh); | ||||
| verts = clmd->clothObject->verts; | verts = clmd->clothObject->verts; | ||||
| /* set initial values */ | /* set initial values */ | ||||
| for (i = 0; i < mesh->totvert; i++, verts++) { | for (i = 0; i < mesh->totvert; i++, verts++) { | ||||
| ▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| const MLoop *mloop = BKE_mesh_loops(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_callocN(sizeof(ClothVertex) * clmd->clothObject->mvert_num, | clmd->clothObject->verts = MEM_cnew_array<ClothVertex>(clmd->clothObject->mvert_num, __func__); | ||||
| "clothVertex"); | if (clmd->clothObject->verts == nullptr) { | ||||
| if (clmd->clothObject->verts == NULL) { | |||||
| 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->verts"); | ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); | ||||
| printf("cloth_free_modifier clmd->clothObject->verts\n"); | printf("cloth_free_modifier clmd->clothObject->verts\n"); | ||||
| return; | return; | ||||
| } | } | ||||
| /* save face information */ | /* save face information */ | ||||
| if (clmd->hairdata == NULL) { | if (clmd->hairdata == nullptr) { | ||||
| clmd->clothObject->primitive_num = looptri_num; | clmd->clothObject->primitive_num = looptri_num; | ||||
| } | } | ||||
| else { | else { | ||||
| clmd->clothObject->primitive_num = mesh->totedge; | clmd->clothObject->primitive_num = mesh->totedge; | ||||
| } | } | ||||
| clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris"); | clmd->clothObject->tri = static_cast<MVertTri *>( | ||||
| if (clmd->clothObject->tri == NULL) { | MEM_malloc_arrayN(looptri_num, sizeof(MVertTri), __func__)); | ||||
| 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, mloop, 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 != NULL) { | if (clmd->clothObject->springs != nullptr) { | ||||
| MEM_freeN(clmd->clothObject->springs); | MEM_freeN(clmd->clothObject->springs); | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Spring Network Building Implementation | /** \name Spring Network Building Implementation | ||||
| * \{ */ | * \{ */ | ||||
| BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) | BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) | ||||
| { | { | ||||
| if (v0 < v1) { | if (v0 < v1) { | ||||
| spring->ij = v0; | spring->ij = v0; | ||||
| spring->kl = v1; | spring->kl = v1; | ||||
| } | } | ||||
| else { | else { | ||||
| spring->ij = v1; | spring->ij = v1; | ||||
| spring->kl = v0; | spring->kl = v0; | ||||
| } | } | ||||
| } | } | ||||
| static void cloth_free_edgelist(LinkNodePair *edgelist, uint mvert_num) | static void cloth_free_edgelist(LinkNodePair *edgelist, uint mvert_num) | ||||
| { | { | ||||
| if (edgelist) { | if (edgelist) { | ||||
| for (uint i = 0; i < mvert_num; i++) { | for (uint i = 0; i < mvert_num; i++) { | ||||
| BLI_linklist_free(edgelist[i].list, NULL); | BLI_linklist_free(edgelist[i].list, nullptr); | ||||
| } | } | ||||
| MEM_freeN(edgelist); | MEM_freeN(edgelist); | ||||
| } | } | ||||
| } | } | ||||
| static void cloth_free_errorsprings(Cloth *cloth, | static void cloth_free_errorsprings(Cloth *cloth, | ||||
| LinkNodePair *edgelist, | LinkNodePair *edgelist, | ||||
| BendSpringRef *spring_ref) | BendSpringRef *spring_ref) | ||||
| { | { | ||||
| if (cloth->springs != NULL) { | if (cloth->springs != nullptr) { | ||||
| LinkNode *search = cloth->springs; | LinkNode *search = cloth->springs; | ||||
| while (search) { | while (search) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| MEM_SAFE_FREE(spring->pa); | MEM_SAFE_FREE(spring->pa); | ||||
| MEM_SAFE_FREE(spring->pb); | MEM_SAFE_FREE(spring->pb); | ||||
| MEM_freeN(spring); | MEM_freeN(spring); | ||||
| search = search->next; | search = search->next; | ||||
| } | } | ||||
| BLI_linklist_free(cloth->springs, NULL); | BLI_linklist_free(cloth->springs, nullptr); | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| } | } | ||||
| cloth_free_edgelist(edgelist, cloth->mvert_num); | cloth_free_edgelist(edgelist, cloth->mvert_num); | ||||
| MEM_SAFE_FREE(spring_ref); | MEM_SAFE_FREE(spring_ref); | ||||
| if (cloth->edgeset) { | if (cloth->edgeset) { | ||||
| BLI_edgeset_free(cloth->edgeset); | BLI_edgeset_free(cloth->edgeset); | ||||
| cloth->edgeset = NULL; | cloth->edgeset = nullptr; | ||||
| } | } | ||||
| } | } | ||||
| BLI_INLINE void cloth_bend_poly_dir( | BLI_INLINE void cloth_bend_poly_dir( | ||||
| ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3]) | ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3]) | ||||
| { | { | ||||
| float cent[3] = {0}; | float cent[3] = {0}; | ||||
| float fact = 1.0f / len; | float fact = 1.0f / len; | ||||
| Show All 27 Lines | static float cloth_spring_angle( | ||||
| sin = dot_v3v3(tmp, vec_e); | sin = dot_v3v3(tmp, vec_e); | ||||
| return atan2f(sin, cos); | return atan2f(sin, cos); | ||||
| } | } | ||||
| static void cloth_hair_update_bending_targets(ClothModifierData *clmd) | static void cloth_hair_update_bending_targets(ClothModifierData *clmd) | ||||
| { | { | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| LinkNode *search = NULL; | LinkNode *search = nullptr; | ||||
| float hair_frame[3][3], dir_old[3], dir_new[3]; | float hair_frame[3][3], dir_old[3], dir_new[3]; | ||||
| int prev_mn; /* to find hair chains */ | int prev_mn; /* to find hair chains */ | ||||
| if (!clmd->hairdata) { | if (!clmd->hairdata) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* XXX NOTE: we need to propagate frames from the root up, | /* XXX NOTE: we need to propagate frames from the root up, | ||||
| * but structural hair springs are stored in reverse order. | * but structural hair springs are stored in reverse order. | ||||
| * The bending springs however are then inserted in the same | * The bending springs however are then inserted in the same | ||||
| * order as vertices again ... | * order as vertices again ... | ||||
| * This messy situation can be resolved when solver data is | * This messy situation can be resolved when solver data is | ||||
| * generated directly from a dedicated hair system. | * generated directly from a dedicated hair system. | ||||
| */ | */ | ||||
| prev_mn = -1; | prev_mn = -1; | ||||
| for (search = cloth->springs; search; search = search->next) { | for (search = cloth->springs; search; search = search->next) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| ClothHairData *hair_ij, *hair_kl; | ClothHairData *hair_ij, *hair_kl; | ||||
| bool is_root = spring->kl != prev_mn; | bool is_root = spring->kl != prev_mn; | ||||
| if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { | if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| hair_ij = &clmd->hairdata[spring->ij]; | hair_ij = &clmd->hairdata[spring->ij]; | ||||
| Show All 23 Lines | for (search = cloth->springs; search; search = search->next) { | ||||
| prev_mn = spring->mn; | prev_mn = spring->mn; | ||||
| } | } | ||||
| } | } | ||||
| static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd) | static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd) | ||||
| { | { | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| LinkNode *search = NULL; | LinkNode *search = nullptr; | ||||
| float hair_frame[3][3], dir_old[3], dir_new[3]; | float hair_frame[3][3], dir_old[3], dir_new[3]; | ||||
| int prev_mn; /* to find hair roots */ | int prev_mn; /* to find hair roots */ | ||||
| if (!clmd->hairdata) { | if (!clmd->hairdata) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* XXX NOTE: we need to propagate frames from the root up, | /* XXX NOTE: we need to propagate frames from the root up, | ||||
| * but structural hair springs are stored in reverse order. | * but structural hair springs are stored in reverse order. | ||||
| * The bending springs however are then inserted in the same | * The bending springs however are then inserted in the same | ||||
| * order as vertices again ... | * order as vertices again ... | ||||
| * This messy situation can be resolved when solver data is | * This messy situation can be resolved when solver data is | ||||
| * generated directly from a dedicated hair system. | * generated directly from a dedicated hair system. | ||||
| */ | */ | ||||
| prev_mn = -1; | prev_mn = -1; | ||||
| for (search = cloth->springs; search; search = search->next) { | for (search = cloth->springs; search; search = search->next) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| ClothHairData *hair_ij, *hair_kl; | ClothHairData *hair_ij, *hair_kl; | ||||
| bool is_root = spring->kl != prev_mn; | bool is_root = spring->kl != prev_mn; | ||||
| if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { | if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| hair_ij = &clmd->hairdata[spring->ij]; | hair_ij = &clmd->hairdata[spring->ij]; | ||||
| Show All 21 Lines | for (search = cloth->springs; search; search = search->next) { | ||||
| prev_mn = spring->mn; | prev_mn = spring->mn; | ||||
| } | } | ||||
| } | } | ||||
| /* update stiffness if vertex group values are changing from frame to frame */ | /* update stiffness if vertex group values are changing from frame to frame */ | ||||
| static void cloth_update_springs(ClothModifierData *clmd) | static void cloth_update_springs(ClothModifierData *clmd) | ||||
| { | { | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| LinkNode *search = NULL; | LinkNode *search = nullptr; | ||||
| search = cloth->springs; | search = cloth->springs; | ||||
| while (search) { | while (search) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| spring->lin_stiffness = 0.0f; | spring->lin_stiffness = 0.0f; | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| if (spring->type & CLOTH_SPRING_TYPE_BENDING) { | if (spring->type & CLOTH_SPRING_TYPE_BENDING) { | ||||
| spring->ang_stiffness = (cloth->verts[spring->kl].bend_stiff + | spring->ang_stiffness = (cloth->verts[spring->kl].bend_stiff + | ||||
| cloth->verts[spring->ij].bend_stiff) / | cloth->verts[spring->ij].bend_stiff) / | ||||
| 2.0f; | 2.0f; | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh) | ||||
| clmd->sim_parms->avg_spring_len = 0.0f; | clmd->sim_parms->avg_spring_len = 0.0f; | ||||
| for (i = 0; i < mvert_num; i++) { | for (i = 0; i < mvert_num; i++) { | ||||
| cloth->verts[i].avg_spring_len = 0.0f; | cloth->verts[i].avg_spring_len = 0.0f; | ||||
| } | } | ||||
| while (search) { | while (search) { | ||||
| ClothSpring *spring = search->link; | ClothSpring *spring = static_cast<ClothSpring *>(search->link); | ||||
| if (spring->type != CLOTH_SPRING_TYPE_SEWING) { | if (spring->type != CLOTH_SPRING_TYPE_SEWING) { | ||||
| if (spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | | if (spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | | ||||
| CLOTH_SPRING_TYPE_BENDING | CLOTH_SPRING_TYPE_INTERNAL)) { | CLOTH_SPRING_TYPE_BENDING | CLOTH_SPRING_TYPE_INTERNAL)) { | ||||
| shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); | shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); | ||||
| } | } | ||||
| else { | else { | ||||
| shrink_factor = 1.0f; | shrink_factor = 1.0f; | ||||
| Show All 20 Lines | static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh) | ||||
| if (struct_springs > 0) { | if (struct_springs > 0) { | ||||
| clmd->sim_parms->avg_spring_len /= struct_springs; | clmd->sim_parms->avg_spring_len /= struct_springs; | ||||
| } | } | ||||
| for (i = 0; i < mvert_num; i++) { | for (i = 0; i < mvert_num; i++) { | ||||
| if (cloth->verts[i].spring_count > 0) { | if (cloth->verts[i].spring_count > 0) { | ||||
| cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / | cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / | ||||
| ((float)cloth->verts[i].spring_count); | float(cloth->verts[i].spring_count); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3]) | BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3]) | ||||
| { | { | ||||
| zero_m3(r); | zero_m3(r); | ||||
| r[0][1] = v[2]; | r[0][1] = v[2]; | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, | ||||
| /* Bending specific properties. */ | /* Bending specific properties. */ | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| spring->type |= CLOTH_SPRING_TYPE_BENDING; | spring->type |= CLOTH_SPRING_TYPE_BENDING; | ||||
| spring->la = k - j + 1; | spring->la = k - j + 1; | ||||
| spring->lb = mpoly[i].totloop - k + j + 1; | spring->lb = mpoly[i].totloop - k + j + 1; | ||||
| spring->pa = MEM_mallocN(sizeof(*spring->pa) * spring->la, "spring poly"); | spring->pa = static_cast<int *>(MEM_mallocN(sizeof(*spring->pa) * spring->la, "spring poly")); | ||||
| if (!spring->pa) { | if (!spring->pa) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| spring->pb = 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_loop = mloop + 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_loop[j + x].v; | ||||
| Show All 19 Lines | static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, | ||||
| 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 MLoop *mloop) | ||||
| { | { | ||||
| int *p = 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++, mloop++) { | ||||
| p[i] = mloop->v; | p[i] = mloop->v; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, | ||||
| 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 MLoop *mloop = treedata->loop; | ||||
| const MLoopTri *lt = NULL; | 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; | ||||
| Show All 18 Lines | static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) | static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) | ||||
| { | { | ||||
| Cloth *cloth = clmd->clothObject; | Cloth *cloth = clmd->clothObject; | ||||
| ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; | 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 MLoop *mloop = BKE_mesh_loops(mesh); | ||||
| int index2 = 0; /* our second vertex index */ | int index2 = 0; /* our second vertex index */ | ||||
| LinkNodePair *edgelist = NULL; | LinkNodePair *edgelist = nullptr; | ||||
| EdgeSet *edgeset = NULL; | EdgeSet *edgeset = nullptr; | ||||
| LinkNode *search = NULL, *search2 = NULL; | LinkNode *search = nullptr, *search2 = nullptr; | ||||
| BendSpringRef *spring_ref = NULL; | BendSpringRef *spring_ref = nullptr; | ||||
| /* error handling */ | /* error handling */ | ||||
| if (numedges == 0) { | if (numedges == 0) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* NOTE: handling ownership of springs and edgeset is quite sloppy | /* NOTE: handling ownership of springs and edgeset is quite sloppy | ||||
| * currently they are never initialized but assert just to be sure */ | * currently they are never initialized but assert just to be sure */ | ||||
| BLI_assert(cloth->springs == NULL); | BLI_assert(cloth->springs == nullptr); | ||||
| BLI_assert(cloth->edgeset == NULL); | BLI_assert(cloth->edgeset == nullptr); | ||||
| cloth->springs = NULL; | cloth->springs = nullptr; | ||||
| cloth->edgeset = NULL; | cloth->edgeset = nullptr; | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { | ||||
| spring_ref = MEM_callocN(sizeof(*spring_ref) * numedges, "temp bend spring reference"); | spring_ref = static_cast<BendSpringRef *>( | ||||
| MEM_callocN(sizeof(*spring_ref) * numedges, __func__)); | |||||
| if (!spring_ref) { | if (!spring_ref) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| edgelist = MEM_callocN(sizeof(*edgelist) * mvert_num, "cloth_edgelist_alloc"); | edgelist = static_cast<LinkNodePair *>(MEM_callocN(sizeof(*edgelist) * mvert_num, __func__)); | ||||
| if (!edgelist) { | if (!edgelist) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS); | bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS); | ||||
| if (use_internal_springs && numpolys > 0) { | if (use_internal_springs && numpolys > 0) { | ||||
| BVHTreeFromMesh treedata = {NULL}; | BVHTreeFromMesh treedata = {nullptr}; | ||||
| uint tar_v_idx; | uint tar_v_idx; | ||||
| Mesh *tmp_mesh = NULL; | Mesh *tmp_mesh = nullptr; | ||||
| RNG *rng; | RNG *rng; | ||||
| /* If using the rest shape key, it's necessary to make a copy of the mesh. */ | /* If using the rest shape key, it's necessary to make a copy of the mesh. */ | ||||
| if (clmd->sim_parms->shapekey_rest && | if (clmd->sim_parms->shapekey_rest && | ||||
| !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) { | !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) { | ||||
| tmp_mesh = cloth_make_rest_mesh(clmd, mesh); | tmp_mesh = cloth_make_rest_mesh(clmd, mesh); | ||||
| } | } | ||||
| Show All 39 Lines | for (int i = 0; i < mvert_num; i++) { | ||||
| spring_ref[i].spring = spring; | spring_ref[i].spring = spring; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| BLI_edgeset_free(existing_vert_pairs); | BLI_edgeset_free(existing_vert_pairs); | ||||
| free_bvhtree_from_mesh(&treedata); | free_bvhtree_from_mesh(&treedata); | ||||
| if (tmp_mesh) { | if (tmp_mesh) { | ||||
| BKE_id_free(NULL, &tmp_mesh->id); | BKE_id_free(nullptr, &tmp_mesh->id); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_edgeset_free(existing_vert_pairs); | BLI_edgeset_free(existing_vert_pairs); | ||||
| free_bvhtree_from_mesh(&treedata); | free_bvhtree_from_mesh(&treedata); | ||||
| if (tmp_mesh) { | if (tmp_mesh) { | ||||
| BKE_id_free(NULL, &tmp_mesh->id); | BKE_id_free(nullptr, &tmp_mesh->id); | ||||
| } | } | ||||
| BLI_rng_free(rng); | BLI_rng_free(rng); | ||||
| } | } | ||||
| clmd->sim_parms->avg_spring_len = 0.0f; | clmd->sim_parms->avg_spring_len = 0.0f; | ||||
| for (int i = 0; i < mvert_num; i++) { | for (int i = 0; i < mvert_num; i++) { | ||||
| cloth->verts[i].avg_spring_len = 0.0f; | cloth->verts[i].avg_spring_len = 0.0f; | ||||
| } | } | ||||
| if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW) { | if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW) { | ||||
| /* cloth->sew_edge_graph should not exist before this */ | /* cloth->sew_edge_graph should not exist before this */ | ||||
| BLI_assert(cloth->sew_edge_graph == NULL); | BLI_assert(cloth->sew_edge_graph == nullptr); | ||||
| cloth->sew_edge_graph = BLI_edgeset_new("cloth_sewing_edges_graph"); | cloth->sew_edge_graph = BLI_edgeset_new("cloth_sewing_edges_graph"); | ||||
| } | } | ||||
| /* Structural springs. */ | /* Structural springs. */ | ||||
| for (int i = 0; i < numedges; i++) { | for (int i = 0; i < numedges; i++) { | ||||
| spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | ||||
| if (spring) { | if (spring) { | ||||
| ▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | for (int i = 0; i < numpolys; i++) { | ||||
| } | } | ||||
| /* Third poly found for this edge, remove bending data. */ | /* Third poly found for this edge, remove bending data. */ | ||||
| else if (curr_ref->polys == 3) { | else if (curr_ref->polys == 3) { | ||||
| spring = curr_ref->spring; | spring = curr_ref->spring; | ||||
| spring->type &= ~CLOTH_SPRING_TYPE_BENDING; | spring->type &= ~CLOTH_SPRING_TYPE_BENDING; | ||||
| MEM_freeN(spring->pa); | MEM_freeN(spring->pa); | ||||
| MEM_freeN(spring->pb); | MEM_freeN(spring->pb); | ||||
| spring->pa = NULL; | spring->pa = nullptr; | ||||
| spring->pb = NULL; | spring->pb = nullptr; | ||||
| bend_springs--; | bend_springs--; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Linear bending springs. */ | /* Linear bending springs. */ | ||||
| if (clmd->sim_parms->bending_model == CLOTH_BENDING_LINEAR) { | if (clmd->sim_parms->bending_model == CLOTH_BENDING_LINEAR) { | ||||
| search2 = cloth->springs; | search2 = cloth->springs; | ||||
| for (int i = struct_springs; i < struct_springs + shear_springs; i++) { | for (int i = struct_springs; i < struct_springs + shear_springs; i++) { | ||||
| if (!search2) { | if (!search2) { | ||||
| break; | break; | ||||
| } | } | ||||
| tspring2 = search2->link; | tspring2 = static_cast<ClothSpring *>(search2->link); | ||||
| search = edgelist[tspring2->kl].list; | search = edgelist[tspring2->kl].list; | ||||
| while (search) { | while (search) { | ||||
| tspring = search->link; | tspring = static_cast<ClothSpring *>(search->link); | ||||
| index2 = ((tspring->ij == tspring2->kl) ? (tspring->kl) : (tspring->ij)); | index2 = ((tspring->ij == tspring2->kl) ? (tspring->kl) : (tspring->ij)); | ||||
| /* Check for existing spring. */ | /* Check for existing spring. */ | ||||
| /* Check also if startpoint is equal to endpoint. */ | /* Check also if startpoint is equal to endpoint. */ | ||||
| if ((index2 != tspring2->ij) && !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) { | if ((index2 != tspring2->ij) && !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) { | ||||
| spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | ||||
| if (!spring) { | if (!spring) { | ||||
| Show All 23 Lines | if (clmd->sim_parms->bending_model == CLOTH_BENDING_LINEAR) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (struct_springs > 2) { | else if (struct_springs > 2) { | ||||
| if (G.debug_value != 1112) { | if (G.debug_value != 1112) { | ||||
| search = cloth->springs; | search = cloth->springs; | ||||
| search2 = search->next; | search2 = search->next; | ||||
| while (search && search2) { | while (search && search2) { | ||||
| tspring = search->link; | tspring = static_cast<ClothSpring *>(search->link); | ||||
| tspring2 = search2->link; | tspring2 = static_cast<ClothSpring *>(search2->link); | ||||
| if (tspring->ij == tspring2->kl) { | if (tspring->ij == tspring2->kl) { | ||||
| spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | ||||
| if (!spring) { | if (!spring) { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| return false; | return false; | ||||
| } | } | ||||
| Show All 22 Lines | else { | ||||
| * and makes springs between the outer vert of edges sharing a vertex. This works just | * and makes springs between the outer vert of edges sharing a vertex. This works just | ||||
| * fine for hair, but not for user generated string meshes. This could/should be later | * fine for hair, but not for user generated string meshes. This could/should be later | ||||
| * extended to work with non-ordered edges so that it can be used for general "rope | * extended to work with non-ordered edges so that it can be used for general "rope | ||||
| * dynamics" without the need for the vertices or edges to be ordered through the length | * dynamics" without the need for the vertices or edges to be ordered through the length | ||||
| * of the strands. -jahka */ | * of the strands. -jahka */ | ||||
| search = cloth->springs; | search = cloth->springs; | ||||
| search2 = search->next; | search2 = search->next; | ||||
| while (search && search2) { | while (search && search2) { | ||||
| tspring = search->link; | tspring = static_cast<ClothSpring *>(search->link); | ||||
| tspring2 = search2->link; | tspring2 = static_cast<ClothSpring *>(search2->link); | ||||
| if (tspring->ij == tspring2->kl) { | if (tspring->ij == tspring2->kl) { | ||||
| spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); | ||||
| if (!spring) { | if (!spring) { | ||||
| cloth_free_errorsprings(cloth, edgelist, spring_ref); | cloth_free_errorsprings(cloth, edgelist, spring_ref); | ||||
| return false; | return false; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines | |||||