Compare commits
109 Commits
tmp_libs_3
...
cloth-impr
Author | SHA1 | Date | |
---|---|---|---|
ceddd2bcd9 | |||
f47ace53f2 | |||
7eb44c2f1b | |||
13818c47cf | |||
d7f5520fdf | |||
bbf2f3ac2a | |||
320771dc74 | |||
607a2d80d3 | |||
bc738592df | |||
6b818dcf79 | |||
102b2a7418 | |||
5d07a070cb | |||
87825084d5 | |||
d6a6417e3b | |||
03412896f6 | |||
87625ccce9 | |||
666a9385c4 | |||
6249fb68e0 | |||
6edd60d959 | |||
fe9debc47b | |||
84213a3ce1 | |||
3f0b3a4fb0 | |||
5ad6bdb021 | |||
d6bee4bffd | |||
b034660643 | |||
dbb20c3913 | |||
5315339162 | |||
7fa9ab01d6 | |||
c6f05db912 | |||
a87cd01425 | |||
77df327fa8 | |||
0607cd2e15 | |||
9f0176d795 | |||
215df08c0f | |||
7b6d09e9bd | |||
5e28df26de | |||
e3b5229da2 | |||
bc3b482b9d | |||
6f9cddec21 | |||
1cc8f2d79b | |||
fdea8ecb5b | |||
06090d7a31 | |||
8d1b6b76a2 | |||
a32251b4ed | |||
4e42d01c65 | |||
ade28fe8a2 | |||
115aea5f2f | |||
5de2fc2679 | |||
e735eda393 | |||
6054fff2a6 | |||
7d99e1418b | |||
983d671df8 | |||
0018eae5ed | |||
add9835df6 | |||
309b12ac27 | |||
0f5dc7ad80 | |||
82d3cd586c | |||
73b9899c92 | |||
b2dc669ee7 | |||
8d454ff13a | |||
998900794d | |||
61f8a1cfd7 | |||
403b835992 | |||
8759ec4eae | |||
80ed76cb66 | |||
2d48769a8b | |||
c8d1bbf31c | |||
d4a46809d0 | |||
9596871292 | |||
22f67557d1 | |||
63f023111d | |||
66d19ebeb3 | |||
69e8ee7851 | |||
5aacca55fa | |||
a6c0ab8cb5 | |||
fb542eadd4 | |||
f30048504b | |||
e3df66f1b7 | |||
d1b25a08d7 | |||
3fb5d20cc0 | |||
63aaa7c84a | |||
929aa7c046 | |||
55b9eebede | |||
887dfc298d | |||
a2dbe9f340 | |||
81a8a015b8 | |||
4cbb4bc6be | |||
85af281f85 | |||
d12c650349 | |||
bb32d9240f | |||
eca3877ac4 | |||
e843c10ad5 | |||
dc526671c7 | |||
1d8a08fb9f | |||
54186c5aa9 | |||
f9dad94d9e | |||
8a0d8ddf27 | |||
cb4d349803 | |||
ce6227b6be | |||
04e157e44a | |||
5d2a092f40 | |||
73fd331025 | |||
56c21ff707 | |||
c03db4c501 | |||
fa5669164b | |||
5721918848 | |||
dc6fd8a257 | |||
fe5735c6cf | |||
97b232ec70 |
Submodule release/datafiles/locale updated: d3349b4285...2b3c19f5f6
Submodule release/scripts/addons updated: 9ae033c49c...51e18ead5d
Submodule release/scripts/addons_contrib updated: f178e6c933...a52733b58d
@@ -68,9 +68,14 @@ class MESH_UL_vgroups(UIList):
|
||||
# assert(isinstance(item, bpy.types.VertexGroup))
|
||||
vgroup = item
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
|
||||
split = layout.split(0.66, False)
|
||||
split.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
row = split.row(align=True)
|
||||
row.prop(vgroup, "influence", text="", emboss=False)
|
||||
|
||||
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
|
||||
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
|
||||
row.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
@@ -227,6 +232,11 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
|
||||
|
||||
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
|
||||
|
||||
if group:
|
||||
row = layout.row()
|
||||
row.active = ob.mode != 'EDIT'
|
||||
row.prop(group, "influence")
|
||||
|
||||
|
||||
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
|
||||
bl_label = "Shape Keys"
|
||||
|
@@ -62,7 +62,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
|
||||
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
split = layout.split(percentage=0.25)
|
||||
split = layout.split(percentage=0.3)
|
||||
|
||||
split.label(text="Presets:")
|
||||
sub = split.row(align=True)
|
||||
@@ -70,41 +70,87 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
|
||||
sub.operator("cloth.preset_add", text="", icon='ZOOMIN')
|
||||
sub.operator("cloth.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
split = layout.split(percentage=0.25)
|
||||
col = layout.column()
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label(text="Quality:")
|
||||
split.prop(cloth, "quality", text="Steps")
|
||||
|
||||
split = layout.split(percentage=0.25)
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label(text="Speed:")
|
||||
split.prop(cloth, "time_scale", text="Multiplier")
|
||||
|
||||
split = layout.split()
|
||||
layout.separator()
|
||||
|
||||
col = split.column()
|
||||
layout.label("Material Properties:")
|
||||
|
||||
col.label(text="Material:")
|
||||
col.prop(cloth, "mass")
|
||||
col.prop(cloth, "structural_stiffness", text="Structural")
|
||||
col.prop(cloth, "bending_stiffness", text="Bending")
|
||||
col = layout.column()
|
||||
|
||||
col = split.column()
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Mass:")
|
||||
split.prop(cloth, "mass", text="")
|
||||
|
||||
col.label(text="Damping:")
|
||||
col.prop(cloth, "spring_damping", text="Spring")
|
||||
col.prop(cloth, "air_damping", text="Air")
|
||||
col.prop(cloth, "vel_damping", text="Velocity")
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Air Viscosity:")
|
||||
split.prop(cloth, "air_damping", text="")
|
||||
|
||||
split = layout.split()
|
||||
col = layout.column()
|
||||
|
||||
col = split.column()
|
||||
split = col.split(percentage=0.3)
|
||||
split.separator()
|
||||
|
||||
col.prop(cloth, "use_pin_cloth", text="Pinning:")
|
||||
sub = col.column()
|
||||
sub.active = cloth.use_pin_cloth
|
||||
sub.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="")
|
||||
sub.prop(cloth, "pin_stiffness", text="Stiffness")
|
||||
row = split.row(align=True)
|
||||
row.label("Stiffness:")
|
||||
row.label("Damping:")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Tension:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "tension_stiffness", text="")
|
||||
row.prop(cloth, "tension_damping", text="")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Compression:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "compression_stiffness", text="")
|
||||
row.prop(cloth, "compression_damping", text="")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Shear:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "shear_stiffness", text="")
|
||||
row.prop(cloth, "shear_damping", text="")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Bending:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "bending_stiffness", text="")
|
||||
row.prop(cloth, "bending_damping", text="")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.separator()
|
||||
|
||||
row = split.row(align=True)
|
||||
row.label("Plasticity:")
|
||||
row.label("Threshold:")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Structural:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "structural_plasticity", text="")
|
||||
row.prop(cloth, "structural_yield_factor", text="")
|
||||
|
||||
split = col.split(percentage=0.3)
|
||||
split.label("Bending:")
|
||||
row = split.row(align=True)
|
||||
row.prop(cloth, "bending_plasticity", text="")
|
||||
row.prop(cloth, "bending_yield_factor", text="")
|
||||
|
||||
layout.separator()
|
||||
layout.prop(cloth, "use_initial_velocity")
|
||||
|
||||
layout.separator()
|
||||
layout.prop_search(cloth, "vertex_group_trouble", ob, "vertex_groups")
|
||||
|
||||
# Disabled for now
|
||||
"""
|
||||
@@ -117,18 +163,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
|
||||
col.prop(cloth, "goal_friction", text="Friction")
|
||||
"""
|
||||
|
||||
col = split.column()
|
||||
|
||||
col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
|
||||
|
||||
key = ob.data.shape_keys
|
||||
|
||||
if key:
|
||||
sub = col.column()
|
||||
sub.active = not cloth.use_dynamic_mesh
|
||||
sub.label(text="Rest Shape Key:")
|
||||
sub.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Cache"
|
||||
@@ -140,17 +174,68 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
|
||||
point_cache_ui(self, context, md.point_cache, cloth_panel_enabled(md), 'CLOTH')
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_shape(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Shape"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
md = context.cloth
|
||||
ob = context.object
|
||||
cloth = context.cloth.settings
|
||||
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
col = layout.column()
|
||||
split = col.split(percentage=0.3, align=True)
|
||||
|
||||
split.label("Pinning:")
|
||||
|
||||
sub1 = split.row(align=True)
|
||||
sub1.active = not cloth.use_combined_pin_cloth
|
||||
|
||||
sub1.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="")
|
||||
|
||||
sub2 = sub1.row(align=True)
|
||||
sub2.active = cloth.vertex_group_mass != ""
|
||||
sub2.prop(cloth, "pin_stiffness", text="Stiffness")
|
||||
|
||||
col.prop(cloth, "use_combined_pin_cloth")
|
||||
|
||||
layout.separator()
|
||||
|
||||
split = layout.split(percentage=0.3)
|
||||
split.prop(cloth, "use_sewing_springs", text="Sewing:")
|
||||
|
||||
sub = split.column()
|
||||
sub.active = cloth.use_sewing_springs
|
||||
sub.prop(cloth, "sewing_force_max", text="Sewing Force")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(cloth, "shrinking", text="Shrinking")
|
||||
row.prop(cloth, "rest_planarity_factor", text="Flattening")
|
||||
|
||||
row = layout.row()
|
||||
sub = row.column()
|
||||
sub.alert = not cloth.is_basemesh_target_valid
|
||||
sub.prop(cloth, "basemesh_target")
|
||||
row.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
|
||||
|
||||
key = ob.data.shape_keys
|
||||
|
||||
if key:
|
||||
sub = layout.column()
|
||||
sub.active = (not cloth.use_dynamic_mesh) and (cloth.basemesh_target is None)
|
||||
sub.prop_search(cloth, "rest_shape_key", key, "key_blocks")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Collision"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
def draw_header(self, context):
|
||||
cloth = context.cloth.collision_settings
|
||||
|
||||
self.layout.active = cloth_panel_enabled(context.cloth)
|
||||
self.layout.prop(cloth, "use_collision", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -158,39 +243,55 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
|
||||
md = context.cloth
|
||||
ob = context.object
|
||||
|
||||
layout.active = cloth.use_collision and cloth_panel_enabled(md)
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
split = layout.split()
|
||||
layout.prop(cloth, "collision_quality")
|
||||
|
||||
col = split.column()
|
||||
col.prop(cloth, "collision_quality", text="Quality")
|
||||
col.prop(cloth, "distance_min", slider=True, text="Distance")
|
||||
col.prop(cloth, "repel_force", slider=True, text="Repel")
|
||||
col.prop(cloth, "distance_repel", slider=True, text="Repel Distance")
|
||||
col.prop(cloth, "friction")
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
|
||||
split = col.split()
|
||||
|
||||
sub = split.column()
|
||||
sub.prop(cloth, "use_collision", text="Object Collision:")
|
||||
|
||||
sub = split.column()
|
||||
sub.active = cloth.use_collision
|
||||
sub.prop(cloth, "collision_response_quality")
|
||||
|
||||
sub = col.column()
|
||||
sub.active = cloth.use_collision
|
||||
sub.prop(cloth, "distance_min", slider=True, text="Distance")
|
||||
sub.prop(cloth, "impulse_clamp")
|
||||
sub.prop(cloth, "group")
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
|
||||
split = col.split()
|
||||
|
||||
sub = split.column()
|
||||
sub.prop(cloth, "use_self_collision", text="Self Collision:")
|
||||
|
||||
sub = split.column()
|
||||
sub.active = cloth.use_self_collision
|
||||
sub.prop(cloth, "selfcollision_response_quality")
|
||||
|
||||
col = split.column()
|
||||
col.prop(cloth, "use_self_collision", text="Self Collision")
|
||||
sub = col.column()
|
||||
sub.active = cloth.use_self_collision
|
||||
sub.prop(cloth, "self_collision_quality", text="Quality")
|
||||
sub.prop(cloth, "self_friction", text="Friction")
|
||||
sub.prop(cloth, "self_distance_min", slider=True, text="Distance")
|
||||
sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="")
|
||||
|
||||
layout.prop(cloth, "group")
|
||||
sub.prop(cloth, "self_impulse_clamp")
|
||||
sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="Vertex Group")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Stiffness Scaling"
|
||||
class PHYSICS_PT_cloth_scaling(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Property Scaling"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
def draw_header(self, context):
|
||||
cloth = context.cloth.settings
|
||||
|
||||
self.layout.active = cloth_panel_enabled(context.cloth)
|
||||
self.layout.prop(cloth, "use_stiffness_scale", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -198,53 +299,89 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
|
||||
ob = context.object
|
||||
cloth = context.cloth.settings
|
||||
|
||||
layout.active = (cloth.use_stiffness_scale and cloth_panel_enabled(md))
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
split = layout.split()
|
||||
row = layout.row()
|
||||
|
||||
col = split.column()
|
||||
col = row.column(align=True)
|
||||
col.label(text="Structural Stiffness:")
|
||||
col.label(text="Tension:")
|
||||
col.label(text="Compression:")
|
||||
|
||||
col = row.column(align=True)
|
||||
col.prop_search(cloth, "vertex_group_structural_stiffness", ob, "vertex_groups", text="")
|
||||
col.prop(cloth, "structural_stiffness_max", text="Max")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Bending Stiffness:")
|
||||
col.prop_search(cloth, "vertex_group_bending", ob, "vertex_groups", text="")
|
||||
col.prop(cloth, "bending_stiffness_max", text="Max")
|
||||
sub = col.column(align=True)
|
||||
sub.active = cloth.vertex_group_structural_stiffness != ""
|
||||
sub.prop(cloth, "tension_stiffness_max", text="Max")
|
||||
sub.prop(cloth, "compression_stiffness_max", text="Max")
|
||||
|
||||
split = layout.split(percentage=0.25, align=True)
|
||||
split.label(text="Shear:")
|
||||
split.prop_search(cloth, "vertex_group_shear_stiffness", ob, "vertex_groups", text="")
|
||||
|
||||
sub = split.row(align=True)
|
||||
sub.active = cloth.vertex_group_shear_stiffness != ""
|
||||
sub.prop(cloth, "shear_stiffness_max", text="Max")
|
||||
|
||||
split = layout.split(percentage=0.25, align=True)
|
||||
split.label("Bending:")
|
||||
split.prop_search(cloth, "vertex_group_bending", ob, "vertex_groups", text="")
|
||||
|
||||
sub = split.row(align=True)
|
||||
sub.active = cloth.vertex_group_bending != ""
|
||||
sub.prop(cloth, "bending_stiffness_max", text="Max")
|
||||
|
||||
split = layout.split(percentage=0.25, align=True)
|
||||
split.label("Shrinking:")
|
||||
split.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="")
|
||||
|
||||
sub = split.row(align=True)
|
||||
sub.active = cloth.vertex_group_shrink != ""
|
||||
sub.prop(cloth, "shrinking_max", text="Max")
|
||||
|
||||
split = layout.split(percentage=0.25, align=True)
|
||||
split.label("Flattening:")
|
||||
split.prop_search(cloth, "vertex_group_planarity", ob, "vertex_groups", text="")
|
||||
|
||||
sub = split.row(align=True)
|
||||
sub.active = cloth.vertex_group_planarity != ""
|
||||
sub.prop(cloth, "planarity_factor_max", text="Max")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Sewing Springs"
|
||||
class PHYSICS_PT_cloth_adaptive_subframes(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cloth Adaptive Subframes"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
||||
def draw_header(self, context):
|
||||
cloth = context.cloth.settings
|
||||
|
||||
self.layout.active = cloth_panel_enabled(context.cloth)
|
||||
self.layout.prop(cloth, "use_sewing_springs", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
md = context.cloth
|
||||
ob = context.object
|
||||
cloth = context.cloth.settings
|
||||
|
||||
layout.active = (cloth.use_sewing_springs and cloth_panel_enabled(md))
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
layout.prop(cloth, "sewing_force_max", text="Sewing Force")
|
||||
layout.prop(cloth, "max_sub_steps")
|
||||
layout.separator()
|
||||
|
||||
split = layout.split()
|
||||
layout.prop(cloth, "use_adaptive_subframes")
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label(text="Shrinking:")
|
||||
col.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="")
|
||||
col = layout.column()
|
||||
col.active = cloth.use_adaptive_subframes
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label()
|
||||
col.prop(cloth, "shrink_min", text="Min")
|
||||
col.prop(cloth, "shrink_max", text="Max")
|
||||
col.prop(cloth, "max_velocity")
|
||||
col.prop(cloth, "adjustment_factor")
|
||||
|
||||
layout.prop(cloth, "use_impulse_adaptive_subframes")
|
||||
|
||||
col = layout.column()
|
||||
col.active = cloth.use_impulse_adaptive_subframes
|
||||
|
||||
col.prop(cloth, "max_impulse")
|
||||
col.prop(cloth, "impulse_adjustment_factor")
|
||||
|
||||
layout.prop(cloth, "compensate_instability")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
|
||||
@@ -261,9 +398,10 @@ classes = (
|
||||
CLOTH_MT_presets,
|
||||
PHYSICS_PT_cloth,
|
||||
PHYSICS_PT_cloth_cache,
|
||||
PHYSICS_PT_cloth_shape,
|
||||
PHYSICS_PT_cloth_collision,
|
||||
PHYSICS_PT_cloth_stiffness,
|
||||
PHYSICS_PT_cloth_sewing,
|
||||
PHYSICS_PT_cloth_scaling,
|
||||
PHYSICS_PT_cloth_adaptive_subframes,
|
||||
PHYSICS_PT_cloth_field_weights,
|
||||
)
|
||||
|
||||
|
@@ -222,6 +222,11 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
|
||||
sub.prop(settings, "thickness_outer", text="Outer", slider=True)
|
||||
sub.prop(settings, "thickness_inner", text="Inner", slider=True)
|
||||
|
||||
col.prop(settings, "use_culling")
|
||||
col.prop(settings, "use_normal")
|
||||
|
||||
col.prop(settings, "cloth_friction")
|
||||
|
||||
col.label(text="Soft Body Damping:")
|
||||
col.prop(settings, "damping", text="Factor", slider=True)
|
||||
|
||||
|
@@ -96,8 +96,9 @@ typedef struct Cloth {
|
||||
struct BVHTree *bvhselftree; /* collision tree for this cloth object */
|
||||
struct MVertTri *tri;
|
||||
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
|
||||
struct EdgeSet *edgeset; /* used for selfcollisions */
|
||||
int last_frame, pad4;
|
||||
int last_frame;
|
||||
float adapt_fact; /* Stability dt compensation factor */
|
||||
float max_col_trouble;
|
||||
} Cloth;
|
||||
|
||||
/**
|
||||
@@ -112,17 +113,21 @@ typedef struct ClothVertex {
|
||||
float tx[3]; /* temporary position */
|
||||
float txold[3]; /* temporary old position */
|
||||
float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */
|
||||
float tvold[3];
|
||||
float mass; /* mass / weight of the vertex */
|
||||
float goal; /* goal, from SB */
|
||||
float impulse[3]; /* used in collision.c */
|
||||
float xrest[3]; /* rest position of the vertex */
|
||||
float dcvel[3]; /* delta velocities to be applied by collision responce */
|
||||
unsigned int impulse_count; /* same as above */
|
||||
float avg_spring_len; /* average length of connected springs */
|
||||
float struct_stiff;
|
||||
float bend_stiff;
|
||||
float shear_stiff;
|
||||
float planarity;
|
||||
int spring_count; /* how many springs attached? */
|
||||
float shrink_factor; /* how much to shrink this cloth */
|
||||
float col_trouble;
|
||||
}
|
||||
ClothVertex;
|
||||
|
||||
@@ -132,17 +137,24 @@ ClothVertex;
|
||||
typedef struct ClothSpring {
|
||||
int ij; /* Pij from the paper, one end of the spring. */
|
||||
int kl; /* Pkl from the paper, one end of the spring. */
|
||||
int mn;
|
||||
float restlen; /* The original length of the spring. */
|
||||
int mn; /* For hair springs: third vertex index; For bending springs: edge index */
|
||||
int *pa; /* array of vert indices for poly a (for bending springs) */
|
||||
int *pb; /* array of vert indices for poly b (for bending springs) */
|
||||
int la; /* length of *pa */
|
||||
int lb; /* length of *pb */
|
||||
float restlen; /* The original length of the spring */
|
||||
float restang; /* The original angle of the bending springs */
|
||||
float lenfact; /* Factor of restlen used for plasticity */
|
||||
float angoffset; /* Offset of restang used for plasticity */
|
||||
int type; /* types defined in BKE_cloth.h ("springType") */
|
||||
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
|
||||
float stiffness; /* stiffness factor from the vertex groups */
|
||||
float editrestlen;
|
||||
float lin_stiffness; /* linear stiffness factor from the vertex groups */
|
||||
float ang_stiffness; /* angular stiffness factor from the vertex groups */
|
||||
float planarity;
|
||||
|
||||
/* angular bending spring target and derivatives */
|
||||
float target[3];
|
||||
}
|
||||
ClothSpring;
|
||||
} ClothSpring;
|
||||
|
||||
// some macro enhancements for vector treatment
|
||||
#define VECADDADD(v1,v2,v3) {*(v1)+= *(v2) + *(v3); *(v1+1)+= *(v2+1) + *(v3+1); *(v1+2)+= *(v2+2) + *(v3+2);}
|
||||
@@ -161,10 +173,13 @@ ClothSpring;
|
||||
/* SIMULATION FLAGS: goal flags,.. */
|
||||
/* These are the bits used in SimSettings.flags. */
|
||||
typedef enum {
|
||||
CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_VEL = (1 << 0), /* use velocity based adaptive subframes*/
|
||||
CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_IMP = (1 << 1), /* use velocity based adaptive subframes*/
|
||||
CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done
|
||||
CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled
|
||||
CLOTH_SIMSETTINGS_FLAG_INIT_VEL = ( 1 << 3 ), /* initialize cloth velocity from animation */
|
||||
CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
|
||||
CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
|
||||
CLOTH_SIMSETTINGS_FLAG_COMB_GOAL = (1 << 5), // combined weights for goal
|
||||
CLOTH_SIMSETTINGS_FLAG_COMPENSATE_INSTABILITY = (1 << 6), /* Compensate instability by increasing subframes */
|
||||
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12), /* edit cache in editmode */
|
||||
CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */
|
||||
CLOTH_SIMSETTINGS_FLAG_SEW = (1 << 14), /* pull ends of loose edges together */
|
||||
@@ -184,7 +199,7 @@ typedef enum {
|
||||
CLOTH_SPRING_TYPE_BENDING = (1 << 3),
|
||||
CLOTH_SPRING_TYPE_GOAL = (1 << 4),
|
||||
CLOTH_SPRING_TYPE_SEWING = (1 << 5),
|
||||
CLOTH_SPRING_TYPE_BENDING_ANG = (1 << 6),
|
||||
CLOTH_SPRING_TYPE_BENDING_HAIR = (1 << 6),
|
||||
} CLOTH_SPRING_TYPES;
|
||||
|
||||
/* SPRING FLAGS */
|
||||
@@ -231,7 +246,7 @@ void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, stru
|
||||
int cloth_uses_vgroup(struct ClothModifierData *clmd);
|
||||
|
||||
// needed for collision.c
|
||||
void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
|
||||
void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving, bool self);
|
||||
void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
|
||||
|
||||
// needed for button_object.c
|
||||
@@ -239,6 +254,8 @@ void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float
|
||||
|
||||
void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
|
||||
|
||||
bool is_basemesh_valid(struct Object *ob, struct Object *basemesh, struct ClothModifierData *clmd);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
@@ -62,6 +62,7 @@ typedef enum {
|
||||
COLLISION_USE_COLLFACE = (1 << 2),
|
||||
COLLISION_IS_EDGES = (1 << 3),
|
||||
#endif
|
||||
COLLISION_INACTIVE = (1 << 4),
|
||||
} COLLISION_FLAGS;
|
||||
|
||||
|
||||
@@ -72,7 +73,7 @@ typedef enum {
|
||||
typedef struct CollPair {
|
||||
unsigned int face1; // cloth face
|
||||
unsigned int face2; // object face
|
||||
double distance; // magnitude of vector
|
||||
float distance;
|
||||
float normal[3];
|
||||
float vector[3]; // unnormalized collision vector: p2-p1
|
||||
float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
|
||||
|
@@ -116,4 +116,12 @@ void BKE_defvert_extract_vgroup_to_polyweights(
|
||||
struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
|
||||
struct MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup);
|
||||
|
||||
float BKE_defvert_combined_weight(const Object *object, const struct MDeformVert *dvert, const int mode);
|
||||
|
||||
/* combined weight mode */
|
||||
enum {
|
||||
DVERT_COMBINED_MODE_ADD = 0,
|
||||
DVERT_COMBINED_MODE_MIX = 1,
|
||||
};
|
||||
|
||||
#endif /* __BKE_DEFORM_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -70,6 +70,8 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
|
||||
|
||||
BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
|
||||
|
||||
defgroup->influence = 0.0f;
|
||||
|
||||
BLI_addtail(&ob->defbase, defgroup);
|
||||
defgroup_unique_name(defgroup, ob);
|
||||
|
||||
@@ -1290,3 +1292,35 @@ bool data_transfer_layersmapping_vgroups(
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/**
|
||||
* \return The interpolated weight of all vertex groups for a given vertex.
|
||||
*/
|
||||
float BKE_defvert_combined_weight(const Object *object, const MDeformVert *dvert, const int mode)
|
||||
{
|
||||
bDeformGroup *dg;
|
||||
float tot_weight = 0;
|
||||
float tot_influence = 0;
|
||||
int i = 0;
|
||||
|
||||
if (mode == DVERT_COMBINED_MODE_ADD) {
|
||||
for (; i < dvert->totweight; i++) {
|
||||
dg = BLI_findlink(&object->defbase, dvert->dw[i].def_nr);
|
||||
tot_weight += dvert->dw[i].weight * dg->influence;
|
||||
}
|
||||
|
||||
return min_ff(tot_weight, 1.0f);
|
||||
}
|
||||
else if (mode == DVERT_COMBINED_MODE_MIX) {
|
||||
for (dg = object->defbase.first; dg; dg = dg->next, i++) {
|
||||
if (dg->influence > 0) {
|
||||
tot_weight += defvert_find_weight(dvert, i) * dg->influence;
|
||||
tot_influence += dg->influence;
|
||||
}
|
||||
}
|
||||
|
||||
return tot_influence > 0 ? tot_weight / tot_influence : 0.0f;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
@@ -106,6 +106,7 @@ PartDeflect *object_add_collision_fields(int type)
|
||||
pd->pdef_sbdamp = 0.1f;
|
||||
pd->pdef_sbift = 0.2f;
|
||||
pd->pdef_sboft = 0.02f;
|
||||
pd->pdef_cfrict = 5.0f;
|
||||
pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128;
|
||||
pd->f_strength = 1.0f;
|
||||
pd->f_damp = 1.0f;
|
||||
@@ -126,7 +127,7 @@ PartDeflect *object_add_collision_fields(int type)
|
||||
pd->f_flow = 1.0f;
|
||||
break;
|
||||
}
|
||||
pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION;
|
||||
pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION|PFIELD_CLOTH_USE_CULLING;
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
@@ -3158,7 +3158,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
|
||||
psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
|
||||
psys->clmd->sim_parms->goalspring = 0.0f;
|
||||
psys->clmd->sim_parms->vel_damping = 1.0f;
|
||||
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
|
||||
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
|
||||
}
|
||||
|
||||
|
@@ -336,6 +336,8 @@ bool clip_segment_v3_plane_n(
|
||||
const float p1[3], const float p2[3], const float plane_array[][4], const int plane_tot,
|
||||
float r_p1[3], float r_p2[3]);
|
||||
|
||||
bool point_in_slice_seg(float p[3], float l1[3], float l2[3]);
|
||||
|
||||
/****************************** Interpolation ********************************/
|
||||
void interp_weights_tri_v3(float w[3], const float a[3], const float b[3], const float c[3], const float p[3]);
|
||||
void interp_weights_quad_v3(float w[4], const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
|
||||
|
@@ -2682,19 +2682,27 @@ static bool point_in_slice(const float p[3], const float v1[3], const float l1[3
|
||||
return (h >= 0.0f && h <= 1.0f);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* adult sister defining the slice planes by the origin and the normal
|
||||
* NOTE |normal| may not be 1 but defining the thickness of the slice */
|
||||
static int point_in_slice_as(float p[3], float origin[3], float normal[3])
|
||||
static bool point_in_slice_as(float p[3], float origin[3], float normal[3])
|
||||
{
|
||||
float h, rp[3];
|
||||
sub_v3_v3v3(rp, p, origin);
|
||||
h = dot_v3v3(normal, rp) / dot_v3v3(normal, normal);
|
||||
if (h < 0.0f || h > 1.0f) return 0;
|
||||
return 1;
|
||||
if (h < 0.0f || h > 1.0f) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool point_in_slice_seg(float p[3], float l1[3], float l2[3])
|
||||
{
|
||||
float normal[3];
|
||||
|
||||
sub_v3_v3v3(normal, l2, l1);
|
||||
|
||||
return point_in_slice_as(p, l1, normal);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*mama (knowing the squared length of the normal) */
|
||||
static int point_in_slice_m(float p[3], float origin[3], float normal[3], float lns)
|
||||
{
|
||||
|
@@ -264,6 +264,7 @@ void ED_vgroup_mirror(struct Object *ob,
|
||||
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
|
||||
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
||||
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
||||
float ED_vgroup_combined_vert_weight(const struct Object *ob, const int vertnum, const int mode);
|
||||
void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
|
||||
|
||||
|
||||
|
@@ -956,6 +956,60 @@ float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
|
||||
return get_vert_def_nr(ob, def_nr, vertnum);
|
||||
}
|
||||
|
||||
float ED_vgroup_combined_vert_weight(const Object *ob, const int vertnum, const int mode)
|
||||
{
|
||||
MDeformVert *dv = NULL;
|
||||
|
||||
/* get the deform vertices corresponding to the vertnum */
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = ob->data;
|
||||
|
||||
if (me->edit_btmesh) {
|
||||
BMEditMesh *em = me->edit_btmesh;
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
/* warning, this lookup is _not_ fast */
|
||||
|
||||
if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
|
||||
BMVert *eve;
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
|
||||
eve = BM_vert_at_index(em->bm, vertnum);
|
||||
dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
||||
}
|
||||
else {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (vertnum < me->totvert) {
|
||||
if (me->dvert) {
|
||||
dv = &me->dvert[vertnum];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ob->type == OB_LATTICE) {
|
||||
Lattice *lt = vgroup_edit_lattice((Object *)ob);
|
||||
|
||||
if (vertnum < lt->pntsu * lt->pntsv * lt->pntsw) {
|
||||
if (lt->dvert) {
|
||||
dv = <->dvert[vertnum];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (dv) {
|
||||
return BKE_defvert_combined_weight(ob, dv, mode);
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void ED_vgroup_select_by_name(Object *ob, const char *name)
|
||||
{ /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */
|
||||
ob->actdef = defgroup_name_index(ob, name) + 1;
|
||||
|
@@ -49,17 +49,21 @@
|
||||
typedef struct ClothSimSettings {
|
||||
struct LinkNode *cache; /* UNUSED atm */
|
||||
float mingoal; /* see SB */
|
||||
float Cdis; /* Mechanical damping of springs. */
|
||||
float tension_damp; /* Mechanical damping of structural springs. */
|
||||
float compression_damp; /* Mechanical damping of structural springs. */
|
||||
float shear_damp; /* Mechanical damping of structural springs. */
|
||||
float Cvi; /* Viscous/fluid damping. */
|
||||
float gravity[3]; /* Gravity/external force vector. */
|
||||
float dt; /* This is the duration of our time step, computed. */
|
||||
float mass; /* The mass of the entire cloth. */
|
||||
float structural; /* Structural spring stiffness. */
|
||||
float tension; /* Tension spring stiffness. */
|
||||
float compression; /* Compression spring stiffness. */
|
||||
float shear; /* Shear spring stiffness. */
|
||||
float bending; /* Flexion spring stiffness. */
|
||||
float max_bend; /* max bending scaling value, min is "bending" */
|
||||
float max_struct; /* max structural scaling value, min is "structural" */
|
||||
float max_shear; /* max shear scaling value, UNUSED */
|
||||
float max_tension; /* max structural scaling value, min is "structural" */
|
||||
float max_compression; /* max structural scaling value, min is "structural" */
|
||||
float max_shear; /* max shear scaling value */
|
||||
float max_sewing; /* max sewing force */
|
||||
float avg_spring_len; /* used for normalized springs */
|
||||
float timescale; /* parameter how fast cloth runs */
|
||||
@@ -76,15 +80,20 @@ typedef struct ClothSimSettings {
|
||||
float density_strength; /* influence of hair density */
|
||||
float collider_friction; /* friction with colliders */
|
||||
float vel_damping; /* damp the velocity to speed up getting to the resting position */
|
||||
float shrink_min; /* min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
|
||||
float shrink_max; /* max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
|
||||
float shrink; /* min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
|
||||
float max_shrink; /* max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
|
||||
float struct_plasticity; /* Factor of how much the rest length will change after reaching yield point (0-1) */
|
||||
float struct_yield_fact; /* Factor of how much length has to change before plastic behavior kicks in (1-inf) */
|
||||
float bend_plasticity; /* Factor of how much the rest angle will change after reaching yield point (0-1) */
|
||||
float bend_yield_fact; /* How much angle has to change as a factor of a full circle before plastic behavior kicks in (0-1) */
|
||||
float rest_planar_fact; /* Factor of how planar rest angles should be, 0 means the original angle, and 1 means totally flat */
|
||||
float max_planarity;
|
||||
|
||||
/* XXX various hair stuff
|
||||
* should really be separate, this struct is a horrible mess already
|
||||
*/
|
||||
float bending_damping; /* damping of bending springs */
|
||||
float voxel_cell_size; /* size of voxel grid cells for continuum dynamics */
|
||||
int pad;
|
||||
|
||||
int stepsPerFrame; /* Number of time steps per frame. */
|
||||
int flags; /* flags, see CSIMSETT_FLAGS enum above. */
|
||||
@@ -94,13 +103,26 @@ typedef struct ClothSimSettings {
|
||||
short vgroup_bend; /* vertex group for scaling bending stiffness */
|
||||
short vgroup_mass; /* optional vertexgroup name for assigning weight.*/
|
||||
short vgroup_struct; /* vertex group for scaling structural stiffness */
|
||||
short vgroup_shear; /* vertex group for scaling structural stiffness */
|
||||
short vgroup_shrink; /* vertex group for shrinking cloth */
|
||||
short vgroup_planar; /* vertex group for shrinking cloth */
|
||||
short vgroup_trouble; /* cloth trouble is written to this group */
|
||||
short shapekey_rest; /* vertex group for scaling structural stiffness */
|
||||
short presets; /* used for presets on GUI */
|
||||
short reset;
|
||||
|
||||
char pad0[4];
|
||||
char pad0[2];
|
||||
struct EffectorWeights *effector_weights;
|
||||
|
||||
/* Adaptive subframe stuff */
|
||||
int max_subframes;
|
||||
float max_vel;
|
||||
float adjustment_factor;
|
||||
float max_imp;
|
||||
float imp_adj_factor;
|
||||
char pad1[4];
|
||||
|
||||
struct Object *basemesh_target; /* object to use for dynamic basemesh */
|
||||
} ClothSimSettings;
|
||||
|
||||
|
||||
@@ -111,14 +133,16 @@ typedef struct ClothCollSettings {
|
||||
float friction; /* Friction/damping applied on contact with other object.*/
|
||||
float damping; /* Collision restitution on contact with other object.*/
|
||||
float selfepsilon; /* for selfcollision */
|
||||
float repel_force, distance_repel;
|
||||
float clamp; /* Impulse clamp for object collisions */
|
||||
float self_clamp; /* Impulse clamp for self collisions */
|
||||
int flags; /* collision flags defined in BKE_cloth.h */
|
||||
short self_loop_count; /* How many iterations for the selfcollision loop */
|
||||
short loop_count; /* How many iterations for the collision loop. */
|
||||
int pad;
|
||||
short pad[3];
|
||||
struct Group *group; /* Only use colliders from this group of objects */
|
||||
short vgroup_selfcol; /* vgroup to paint which vertices are used for self collisions */
|
||||
short pad2[3];
|
||||
short objcol_resp_iter; /* Iterations for object collision response */
|
||||
short selfcol_resp_iter; /* Iterations for self collision response */
|
||||
short pad2;
|
||||
} ClothCollSettings;
|
||||
|
||||
|
||||
|
@@ -99,6 +99,9 @@ typedef struct PartDeflect {
|
||||
float pdef_sbift; /* inner face thickness for softbody deflection */
|
||||
float pdef_sboft; /* outer face thickness for softbody deflection */
|
||||
|
||||
float pdef_cfrict; /* Friction of cloth collisions */
|
||||
char pad[4];
|
||||
|
||||
/* guide curve, same as for particle child effects */
|
||||
float clump_fac, clump_pow;
|
||||
float kink_freq, kink_shape, kink_amp, free_end;
|
||||
@@ -373,6 +376,8 @@ typedef struct SoftBody {
|
||||
#define PFIELD_GUIDE_PATH_WEIGHT (1<<16) /* apply curve weights */
|
||||
#define PFIELD_SMOKE_DENSITY (1<<17) /* multiply smoke force by density */
|
||||
#define PFIELD_GRAVITATION (1<<18) /* used for (simple) force */
|
||||
#define PFIELD_CLOTH_USE_CULLING (1<<19) /* enable cloth collision side detection based on normal */
|
||||
#define PFIELD_CLOTH_USE_NORMAL (1<<12) /* replace collision direction with collider normal */
|
||||
|
||||
/* pd->falloff */
|
||||
#define PFIELD_FALL_SPHERE 0
|
||||
|
@@ -65,7 +65,8 @@ typedef struct bDeformGroup {
|
||||
struct bDeformGroup *next, *prev;
|
||||
char name[64]; /* MAX_VGROUP_NAME */
|
||||
/* need this flag for locking weights */
|
||||
char flag, pad[7];
|
||||
char flag, pad[3];
|
||||
float influence;
|
||||
} bDeformGroup;
|
||||
#define MAX_VGROUP_NAME 64
|
||||
|
||||
|
@@ -31,10 +31,13 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_modifier.h"
|
||||
|
||||
@@ -62,18 +65,6 @@ static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
|
||||
rna_cloth_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
/* ClothSimSettings *settings = (ClothSimSettings *)ptr->data; */
|
||||
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
||||
|
||||
cloth_free_modifier(clmd);
|
||||
|
||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_bending_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
@@ -88,34 +79,78 @@ static void rna_ClothSettings_bending_set(struct PointerRNA *ptr, float value)
|
||||
static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->bending)
|
||||
value = settings->bending;
|
||||
|
||||
|
||||
settings->max_bend = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_structural_set(struct PointerRNA *ptr, float value)
|
||||
static void rna_ClothSettings_tension_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->structural = value;
|
||||
settings->tension = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_struct)
|
||||
settings->max_struct = value;
|
||||
if (value > settings->max_tension)
|
||||
settings->max_tension = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value)
|
||||
static void rna_ClothSettings_max_tension_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->tension)
|
||||
value = settings->tension;
|
||||
|
||||
settings->max_tension = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_compression_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->compression = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_compression)
|
||||
settings->max_compression = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_compression_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->compression)
|
||||
value = settings->compression;
|
||||
|
||||
settings->max_compression = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_shear_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->shear = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_shear)
|
||||
settings->max_shear = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_shear_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->structural)
|
||||
value = settings->structural;
|
||||
if (value < settings->shear)
|
||||
value = settings->shear;
|
||||
|
||||
settings->max_struct = value;
|
||||
settings->max_shear = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_sewing_set(struct PointerRNA *ptr, float value)
|
||||
@@ -129,6 +164,72 @@ static void rna_ClothSettings_max_sewing_set(struct PointerRNA *ptr, float value
|
||||
settings->max_sewing = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_shrink_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->shrink = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_shrink)
|
||||
settings->max_shrink = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_shrink_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->shrink)
|
||||
value = settings->shrink;
|
||||
|
||||
settings->max_shrink = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_planarity_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->rest_planar_fact = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_planarity)
|
||||
settings->max_planarity = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_planarity_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->rest_planar_fact)
|
||||
value = settings->rest_planar_fact;
|
||||
|
||||
settings->max_planarity = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_subframes_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
settings->stepsPerFrame = value;
|
||||
|
||||
/* check for max clipping */
|
||||
if (value > settings->max_subframes)
|
||||
settings->max_subframes = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_subframes_set(struct PointerRNA *ptr, int value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
|
||||
|
||||
/* check for clipping */
|
||||
if (value < settings->stepsPerFrame)
|
||||
value = settings->stepsPerFrame;
|
||||
|
||||
settings->max_subframes = value;
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_mass_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
@@ -183,6 +284,24 @@ static void rna_ClothSettings_struct_vgroup_set(PointerRNA *ptr, const char *val
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_struct);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_shear_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_shear);
|
||||
}
|
||||
|
||||
static int rna_ClothSettings_shear_vgroup_length(PointerRNA *ptr)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_shear);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_shear_vgroup_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_shear);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_bend_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
@@ -201,6 +320,41 @@ static void rna_ClothSettings_bend_vgroup_set(PointerRNA *ptr, const char *value
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_bend);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_planar_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_planar);
|
||||
}
|
||||
|
||||
static int rna_ClothSettings_planar_vgroup_length(PointerRNA *ptr)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_planar);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_planar_vgroup_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_planar);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_trouble_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_trouble);
|
||||
}
|
||||
|
||||
static int rna_ClothSettings_trouble_vgroup_length(PointerRNA *ptr)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_trouble);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_trouble_vgroup_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_trouble);
|
||||
}
|
||||
|
||||
static void rna_CollSettings_selfcol_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
@@ -284,13 +438,35 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_besemesh_target_set(PointerRNA *ptr, PointerRNA value)
|
||||
{
|
||||
Object *target = (Object *)value.data;
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
|
||||
if (is_basemesh_valid((Object *)ptr->id.data, target, NULL)) {
|
||||
sim->basemesh_target = target;
|
||||
}
|
||||
}
|
||||
|
||||
static bool rna_ClothSettings_besemesh_target_poll(PointerRNA *ptr, const PointerRNA value)
|
||||
{
|
||||
return is_basemesh_valid((Object *)ptr->id.data, (Object *)value.data, NULL);
|
||||
}
|
||||
|
||||
static int rna_ClothSettings_besemesh_target_valid_get(PointerRNA *ptr)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
|
||||
return is_basemesh_valid((Object *)ptr->id.data, sim->basemesh_target, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_cloth_solver_result(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
|
||||
static const EnumPropertyItem status_items[] = {
|
||||
{BPH_SOLVER_SUCCESS, "SUCCESS", 0, "Success", "Computation was successful"},
|
||||
{BPH_SOLVER_NUMERICAL_ISSUE, "NUMERICAL_ISSUE", 0, "Numerical Issue", "The provided data did not satisfy the prerequisites"},
|
||||
@@ -298,7 +474,7 @@ static void rna_def_cloth_solver_result(BlenderRNA *brna)
|
||||
{BPH_SOLVER_INVALID_INPUT, "INVALID_INPUT", 0, "Invalid Input", "The inputs are invalid, or the algorithm has been improperly called"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
srna = RNA_def_struct(brna, "ClothSolverResult", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Solver Result", "Result of cloth solver iteration");
|
||||
|
||||
@@ -424,7 +600,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length",
|
||||
"rna_ClothSettings_mass_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex Group for pinning of vertices");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_pinning_changed");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
@@ -449,10 +625,10 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
"(1.0 = no damping, 0.0 = fully dampened)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_pin_cloth", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
|
||||
RNA_def_property_ui_text(prop, "Pin Cloth", "Enable pinning of cloth vertices to other objects/positions");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_pinning_changed");
|
||||
prop = RNA_def_property(srna, "use_combined_pin_cloth", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_COMB_GOAL);
|
||||
RNA_def_property_ui_text(prop, "Combined Weights", "Use combined interpolated weights for cloth pinning");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
@@ -465,6 +641,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
|
||||
RNA_def_property_range(prop, 1, INT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 80, 1, -1);
|
||||
RNA_def_property_int_funcs(prop, NULL, "rna_ClothSettings_subframes_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Quality",
|
||||
"Quality of the simulation in steps per frame (higher is better quality but slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
@@ -482,15 +659,17 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Shrink Vertex Group", "Vertex Group for shrinking cloth");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shrink_min", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shrink_min");
|
||||
prop = RNA_def_property(srna, "shrinking", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shrink");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Shrink Factor Min", "Min amount to shrink cloth by");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_shrink_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shrink Factor", "Factor by which to shrink cloth");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shrink_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shrink_max");
|
||||
prop = RNA_def_property(srna, "shrinking_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_shrink");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_shrink_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shrink Factor Max", "Max amount to shrink cloth by");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
@@ -501,34 +680,150 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Voxel Grid Cell Size", "Size of the voxel grid cells for interaction effects");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
/* Adaptive subframes */
|
||||
prop = RNA_def_property(srna, "use_adaptive_subframes", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_VEL);
|
||||
RNA_def_property_ui_text(prop, "Use Adaptive Velocity Subframes", "Adapt subframes to the cloth velocity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_impulse_adaptive_subframes", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_IMP);
|
||||
RNA_def_property_ui_text(prop, "Use Adaptive Impulse Subframes", "Adapt subframes to the cloth collision impulses");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "max_sub_steps", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "max_subframes");
|
||||
RNA_def_property_range(prop, 1, INT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 80, 1, -1);
|
||||
RNA_def_property_int_funcs(prop, NULL, "rna_ClothSettings_max_subframes_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Max Subframes", "Maximum number of subframes to use with adaptive subframes");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_vel");
|
||||
RNA_def_property_range(prop, 0.001f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Maximum Velocity", "Maximum velocity before increasing subframes");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "adjustment_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "adjustment_factor");
|
||||
RNA_def_property_range(prop, 0.1f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Adjustment Factor", "Factor of the velocity to adjust subframes by (lower means more subframes)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "max_impulse", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_imp");
|
||||
RNA_def_property_range(prop, 0.001f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Maximum Collision Impulse", "Maximum collision impulse before increasing subframes");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "impulse_adjustment_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "imp_adj_factor");
|
||||
RNA_def_property_range(prop, 0.1f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Adjustment Factor", "Factor of the impulse to adjust subframes by (lower means more subframes)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
/* springs */
|
||||
|
||||
prop = RNA_def_property(srna, "use_stiffness_scale", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
|
||||
RNA_def_property_ui_text(prop, "Stiffness Scaling",
|
||||
"If enabled, stiffness can be scaled along a weight painted vertex group");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "Cdis");
|
||||
prop = RNA_def_property(srna, "tension_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "tension_damp");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0f);
|
||||
RNA_def_property_ui_text(prop, "Spring Damping",
|
||||
"Damping of cloth velocity (higher = more smooth, less jiggling)");
|
||||
RNA_def_property_ui_text(prop, "Tension Spring Damping", "Amount of damping in stretching behavior");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "structural");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_structural_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure");
|
||||
prop = RNA_def_property(srna, "compression_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "compression_damp");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0f);
|
||||
RNA_def_property_ui_text(prop, "Compression Spring Damping", "Amount of damping in compression behavior");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_struct");
|
||||
prop = RNA_def_property(srna, "shear_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shear_damp");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0f);
|
||||
RNA_def_property_ui_text(prop, "Shear Spring Damping", "Amount of damping in shearing behavior");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "tension_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "tension");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_tension_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Tension Stiffness", "How much the material resists stretching");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "tension_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_tension");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_tension_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Tension Stiffness Maximum", "Maximum tension stiffness value");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "compression_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "compression");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_compression_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Compression Stiffness", "How much the material resists compression");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "compression_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_compression");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_compression_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Compression Stiffness Maximum", "Maximum compression stiffness value");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shear");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_shear_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shear Stiffness", "How much the material resists shearing");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_shear");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_shear_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shear Stiffness Maximum", "Maximum shear scaling value");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "structural_plasticity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "struct_plasticity");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Structural Plasticity", "Rate at which the material should retain in-plane deformations");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "structural_yield_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "struct_yield_fact");
|
||||
RNA_def_property_range(prop, 1.0f, 100.0f);
|
||||
RNA_def_property_ui_range(prop, 1.0f, 2.0f, 10, 3);
|
||||
RNA_def_property_ui_text(prop, "Structural Yield Factor", "How much cloth has to deform in-plane before plasticity takes effect (factor of rest state)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bending_plasticity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bend_plasticity");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Bending Plasticity", "Rate at which the material should retain out-of-plane deformations");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bending_yield_factor", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bend_yield_fact");
|
||||
RNA_def_property_range(prop, 0.0f, M_PI * 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Bending Yield Factor", "How much cloth has to bend before plasticity takes effect (degrees)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "rest_planarity_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rest_planar_fact");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_planarity_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Rest Planarity Factor", "How planar the rest shape should be, 0 is the original shape, and 1 is totally flat");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "planarity_factor_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_planarity");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_planarity_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Rest Planarity Maximum", "Maximum rest planarity factor value");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "sewing_force_max", PROP_FLOAT, PROP_NONE);
|
||||
@@ -546,12 +841,19 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
"Vertex group for fine control over structural stiffness");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_group_shear_stiffness", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_shear_vgroup_get",
|
||||
"rna_ClothSettings_shear_vgroup_length",
|
||||
"rna_ClothSettings_shear_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Shear Stiffness Vertex Group",
|
||||
"Vertex group for fine control over shear stiffness");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bending");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_bending_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Bending Stiffness",
|
||||
"Wrinkle coefficient (higher = less smaller but more big wrinkles)");
|
||||
RNA_def_property_ui_text(prop, "Bending Stiffness", "How much the material resists bending");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
@@ -564,8 +866,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
prop = RNA_def_property(srna, "bending_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bending_damping");
|
||||
RNA_def_property_range(prop, 0.0f, 1000.0f);
|
||||
RNA_def_property_ui_text(prop, "Bending Spring Damping",
|
||||
"Damping of bending motion");
|
||||
RNA_def_property_ui_text(prop, "Bending Spring Damping", "Amount of damping in bending behavior");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_sewing_springs", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -581,6 +882,18 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
"Vertex group for fine control over bending stiffness");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_group_planarity", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_planar_vgroup_get", "rna_ClothSettings_planar_vgroup_length",
|
||||
"rna_ClothSettings_planar_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Planarity Scaling Vertex Group", "Vertex group for fine control over rest planarity");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_group_trouble", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_trouble_vgroup_get", "rna_ClothSettings_trouble_vgroup_length",
|
||||
"rna_ClothSettings_trouble_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Trouble Vertex Group", "Vertex group to which troublesome things are written");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "EffectorWeights");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
@@ -591,7 +904,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "ShapeKey");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_ClothSettings_rest_shape_key_get",
|
||||
"rna_ClothSettings_rest_shape_key_set", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Rest Shape Key", "Shape key to use the rest spring lengths from");
|
||||
RNA_def_property_ui_text(prop, "Rest Shape Key", "Shape key to use as rest shape");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_dynamic_mesh", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -600,22 +913,31 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "basemesh_target", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Basemesh", "Object mesh to use as rest shape");
|
||||
RNA_def_property_pointer_funcs(prop, NULL, "rna_ClothSettings_besemesh_target_set", NULL, "rna_ClothSettings_besemesh_target_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "is_basemesh_target_valid", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_ClothSettings_besemesh_target_valid_get", NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Basemesh Valid", "True if the set basemesh is valid");
|
||||
|
||||
prop = RNA_def_property(srna, "use_initial_velocity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_INIT_VEL);
|
||||
RNA_def_property_ui_text(prop, "Initialize Velocity", "Initialize velocity from animation");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "compensate_instability", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_COMPENSATE_INSTABILITY);
|
||||
RNA_def_property_ui_text(prop, "Compensate Instability", "Compensate instability by increasing subframes");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
/* unused */
|
||||
|
||||
/* unused still */
|
||||
#if 0
|
||||
prop = RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shear");
|
||||
RNA_def_property_range(prop, 0.0f, 1000.0f);
|
||||
RNA_def_property_ui_text(prop, "Shear Stiffness", "Shear spring stiffness");
|
||||
#endif
|
||||
/* unused still */
|
||||
#if 0
|
||||
prop = RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_shear");
|
||||
RNA_def_property_range(prop, 0.0f, upperLimitf);
|
||||
RNA_def_property_ui_text(prop, "Shear Stiffness Maximum", "Maximum shear scaling value");
|
||||
#endif
|
||||
/* unused still */
|
||||
#if 0
|
||||
prop = RNA_def_property(srna, "effector_force_scale", PROP_FLOAT, PROP_NONE);
|
||||
@@ -663,21 +985,6 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "repel_force", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "repel_force");
|
||||
RNA_def_property_range(prop, 0.0f, 20.0f);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Repulsion Force", "Repulsion force to apply on cloth when close to colliding");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "distance_repel", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "distance_repel");
|
||||
RNA_def_property_range(prop, 0.001f, 10.0f);
|
||||
RNA_def_property_float_default(prop, 0.005f);
|
||||
RNA_def_property_ui_text(prop, "Repulsion Distance",
|
||||
"Maximum distance to apply repulsion force, must be greater than minimum distance");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "distance_min", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "epsilon");
|
||||
RNA_def_property_range(prop, 0.001f, 1.0f);
|
||||
@@ -702,7 +1009,21 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 1, SHRT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 20, 1, -1);
|
||||
RNA_def_property_ui_text(prop, "Collision Quality",
|
||||
"How many collision iterations should be done. (higher is better quality but slower)");
|
||||
"How many collision iterations should be done. (higher is smoother quality but slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "collision_response_quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "objcol_resp_iter");
|
||||
RNA_def_property_range(prop, 1, SHRT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 20, 1, -1);
|
||||
RNA_def_property_ui_text(prop, "Response Quality",
|
||||
"How many object collision response iterations should be done. (higher is smoother but slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "impulse_clamp", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "clamp");
|
||||
RNA_def_property_range(prop, 0.0f, 100.0f);
|
||||
RNA_def_property_ui_text(prop, "Impulse Clamping", "Don't use collision impulses above this magnitude (0.0 to disable clamping)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
/* self collision */
|
||||
@@ -714,22 +1035,13 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "self_distance_min", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
|
||||
RNA_def_property_range(prop, 0.5f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
|
||||
RNA_def_property_range(prop, 0.001f, 0.1f);
|
||||
RNA_def_property_ui_text(prop, "Self Minimum Distance", "Minimum distance between cloth faces before collision response takes in");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0f, 80.0f);
|
||||
RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
|
||||
RNA_def_property_range(prop, 1, SHRT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 10, 1, -1);
|
||||
RNA_def_property_ui_text(prop, "Self Collision Quality",
|
||||
"How many self collision iterations should be done "
|
||||
"(higher is better quality but slower)");
|
||||
RNA_def_property_ui_text(prop, "Self Friction", "Friction with self contact");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
|
||||
@@ -743,6 +1055,20 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Selfcollision Vertex Group",
|
||||
"Vertex group to define vertices which are not used during self collisions");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "selfcollision_response_quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "selfcol_resp_iter");
|
||||
RNA_def_property_range(prop, 1, SHRT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1, 20, 1, -1);
|
||||
RNA_def_property_ui_text(prop, "Response Quality",
|
||||
"How many self collision response iterations should be done. (higher is better quality but slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "self_impulse_clamp", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "self_clamp");
|
||||
RNA_def_property_range(prop, 0.0f, 100.0f);
|
||||
RNA_def_property_ui_text(prop, "Impulse Clamping", "Don't use self collision impulses above this magnitude (0.0 to disable clamping)");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
}
|
||||
|
||||
void RNA_def_cloth(BlenderRNA *brna)
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
|
||||
#include "BKE_object_deform.h"
|
||||
#include "BKE_deform.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
@@ -964,6 +965,11 @@ static char *rna_MaterialSlot_path(PointerRNA *ptr)
|
||||
return BLI_sprintfN("material_slots[%d]", index);
|
||||
}
|
||||
|
||||
static char *rna_VertexGroup_path(PointerRNA *ptr)
|
||||
{
|
||||
return BLI_sprintfN("vertex_groups[%d]", rna_VertexGroup_index_get(ptr));
|
||||
}
|
||||
|
||||
/* why does this have to be so complicated?, can't all this crap be
|
||||
* moved to in BGE conversion function? - Campbell *
|
||||
*
|
||||
@@ -1435,6 +1441,17 @@ static void rna_Object_vgroup_clear(Object *ob)
|
||||
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
|
||||
}
|
||||
|
||||
static float rna_Object_combined_vgroup_weight(Object *ob, ReportList *reports, int index, int mode)
|
||||
{
|
||||
float weight = ED_vgroup_combined_vert_weight(ob, index, mode);
|
||||
|
||||
if (weight < 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Vertex index not in range");
|
||||
}
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
static void rna_VertexGroup_vertex_add(ID *id, bDeformGroup *def, ReportList *reports, int index_len,
|
||||
int *index, float weight, int assignmode)
|
||||
{
|
||||
@@ -1568,6 +1585,14 @@ static void rna_def_vertex_group(BlenderRNA *brna)
|
||||
RNA_def_property_int_funcs(prop, "rna_VertexGroup_index_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Index", "Index number of the vertex group");
|
||||
|
||||
prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "influence");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1f, 3);
|
||||
RNA_def_property_ui_text(prop, "Influence", "Influence of the vertex group on the combined group");
|
||||
RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data");
|
||||
RNA_def_property_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
func = RNA_def_function(srna, "add", "rna_VertexGroup_vertex_add");
|
||||
RNA_def_function_ui_description(func, "Add vertices to the group");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
|
||||
@@ -1593,6 +1618,8 @@ static void rna_def_vertex_group(BlenderRNA *brna)
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight", 0.0f, 1.0f);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
RNA_def_struct_path_func(srna, "rna_VertexGroup_path");
|
||||
}
|
||||
|
||||
static void rna_def_material_slot(BlenderRNA *brna)
|
||||
@@ -2085,6 +2112,12 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
static EnumPropertyItem combined_vertex_group_mode[] = {
|
||||
{DVERT_COMBINED_MODE_ADD, "ADD", 0, "Add", "Add"},
|
||||
{DVERT_COMBINED_MODE_MIX, "MIX", 0, "Mix", "Mix"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
RNA_def_property_srna(cprop, "VertexGroups");
|
||||
srna = RNA_def_struct(brna, "VertexGroups", NULL);
|
||||
RNA_def_struct_sdna(srna, "Object");
|
||||
@@ -2122,6 +2155,15 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
|
||||
func = RNA_def_function(srna, "clear", "rna_Object_vgroup_clear");
|
||||
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
|
||||
|
||||
func = RNA_def_function(srna, "combined_weight", "rna_Object_combined_vgroup_weight");
|
||||
RNA_def_function_ui_description(func, "Get combined interpolated weight for vertex");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "The index of the vertex", 0, INT_MAX);
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_enum(func, "mode", combined_vertex_group_mode, 0, "", "Weight interpolation mode");
|
||||
parm = RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight", 0.0f, 1.0f);
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1011,6 +1011,22 @@ static void rna_def_collision(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Absorption",
|
||||
"How much of effector force gets lost during collision with this object (in percent)");
|
||||
RNA_def_property_update(prop, 0, "rna_CollisionSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "cloth_friction", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "pdef_cfrict");
|
||||
RNA_def_property_range(prop, 0.0f, 80.0f);
|
||||
RNA_def_property_ui_text(prop, "Friction", "Friction for cloth collisions");
|
||||
RNA_def_property_update(prop, 0, "rna_CollisionSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_culling", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_CLOTH_USE_CULLING);
|
||||
RNA_def_property_ui_text(prop, "Single Sided", "Cloth collision acts with respect to the collider normals (improves penetration recovery)");
|
||||
RNA_def_property_update(prop, 0, "rna_CollisionSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_CLOTH_USE_NORMAL);
|
||||
RNA_def_property_ui_text(prop, "Override Normals", "Cloth collision impulses act in the direction of the collider normals (might improve some cases)");
|
||||
RNA_def_property_update(prop, 0, "rna_CollisionSettings_update");
|
||||
}
|
||||
|
||||
static void rna_def_effector_weight(BlenderRNA *brna)
|
||||
|
@@ -790,7 +790,6 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer
|
||||
if (psys && !psys->clmd) {
|
||||
psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
|
||||
psys->clmd->sim_parms->goalspring = 0.0f;
|
||||
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL | CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
|
||||
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
|
||||
rna_Particle_redo(bmain, scene, ptr);
|
||||
}
|
||||
|
@@ -127,6 +127,12 @@ static void updateDepgraph(ModifierData *md, const ModifierUpdateDepsgraphContex
|
||||
#ifdef WITH_LEGACY_DEPSGRAPH
|
||||
dag_add_collision_relations(ctx->forest, ctx->scene, ctx->object, ctx->obNode, clmd->coll_parms->group, ctx->object->lay|ctx->scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
|
||||
dag_add_forcefield_relations(ctx->forest, ctx->scene, ctx->object, ctx->obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
|
||||
|
||||
if (clmd->sim_parms->basemesh_target && (clmd->sim_parms->basemesh_target != ctx->object)) {
|
||||
DagNode *curNode = dag_get_node(ctx->forest, clmd->sim_parms->basemesh_target);
|
||||
|
||||
dag_add_relation(ctx->forest, curNode, ctx->obNode, (DAG_RL_DATA_DATA | DAG_RL_OB_DATA), "Cloth Base Mesh Target");
|
||||
}
|
||||
#else
|
||||
(void)ctx;
|
||||
#endif
|
||||
@@ -141,6 +147,11 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
|
||||
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, clmd->coll_parms->group, ctx->object->lay|ctx->scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
|
||||
|
||||
DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
|
||||
|
||||
if (clmd->sim_parms->basemesh_target && (clmd->sim_parms->basemesh_target != ctx->object)) {
|
||||
DEG_add_object_relation(ctx->node, clmd->sim_parms->basemesh_target, DEG_OB_COMP_TRANSFORM, "Cloth Base Mesh Target");
|
||||
DEG_add_object_relation(ctx->node, clmd->sim_parms->basemesh_target, DEG_OB_COMP_GEOMETRY, "Cloth Base Mesh Target");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +190,7 @@ static void copyData(const ModifierData *md, ModifierData *target)
|
||||
if (clmd->sim_parms->effector_weights)
|
||||
tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
|
||||
tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
|
||||
tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
|
||||
tclmd->point_cache->step = 1;
|
||||
tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches, true);
|
||||
tclmd->clothObject = NULL;
|
||||
tclmd->hairdata = NULL;
|
||||
tclmd->solver_result = NULL;
|
||||
@@ -233,6 +243,10 @@ static void foreachIDLink(
|
||||
if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
|
||||
walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
if (clmd->sim_parms && clmd->sim_parms->basemesh_target) {
|
||||
walk(userData, ob, (ID **)&clmd->sim_parms->basemesh_target, IDWALK_NOP);
|
||||
}
|
||||
}
|
||||
|
||||
ModifierTypeInfo modifierType_Cloth = {
|
||||
|
@@ -49,10 +49,10 @@
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
static void initData(ModifierData *md)
|
||||
{
|
||||
CollisionModifierData *collmd = (CollisionModifierData *) md;
|
||||
|
||||
|
||||
collmd->x = NULL;
|
||||
collmd->xnew = NULL;
|
||||
collmd->current_x = NULL;
|
||||
@@ -68,7 +68,7 @@ static void initData(ModifierData *md)
|
||||
static void freeData(ModifierData *md)
|
||||
{
|
||||
CollisionModifierData *collmd = (CollisionModifierData *) md;
|
||||
|
||||
|
||||
if (collmd) { /* Seriously? */
|
||||
if (collmd->bvhtree) {
|
||||
BLI_bvhtree_free(collmd->bvhtree);
|
||||
@@ -118,6 +118,7 @@ static void deformVerts(
|
||||
if (dm) {
|
||||
float current_time = 0;
|
||||
unsigned int mvert_num = 0;
|
||||
unsigned int i;
|
||||
|
||||
CDDM_apply_vert_coords(dm, vertexCos);
|
||||
CDDM_calc_normals(dm);
|
||||
@@ -129,113 +130,108 @@ static void deformVerts(
|
||||
|
||||
mvert_num = dm->getNumVerts(dm);
|
||||
|
||||
if (current_time > collmd->time_xnew) {
|
||||
unsigned int i;
|
||||
|
||||
/* check if mesh has changed */
|
||||
if (collmd->x && (mvert_num != collmd->mvert_num))
|
||||
freeData((ModifierData *)collmd);
|
||||
|
||||
if (collmd->time_xnew == -1000) { /* first time */
|
||||
|
||||
collmd->x = dm->dupVertArray(dm); /* frame start position */
|
||||
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
/* we save global positions */
|
||||
mul_m4_v3(ob->obmat, collmd->x[i].co);
|
||||
}
|
||||
|
||||
collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
|
||||
collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
|
||||
|
||||
collmd->mvert_num = mvert_num;
|
||||
|
||||
collmd->tri_num = dm->getNumLoopTri(dm);
|
||||
{
|
||||
const MLoop *mloop = dm->getLoopArray(dm);
|
||||
const MLoopTri *looptri = dm->getLoopTriArray(dm);
|
||||
MVertTri *tri = MEM_malloc_arrayN(collmd->tri_num, sizeof(*tri), __func__);
|
||||
DM_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
|
||||
collmd->tri = tri;
|
||||
}
|
||||
|
||||
/* create bounding box hierarchy */
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
|
||||
collmd->time_x = collmd->time_xnew = current_time;
|
||||
collmd->is_static = true;
|
||||
}
|
||||
else if (mvert_num == collmd->mvert_num) {
|
||||
/* put positions to old positions */
|
||||
tempVert = collmd->x;
|
||||
collmd->x = collmd->xnew;
|
||||
collmd->xnew = tempVert;
|
||||
collmd->time_x = collmd->time_xnew;
|
||||
|
||||
memcpy(collmd->xnew, dm->getVertArray(dm), mvert_num * sizeof(MVert));
|
||||
|
||||
bool is_static = true;
|
||||
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
/* we save global positions */
|
||||
mul_m4_v3(ob->obmat, collmd->xnew[i].co);
|
||||
|
||||
/* detect motion */
|
||||
is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
|
||||
}
|
||||
|
||||
memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
|
||||
memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
|
||||
|
||||
/* check if GUI setting has changed for bvh */
|
||||
if (collmd->bvhtree) {
|
||||
if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
|
||||
BLI_bvhtree_free(collmd->bvhtree);
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->current_x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* happens on file load (ONLY when i decomment changes in readfile.c) */
|
||||
if (!collmd->bvhtree) {
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->current_x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
}
|
||||
else if (!collmd->is_static || !is_static) {
|
||||
/* recalc static bounding boxes */
|
||||
bvhtree_update_from_mvert(
|
||||
collmd->bvhtree,
|
||||
collmd->current_x, collmd->current_xnew,
|
||||
collmd->tri, collmd->tri_num,
|
||||
true);
|
||||
}
|
||||
|
||||
collmd->is_static = is_static;
|
||||
collmd->time_xnew = current_time;
|
||||
}
|
||||
else if (mvert_num != collmd->mvert_num) {
|
||||
freeData((ModifierData *)collmd);
|
||||
}
|
||||
|
||||
}
|
||||
else if (current_time < collmd->time_xnew) {
|
||||
if (current_time < collmd->time_xnew) {
|
||||
freeData((ModifierData *)collmd);
|
||||
}
|
||||
else {
|
||||
else if (current_time == collmd->time_xnew) {
|
||||
if (mvert_num != collmd->mvert_num) {
|
||||
freeData((ModifierData *)collmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if mesh has changed */
|
||||
if (collmd->x && (mvert_num != collmd->mvert_num))
|
||||
freeData((ModifierData *)collmd);
|
||||
|
||||
if (collmd->time_xnew == -1000) { /* first time */
|
||||
|
||||
collmd->x = dm->dupVertArray(dm); /* frame start position */
|
||||
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
/* we save global positions */
|
||||
mul_m4_v3(ob->obmat, collmd->x[i].co);
|
||||
}
|
||||
|
||||
collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
|
||||
collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
|
||||
|
||||
collmd->mvert_num = mvert_num;
|
||||
|
||||
collmd->tri_num = dm->getNumLoopTri(dm);
|
||||
{
|
||||
const MLoop *mloop = dm->getLoopArray(dm);
|
||||
const MLoopTri *looptri = dm->getLoopTriArray(dm);
|
||||
MVertTri *tri = MEM_malloc_arrayN(collmd->tri_num, sizeof(*tri), __func__);
|
||||
DM_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
|
||||
collmd->tri = tri;
|
||||
}
|
||||
|
||||
/* create bounding box hierarchy */
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
|
||||
collmd->time_x = collmd->time_xnew = current_time;
|
||||
collmd->is_static = true;
|
||||
}
|
||||
else if (mvert_num == collmd->mvert_num) {
|
||||
/* put positions to old positions */
|
||||
tempVert = collmd->x;
|
||||
collmd->x = collmd->xnew;
|
||||
collmd->xnew = tempVert;
|
||||
collmd->time_x = collmd->time_xnew;
|
||||
|
||||
memcpy(collmd->xnew, dm->getVertArray(dm), mvert_num * sizeof(MVert));
|
||||
|
||||
bool is_static = true;
|
||||
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
/* we save global positions */
|
||||
mul_m4_v3(ob->obmat, collmd->xnew[i].co);
|
||||
|
||||
/* detect motion */
|
||||
is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
|
||||
}
|
||||
|
||||
memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
|
||||
memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
|
||||
|
||||
/* check if GUI setting has changed for bvh */
|
||||
if (collmd->bvhtree) {
|
||||
if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
|
||||
BLI_bvhtree_free(collmd->bvhtree);
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->current_x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
}
|
||||
}
|
||||
|
||||
/* happens on file load (ONLY when i decomment changes in readfile.c) */
|
||||
if (!collmd->bvhtree) {
|
||||
collmd->bvhtree = bvhtree_build_from_mvert(
|
||||
collmd->current_x,
|
||||
collmd->tri, collmd->tri_num,
|
||||
ob->pd->pdef_sboft);
|
||||
}
|
||||
else if (!collmd->is_static || !is_static) {
|
||||
/* recalc static bounding boxes */
|
||||
bvhtree_update_from_mvert(
|
||||
collmd->bvhtree,
|
||||
collmd->current_x, collmd->current_xnew,
|
||||
collmd->tri, collmd->tri_num,
|
||||
true);
|
||||
}
|
||||
|
||||
collmd->is_static = is_static;
|
||||
collmd->time_xnew = current_time;
|
||||
}
|
||||
else if (mvert_num != collmd->mvert_num) {
|
||||
freeData((ModifierData *)collmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (dm)
|
||||
|
@@ -55,7 +55,7 @@ int BPH_mass_spring_solver_numvert(struct Implicit_Data *id);
|
||||
|
||||
int BPH_cloth_solver_init(struct Object *ob, struct ClothModifierData *clmd);
|
||||
void BPH_cloth_solver_free(struct ClothModifierData *clmd);
|
||||
int BPH_cloth_solve(struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors);
|
||||
int BPH_cloth_solve(struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors, struct DerivedMesh *dm);
|
||||
void BKE_cloth_solver_set_positions(struct ClothModifierData *clmd);
|
||||
|
||||
bool BPH_cloth_solver_get_texture_data(struct Object *ob, struct ClothModifierData *clmd, struct VoxelData *vd);
|
||||
|
@@ -45,6 +45,8 @@ extern "C" {
|
||||
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_collision.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_effect.h"
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
|
||||
for (link = cloth->springs; link; link = link->next) {
|
||||
ClothSpring *spring = (ClothSpring *)link->link;
|
||||
switch (spring->type) {
|
||||
case CLOTH_SPRING_TYPE_BENDING_ANG:
|
||||
case CLOTH_SPRING_TYPE_BENDING_HAIR:
|
||||
/* angular bending combines 3 vertices */
|
||||
nondiag += 3;
|
||||
break;
|
||||
@@ -128,6 +130,7 @@ void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
|
||||
BPH_mass_spring_set_rest_transform(id, i, I3);
|
||||
|
||||
BPH_mass_spring_set_motion_state(id, i, verts[i].x, verts[i].v);
|
||||
copy_v3_v3(verts[i].tvold, verts[i].v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +291,7 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
|
||||
float len, c, l, vec[3];
|
||||
|
||||
spring = (ClothSpring *)node->link;
|
||||
if (spring->type != CLOTH_SPRING_TYPE_STRUCTURAL && spring->type != CLOTH_SPRING_TYPE_SHEAR)
|
||||
if (!(spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR)))
|
||||
continue;
|
||||
|
||||
v1 = spring->ij; v2 = spring->kl;
|
||||
@@ -333,7 +336,8 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
|
||||
return 1;
|
||||
}
|
||||
|
||||
BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
|
||||
BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float struct_plast,
|
||||
float bend_plast, bool collision_pass)
|
||||
{
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
ClothSimSettings *parms = clmd->sim_parms;
|
||||
@@ -343,42 +347,90 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
|
||||
|
||||
s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
|
||||
|
||||
// calculate force of structural + shear springs
|
||||
if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) {
|
||||
#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
|
||||
float k, scaling;
|
||||
if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
|
||||
#ifdef CLOTH_FORCE_SPRING_BEND
|
||||
float k, scaling, planarity;
|
||||
|
||||
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
|
||||
|
||||
scaling = parms->structural + s->stiffness * fabsf(parms->max_struct - parms->structural);
|
||||
k = scaling / (parms->avg_spring_len + FLT_EPSILON);
|
||||
scaling = parms->bending + s->ang_stiffness * fabsf(parms->max_bend - parms->bending);
|
||||
k = scaling * s->restlen * s->lenfact * 0.1f; /* multiplying by 0.1, just to scale the forces to more reasonable values */
|
||||
|
||||
planarity = parms->rest_planar_fact + s->planarity * fabsf(parms->max_planarity - parms->rest_planar_fact);
|
||||
|
||||
BPH_mass_spring_force_spring_angular(data, s->ij, s->kl, s->pa, s->pb, s->la, s->lb,
|
||||
s->restang * (1.0f - planarity), &s->angoffset, k,
|
||||
parms->bending_damping, bend_plast, parms->bend_yield_fact, !collision_pass);
|
||||
#endif
|
||||
}
|
||||
|
||||
// calculate force of structural + shear springs
|
||||
if ( s->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SEWING) ) {
|
||||
#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
|
||||
float k_tension, k_compression, scaling_tension, scaling_compression;
|
||||
float d_tension, d_compression;
|
||||
|
||||
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
|
||||
|
||||
// TODO: Scaling should be relative to half the area of the adjacent faces instead of length (except for sewing)
|
||||
// Note that this scaling is only valid when coupled with proper mass distribution
|
||||
scaling_tension = parms->tension + s->lin_stiffness * fabsf(parms->max_tension - parms->tension);
|
||||
|
||||
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
|
||||
// Multiply by some arbitrary large value, just so zero-length (sewing) springs have enough force.
|
||||
k_tension = scaling_tension * 10000;
|
||||
d_tension = parms->tension_damp * 10000;
|
||||
|
||||
// TODO: verify, half verified (couldn't see error)
|
||||
// sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
|
||||
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing);
|
||||
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, &s->lenfact, k_tension, 0.0f,
|
||||
d_tension, 0.0f, no_compress, parms->max_sewing, 0.0f, 1.0f, false);
|
||||
}
|
||||
else {
|
||||
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f);
|
||||
scaling_compression = parms->compression + s->lin_stiffness * fabsf(parms->max_compression - parms->compression);
|
||||
|
||||
if (s->restlen * s->lenfact > ALMOST_ZERO) {
|
||||
k_tension = scaling_tension / (s->restlen * s->lenfact);
|
||||
k_compression = scaling_compression / (s->restlen * s->lenfact);
|
||||
d_tension = parms->tension_damp / (s->restlen * s->lenfact);
|
||||
d_compression = parms->compression_damp / (s->restlen * s->lenfact);
|
||||
}
|
||||
else {
|
||||
// Multiply by some arbitrary large value, just so zero-length springs have enough force.
|
||||
k_tension = scaling_tension * 10000;
|
||||
k_compression = 0; // No compression for zero-length springs
|
||||
d_tension = parms->tension_damp * 10000;
|
||||
d_compression = 0;
|
||||
}
|
||||
|
||||
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, &s->lenfact, k_tension, k_compression,
|
||||
d_tension, d_compression, no_compress, 0.0f,
|
||||
struct_plast, parms->struct_yield_fact, !collision_pass);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
|
||||
#ifdef CLOTH_FORCE_SPRING_BEND
|
||||
float kb, cb, scaling;
|
||||
else if (s->type & CLOTH_SPRING_TYPE_SHEAR) {
|
||||
#ifdef CLOTH_FORCE_SPRING_SHEAR
|
||||
float k, d, scaling;
|
||||
|
||||
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
|
||||
|
||||
scaling = parms->bending + s->stiffness * fabsf(parms->max_bend - parms->bending);
|
||||
kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
|
||||
scaling = parms->shear + s->lin_stiffness * fabsf(parms->max_shear - parms->shear);
|
||||
|
||||
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
|
||||
cb = kb * parms->bending_damping;
|
||||
if (s->restlen * s->lenfact > ALMOST_ZERO) {
|
||||
k = scaling / (s->restlen * s->lenfact);
|
||||
d = parms->shear_damp / (s->restlen * s->lenfact);
|
||||
}
|
||||
else {
|
||||
k = scaling * 10000;
|
||||
d = parms->shear_damp * 10000;
|
||||
}
|
||||
|
||||
BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb);
|
||||
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, &s->lenfact, k, 0.0f, d, 0.0f, true, 0.0f,
|
||||
struct_plast, parms->struct_yield_fact, !collision_pass);
|
||||
#endif
|
||||
}
|
||||
else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) {
|
||||
else if (s->type & CLOTH_SPRING_TYPE_BENDING_HAIR) {
|
||||
#ifdef CLOTH_FORCE_SPRING_BEND
|
||||
float kb, cb, scaling;
|
||||
|
||||
@@ -388,14 +440,14 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
|
||||
* this is crap, but needed due to cloth/hair mixing ...
|
||||
* max_bend factor is not even used for hair, so ...
|
||||
*/
|
||||
scaling = s->stiffness * parms->bending;
|
||||
scaling = s->lin_stiffness * parms->bending;
|
||||
kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
|
||||
|
||||
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
|
||||
cb = kb * parms->bending_damping;
|
||||
cb = kb * 0.5f; // this was multiplied by a constant parms->bending_damping, which is no longer constant
|
||||
|
||||
/* XXX assuming same restlen for ij and jk segments here, this can be done correctly for hair later */
|
||||
BPH_mass_spring_force_spring_bending_angular(data, s->ij, s->kl, s->mn, s->target, kb, cb);
|
||||
BPH_mass_spring_force_spring_bending_hair(data, s->ij, s->kl, s->mn, s->target, kb, cb);
|
||||
|
||||
#if 0
|
||||
{
|
||||
@@ -433,7 +485,7 @@ static void hair_get_boundbox(ClothModifierData *clmd, float gmin[3], float gmax
|
||||
}
|
||||
}
|
||||
|
||||
static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListBase *effectors, float time)
|
||||
static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListBase *effectors, float time, bool collision_pass)
|
||||
{
|
||||
/* Collect forces and derivatives: F, dFdX, dFdV */
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
@@ -444,6 +496,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
|
||||
const MVertTri *tri = cloth->tri;
|
||||
unsigned int mvert_num = cloth->mvert_num;
|
||||
ClothVertex *vert;
|
||||
float struct_plast, bend_plast;
|
||||
|
||||
#ifdef CLOTH_FORCE_GRAVITY
|
||||
/* global acceleration (gravitation) */
|
||||
@@ -504,7 +557,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
|
||||
|
||||
for (LinkNode *link = cloth->springs; link; link = link->next) {
|
||||
ClothSpring *spring = (ClothSpring *)link->link;
|
||||
if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
|
||||
if (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL) {
|
||||
if (hairdata) {
|
||||
hair_ij = &hairdata[spring->ij];
|
||||
hair_kl = &hairdata[spring->kl];
|
||||
@@ -532,13 +585,44 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
|
||||
MEM_freeN(winvec);
|
||||
}
|
||||
|
||||
/* Implementation note:
|
||||
* Plasticity defines how much the springs will retain deformations, after reaching the yield factor.
|
||||
* However, this change accumulates over each time step, so say a spring is stretched above the yield factor,
|
||||
* then at each time step that passes, the rest shape will approach the current position.
|
||||
* This causes simulations with more sub-steps to approach the current shape faster.
|
||||
* This is solved by properly scaling the plasticity value.
|
||||
*
|
||||
* Plasticity progresses according to the sum:
|
||||
* sum_1_to_n((1/x - 1)^(i - 1) / (1/x)^i)
|
||||
* Where 'n' is the number of sub-steps, and 'x' is the plasticity.
|
||||
*
|
||||
* For artistic control, we set sum_1_to_n((x - 1)^(i - 1) / x^i) = a
|
||||
* where the artist now controls 'a', which represents how much the shape
|
||||
* changes in one frame (considering all sub-steps).
|
||||
* This has the partial sum formula:
|
||||
* 1 - ((1/x - 1) * x)^n
|
||||
*
|
||||
* Which we can now set equal to 'a' and easily solve for 'x':
|
||||
* x = 1 - (1-a)^(1/n) */
|
||||
|
||||
struct_plast = clmd->sim_parms->struct_plasticity;
|
||||
|
||||
if (!(struct_plast < FLT_EPSILON || 1.0f - struct_plast < FLT_EPSILON)) {
|
||||
struct_plast = 1.0f - powf(1.0f - struct_plast, clmd->sim_parms->dt);
|
||||
}
|
||||
|
||||
bend_plast = clmd->sim_parms->bend_plasticity;
|
||||
|
||||
if (!(bend_plast < FLT_EPSILON || 1.0f - bend_plast < FLT_EPSILON)) {
|
||||
bend_plast = 1.0f - powf(1.0f - bend_plast, clmd->sim_parms->dt);
|
||||
}
|
||||
|
||||
// calculate spring forces
|
||||
for (LinkNode *link = cloth->springs; link; link = link->next) {
|
||||
ClothSpring *spring = (ClothSpring *)link->link;
|
||||
// only handle active springs
|
||||
if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) {
|
||||
cloth_calc_spring_force(clmd, spring);
|
||||
}
|
||||
if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
|
||||
cloth_calc_spring_force(clmd, spring, struct_plast, bend_plast, collision_pass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +644,7 @@ BLI_INLINE LinkNode *hair_spring_next(LinkNode *spring_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)
|
||||
if (next_spring->type & CLOTH_SPRING_TYPE_STRUCTURAL && next_spring->kl == spring->ij)
|
||||
return next;
|
||||
}
|
||||
return NULL;
|
||||
@@ -669,7 +753,7 @@ static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
|
||||
link = cloth->springs;
|
||||
while (link) {
|
||||
ClothSpring *spring = (ClothSpring *)link->link;
|
||||
if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL)
|
||||
if (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL)
|
||||
link = cloth_continuum_add_hair_segments(grid, cell_scale, cell_offset, cloth, link);
|
||||
else
|
||||
link = link->next;
|
||||
@@ -844,87 +928,62 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* old collision stuff for cloth, use for continuity
|
||||
* until a good replacement is ready
|
||||
*/
|
||||
static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, ListBase *effectors, float frame, float step, float dt)
|
||||
static float cloth_solve_collisions(Object *ob, ClothModifierData *clmd, float step, float dt, float *impulses)
|
||||
{
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
Implicit_Data *id = cloth->implicit;
|
||||
ClothVertex *verts = cloth->verts;
|
||||
float impulse;
|
||||
float max_impulse = 0.0f;
|
||||
int mvert_num = cloth->mvert_num;
|
||||
const float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
|
||||
|
||||
bool do_extra_solve;
|
||||
const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
|
||||
int i;
|
||||
|
||||
if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED))
|
||||
return;
|
||||
if (!(clmd->coll_parms->flags & (CLOTH_COLLSETTINGS_FLAG_ENABLED | CLOTH_COLLSETTINGS_FLAG_SELF)))
|
||||
return 0.0f;
|
||||
if (!clmd->clothObject->bvhtree)
|
||||
return;
|
||||
return 0.0f;
|
||||
|
||||
/* do inertial solve */
|
||||
BPH_mass_spring_solve_velocities_inertial(id);
|
||||
|
||||
BPH_mass_spring_solve_positions(id, dt);
|
||||
|
||||
// update verts to current positions
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
BPH_mass_spring_get_new_position(id, i, verts[i].tx);
|
||||
|
||||
sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
|
||||
copy_v3_v3(verts[i].v, verts[i].tv);
|
||||
zero_v3(verts[i].dcvel);
|
||||
}
|
||||
|
||||
#if 0 /* unused */
|
||||
for (i=0, cv=cloth->verts; i<cloth->mvert_num; i++, cv++) {
|
||||
copy_v3_v3(initial_cos[i], cv->tx);
|
||||
}
|
||||
#endif
|
||||
|
||||
// call collision function
|
||||
// TODO: check if "step" or "step+dt" is correct - dg
|
||||
do_extra_solve = cloth_bvh_objcollision(ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale);
|
||||
|
||||
// copy corrected positions back to simulation
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
float curx[3];
|
||||
BPH_mass_spring_get_position(id, i, curx);
|
||||
// correct velocity again, just to be sure we had to change it due to adaptive collisions
|
||||
sub_v3_v3v3(verts[i].tv, verts[i].tx, curx);
|
||||
}
|
||||
|
||||
if (do_extra_solve) {
|
||||
// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
|
||||
|
||||
if (cloth_bvh_objcollision(ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale)) {
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
|
||||
float newv[3];
|
||||
|
||||
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
|
||||
if ((clmd->sim_parms->vgroup_mass>0) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
|
||||
continue;
|
||||
|
||||
BPH_mass_spring_set_new_position(id, i, verts[i].tx);
|
||||
mul_v3_v3fl(newv, verts[i].tv, spf);
|
||||
BPH_mass_spring_set_new_velocity(id, i, newv);
|
||||
impulse = len_v3(verts[i].dcvel);
|
||||
impulses[i] = impulse;
|
||||
|
||||
if (impulse > max_impulse) {
|
||||
max_impulse = impulse;
|
||||
}
|
||||
|
||||
/* Update position, based on old position, only applying delta caused by collision responce */
|
||||
add_v3_v3v3(verts[i].tx, verts[i].txold, verts[i].dcvel);
|
||||
BPH_mass_spring_set_position(id, i, verts[i].tx);
|
||||
|
||||
/* Update velocity, based on old velocity, only applying delta caused by collision responce */
|
||||
BPH_mass_spring_get_velocity(id, i, verts[i].tv);
|
||||
madd_v3_v3fl(verts[i].tv, verts[i].dcvel, time_multiplier);
|
||||
BPH_mass_spring_set_velocity(id, i, verts[i].tv);
|
||||
}
|
||||
}
|
||||
|
||||
// X = Xnew;
|
||||
BPH_mass_spring_apply_result(id);
|
||||
|
||||
if (do_extra_solve) {
|
||||
ImplicitSolverResult result;
|
||||
|
||||
/* initialize forces to zero */
|
||||
BPH_mass_spring_clear_forces(id);
|
||||
|
||||
// calculate forces
|
||||
cloth_calc_force(clmd, frame, effectors, step);
|
||||
|
||||
// calculate new velocity and position
|
||||
BPH_mass_spring_solve_velocities(id, dt, &result);
|
||||
// cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
|
||||
|
||||
/* note: positions are advanced only once in the main solver step! */
|
||||
|
||||
BPH_mass_spring_apply_result(id);
|
||||
}
|
||||
return max_impulse;
|
||||
}
|
||||
|
||||
static void cloth_clear_result(ClothModifierData *clmd)
|
||||
@@ -937,7 +996,7 @@ static void cloth_clear_result(ClothModifierData *clmd)
|
||||
sres->avg_iterations = 0.0f;
|
||||
}
|
||||
|
||||
static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, int steps)
|
||||
static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, float dt)
|
||||
{
|
||||
ClothSolverResult *sres = clmd->solver_result;
|
||||
|
||||
@@ -946,28 +1005,28 @@ static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *r
|
||||
if (result->status == BPH_SOLVER_SUCCESS) {
|
||||
sres->min_error = min_ff(sres->min_error, result->error);
|
||||
sres->max_error = max_ff(sres->max_error, result->error);
|
||||
sres->avg_error += result->error / (float)steps;
|
||||
sres->avg_error += result->error * dt;
|
||||
}
|
||||
|
||||
sres->min_iterations = min_ii(sres->min_iterations, result->iterations);
|
||||
sres->max_iterations = max_ii(sres->max_iterations, result->iterations);
|
||||
sres->avg_iterations += (float)result->iterations / (float)steps;
|
||||
sres->avg_iterations += (float)result->iterations * dt;
|
||||
}
|
||||
else {
|
||||
/* error only makes sense for successful iterations */
|
||||
if (result->status == BPH_SOLVER_SUCCESS) {
|
||||
sres->min_error = sres->max_error = result->error;
|
||||
sres->avg_error += result->error / (float)steps;
|
||||
sres->avg_error += result->error * dt;
|
||||
}
|
||||
|
||||
sres->min_iterations = sres->max_iterations = result->iterations;
|
||||
sres->avg_iterations += (float)result->iterations / (float)steps;
|
||||
sres->avg_iterations += (float)result->iterations * dt;
|
||||
}
|
||||
|
||||
sres->status |= result->status;
|
||||
}
|
||||
|
||||
int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
|
||||
int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors, DerivedMesh *dm)
|
||||
{
|
||||
/* Hair currently is a cloth sim in disguise ...
|
||||
* Collision detection and volumetrics work differently then.
|
||||
@@ -980,10 +1039,16 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
ClothVertex *verts = cloth->verts/*, *cv*/;
|
||||
unsigned int mvert_num = cloth->mvert_num;
|
||||
float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
|
||||
Implicit_Data *id = cloth->implicit;
|
||||
ColliderContacts *contacts = NULL;
|
||||
int totcolliders = 0;
|
||||
float max_vel, max_elong;
|
||||
float vel;
|
||||
float max_impulse = 0.0f;
|
||||
float tmp_vec[3];
|
||||
float adapt_fact;
|
||||
bool init_vel;
|
||||
float *impulses = (float *)MEM_mallocN(sizeof(*impulses) * mvert_num, "impulse_magnitude_array");
|
||||
|
||||
BKE_sim_debug_data_clear_category("collision");
|
||||
|
||||
@@ -991,29 +1056,47 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
clmd->solver_result = (ClothSolverResult *)MEM_callocN(sizeof(ClothSolverResult), "cloth solver result");
|
||||
cloth_clear_result(clmd);
|
||||
|
||||
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { /* do goal stuff */
|
||||
init_vel = ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INIT_VEL) && (frame == (clmd->point_cache->startframe + 1)));
|
||||
|
||||
/* do goal and velocity stuff */
|
||||
if ((clmd->sim_parms->vgroup_mass > 0) ||
|
||||
(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COMB_GOAL) ||
|
||||
init_vel)
|
||||
{
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
// update velocities with constrained velocities from pinned verts
|
||||
if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
|
||||
if ((verts[i].flags & CLOTH_VERT_FLAG_PINNED) || init_vel) {
|
||||
float v[3];
|
||||
sub_v3_v3v3(v, verts[i].xconst, verts[i].xold);
|
||||
// mul_v3_fl(v, clmd->sim_parms->stepsPerFrame);
|
||||
/* divide by time_scale to prevent constrained velocities from being multiplied */
|
||||
mul_v3_fl(v, 1.0f / clmd->sim_parms->time_scale);
|
||||
BPH_mass_spring_set_velocity(id, i, v);
|
||||
|
||||
if (init_vel) {
|
||||
copy_v3_v3(verts[i].tvold, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (step < tf) {
|
||||
ImplicitSolverResult result;
|
||||
float dt = max_ff((clmd->sim_parms->dt * clmd->sim_parms->timescale * cloth->adapt_fact),
|
||||
(1.0f / clmd->sim_parms->max_subframes));
|
||||
bool is_max;
|
||||
|
||||
/* copy velocities for collision */
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv);
|
||||
copy_v3_v3(verts[i].v, verts[i].tv);
|
||||
max_vel = 0.0f;
|
||||
max_elong = 0.0f;
|
||||
adapt_fact = FLT_MAX;
|
||||
|
||||
if (step + dt > tf) {
|
||||
dt = tf - step;
|
||||
is_max = true;
|
||||
}
|
||||
|
||||
is_max = is_max || ((clmd->sim_parms->max_subframes > 0) && ((1.0f / clmd->sim_parms->max_subframes) > dt));
|
||||
|
||||
if (is_hair) {
|
||||
/* determine contact points */
|
||||
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
|
||||
@@ -1042,12 +1125,17 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
}
|
||||
}
|
||||
|
||||
// calculate collision impulses
|
||||
if (!is_hair) {
|
||||
max_impulse = cloth_solve_collisions(ob, clmd, step, dt, impulses);
|
||||
}
|
||||
|
||||
// calculate forces
|
||||
cloth_calc_force(clmd, frame, effectors, step);
|
||||
cloth_calc_force(clmd, frame, effectors, step, false);
|
||||
|
||||
// calculate new velocity and position
|
||||
BPH_mass_spring_solve_velocities(id, dt, &result);
|
||||
cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame);
|
||||
cloth_record_result(clmd, &result, dt);
|
||||
|
||||
if (is_hair) {
|
||||
cloth_continuum_step(clmd, dt);
|
||||
@@ -1055,15 +1143,107 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
|
||||
BPH_mass_spring_solve_positions(id, dt);
|
||||
|
||||
if (!is_hair) {
|
||||
cloth_collision_solve_extra(ob, clmd, effectors, frame, step, dt);
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
if (clmd->sim_parms->vgroup_trouble > 0) {
|
||||
cloth->max_col_trouble = max_ff(cloth->max_col_trouble, max_impulse);
|
||||
|
||||
MDeformVert *dvert = (MDeformVert *)dm->getVertData(dm, i, CD_MDEFORMVERT);
|
||||
MDeformWeight *weight = defvert_verify_index(dvert, (clmd->sim_parms->vgroup_trouble - 1));
|
||||
if (cloth->max_col_trouble > 0.0f) {
|
||||
verts[i].col_trouble = max_ff(verts[i].col_trouble, impulses[i]);
|
||||
|
||||
weight->weight = verts[i].col_trouble / cloth->max_col_trouble;
|
||||
}
|
||||
}
|
||||
|
||||
BPH_mass_spring_get_new_position(id, i, tmp_vec);
|
||||
vel = len_v3v3(tmp_vec, verts[i].txold);
|
||||
max_vel = max_ff(max_vel, vel);
|
||||
}
|
||||
|
||||
for (LinkNode *link = cloth->springs; link; link = link->next) {
|
||||
ClothSpring *spring = (ClothSpring *)link->link;
|
||||
if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE) && (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL)) {
|
||||
float tmp1[3], tmp2[3], len_old, len_new;
|
||||
|
||||
len_old = len_v3v3(verts[spring->ij].txold, verts[spring->kl].txold);
|
||||
|
||||
BPH_mass_spring_get_new_position(id, spring->ij, tmp1);
|
||||
BPH_mass_spring_get_new_position(id, spring->kl, tmp2);
|
||||
|
||||
len_new = len_v3v3(tmp1, tmp2);
|
||||
|
||||
max_elong = max_ff(max_elong, (len_new / len_old));
|
||||
}
|
||||
}
|
||||
|
||||
/* Adaptive step calculation */
|
||||
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_VEL) {
|
||||
if (max_vel < FLT_EPSILON) {
|
||||
adapt_fact = FLT_MAX;
|
||||
}
|
||||
else {
|
||||
adapt_fact = clmd->sim_parms->max_vel / max_vel * clmd->sim_parms->adjustment_factor;
|
||||
}
|
||||
}
|
||||
|
||||
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_IMP) {
|
||||
float tmp_fact;
|
||||
|
||||
if (max_impulse < FLT_EPSILON) {
|
||||
tmp_fact = FLT_MAX;
|
||||
}
|
||||
else {
|
||||
tmp_fact = clmd->sim_parms->max_imp / max_impulse * clmd->sim_parms->imp_adj_factor;
|
||||
}
|
||||
|
||||
if (tmp_fact < adapt_fact) {
|
||||
adapt_fact = tmp_fact;
|
||||
}
|
||||
}
|
||||
|
||||
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COMPENSATE_INSTABILITY) && (max_elong > 2.0f)) {
|
||||
if (!is_max) {
|
||||
cloth->adapt_fact *= 0.5f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cloth->adapt_fact *= 1.1;
|
||||
cloth->adapt_fact = min_ff(cloth->adapt_fact, 1.0f);
|
||||
}
|
||||
|
||||
if ((clmd->sim_parms->flags & (CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_VEL |
|
||||
CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_IMP |
|
||||
CLOTH_SIMSETTINGS_FLAG_COMPENSATE_INSTABILITY)))
|
||||
{
|
||||
clmd->sim_parms->dt *= adapt_fact;
|
||||
clmd->sim_parms->dt = min_ff(1.0f / clmd->sim_parms->stepsPerFrame, clmd->sim_parms->dt);
|
||||
|
||||
if ((clmd->sim_parms->max_subframes > 0) && ((1.0f / clmd->sim_parms->max_subframes) > clmd->sim_parms->dt)) {
|
||||
clmd->sim_parms->dt = 1.0f / clmd->sim_parms->max_subframes;
|
||||
}
|
||||
|
||||
if (((max_vel > clmd->sim_parms->max_vel) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_VEL)) ||
|
||||
((max_impulse > clmd->sim_parms->max_imp) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES_IMP)) ||
|
||||
((max_elong > 2.0f) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COMPENSATE_INSTABILITY)))
|
||||
{
|
||||
if (!is_max) {
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
BPH_mass_spring_set_motion_state(id, i, verts[i].txold, verts[i].tvold);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BPH_mass_spring_apply_result(id);
|
||||
|
||||
/* move pinned verts to correct position */
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
|
||||
if ((clmd->sim_parms->vgroup_mass > 0) ||
|
||||
(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COMB_GOAL))
|
||||
{
|
||||
if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
|
||||
float x[3];
|
||||
/* divide by time_scale to prevent pinned vertices' delta locations from being multiplied */
|
||||
@@ -1072,7 +1252,7 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
}
|
||||
}
|
||||
|
||||
BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL);
|
||||
BPH_mass_spring_get_motion_state(id, i, verts[i].txold, verts[i].tvold);
|
||||
}
|
||||
|
||||
/* free contact points */
|
||||
@@ -1083,6 +1263,8 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
|
||||
step += dt;
|
||||
}
|
||||
|
||||
MEM_freeN(impulses);
|
||||
|
||||
/* copy results back to cloth data */
|
||||
for (i = 0; i < mvert_num; i++) {
|
||||
BPH_mass_spring_get_motion_state(id, i, verts[i].x, verts[i].v);
|
||||
|
@@ -50,6 +50,7 @@ extern "C" {
|
||||
#define CLOTH_FORCE_GRAVITY
|
||||
#define CLOTH_FORCE_DRAG
|
||||
#define CLOTH_FORCE_SPRING_STRUCTURAL
|
||||
#define CLOTH_FORCE_SPRING_SHEAR
|
||||
#define CLOTH_FORCE_SPRING_BEND
|
||||
#define CLOTH_FORCE_SPRING_GOAL
|
||||
#define CLOTH_FORCE_EFFECTORS
|
||||
@@ -80,6 +81,7 @@ void BPH_mass_spring_set_position(struct Implicit_Data *data, int index, const f
|
||||
void BPH_mass_spring_set_velocity(struct Implicit_Data *data, int index, const float v[3]);
|
||||
void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3]);
|
||||
void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3]);
|
||||
void BPH_mass_spring_get_velocity(struct Implicit_Data *data, int index, float v[3]);
|
||||
|
||||
/* access to modified motion state during solver step */
|
||||
void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3]);
|
||||
@@ -93,6 +95,7 @@ void BPH_mass_spring_add_constraint_ndof1(struct Implicit_Data *data, int index,
|
||||
void BPH_mass_spring_add_constraint_ndof2(struct Implicit_Data *data, int index, const float c1[3], const float dV[3]);
|
||||
|
||||
bool BPH_mass_spring_solve_velocities(struct Implicit_Data *data, float dt, struct ImplicitSolverResult *result);
|
||||
void BPH_mass_spring_solve_velocities_inertial(struct Implicit_Data *data);
|
||||
bool BPH_mass_spring_solve_positions(struct Implicit_Data *data, float dt);
|
||||
void BPH_mass_spring_apply_result(struct Implicit_Data *data);
|
||||
|
||||
@@ -113,12 +116,18 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2,
|
||||
/* Wind force, acting on a vertex */
|
||||
void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
|
||||
/* Linear spring force between two points */
|
||||
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
|
||||
float stiffness, float damping, bool no_compress, float clamp_force);
|
||||
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen, float *lenfact,
|
||||
float tension, float compression, float damp_tension, float damp_compression,
|
||||
bool no_compress, float clamp_force, float plasticity, float yield_fact, bool do_plast);
|
||||
/* Angular spring force between two polygons */
|
||||
bool BPH_mass_spring_force_spring_angular(struct Implicit_Data *data, int i, int j, int *i_a, int *i_b, int len_a, int len_b,
|
||||
float restangorig, float *angoffset, float stiffness, float damping,
|
||||
float plasticity, float yield_ang, bool do_plast);
|
||||
/* Bending force, forming a triangle at the base of two structural springs */
|
||||
bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb);
|
||||
bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen,
|
||||
float kb, float cb);
|
||||
/* Angular bending force based on local target vectors */
|
||||
bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k,
|
||||
bool BPH_mass_spring_force_spring_bending_hair(struct Implicit_Data *data, int i, int j, int k,
|
||||
const float target[3], float stiffness, float damping);
|
||||
/* Global goal spring */
|
||||
bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -1132,6 +1133,11 @@ bool BPH_mass_spring_solve_velocities(Implicit_Data *data, float dt, ImplicitSol
|
||||
return result->status == BPH_SOLVER_SUCCESS;
|
||||
}
|
||||
|
||||
void BPH_mass_spring_solve_velocities_inertial(Implicit_Data *data)
|
||||
{
|
||||
cp_lfvector(data->Vnew, data->V, data->M[0].vcount);
|
||||
}
|
||||
|
||||
bool BPH_mass_spring_solve_positions(Implicit_Data *data, float dt)
|
||||
{
|
||||
int numverts = data->M[0].vcount;
|
||||
@@ -1202,6 +1208,11 @@ void BPH_mass_spring_set_new_position(struct Implicit_Data *data, int index, con
|
||||
world_to_root_v3(data, index, data->Xnew[index], x);
|
||||
}
|
||||
|
||||
void BPH_mass_spring_get_velocity(struct Implicit_Data *data, int index, float v[3])
|
||||
{
|
||||
root_to_world_v3(data, index, v, data->V[index]);
|
||||
}
|
||||
|
||||
void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3])
|
||||
{
|
||||
root_to_world_v3(data, index, v, data->Vnew[index]);
|
||||
@@ -1577,44 +1588,84 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3]
|
||||
sub_m3_m3m3(data->dFdV[block_ij].m, data->dFdV[block_ij].m, dfdv);
|
||||
}
|
||||
|
||||
bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
|
||||
float stiffness, float damping, bool no_compress, float clamp_force)
|
||||
bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlenorig, float *lenfact,
|
||||
float tension, float compression, float damp_tension, float damp_compression,
|
||||
bool no_compress, float clamp_force, float plasticity, float yield_fact, bool do_plast)
|
||||
{
|
||||
float extent[3], length, dir[3], vel[3];
|
||||
float f[3], dfdx[3][3], dfdv[3][3];
|
||||
float damping = 0;
|
||||
float restlen;
|
||||
|
||||
// calculate elonglation
|
||||
restlen = (*lenfact) * restlenorig;
|
||||
|
||||
/* calculate elonglation */
|
||||
spring_length(data, i, j, extent, dir, &length, vel);
|
||||
|
||||
/* This code computes not only the force, but also its derivative.
|
||||
Zero derivative effectively disables the spring for the implicit solver.
|
||||
Thus length > restlen makes cloth unconstrained at the start of simulation. */
|
||||
if ((length >= restlen && length > 0) || no_compress) {
|
||||
float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
|
||||
/* Calculate tension forces */
|
||||
if (length >= restlen) {
|
||||
float stretch_force;
|
||||
damping = damp_tension;
|
||||
|
||||
stretch_force = tension * (length - restlen);
|
||||
|
||||
stretch_force = stiffness * (length - restlen);
|
||||
if (clamp_force > 0.0f && stretch_force > clamp_force) {
|
||||
stretch_force = clamp_force;
|
||||
}
|
||||
mul_v3_v3fl(f, dir, stretch_force);
|
||||
|
||||
// Ascher & Boxman, p.21: Damping only during elonglation
|
||||
// something wrong with it...
|
||||
madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
|
||||
dfdx_spring(dfdx, dir, length, restlen, tension);
|
||||
|
||||
dfdx_spring(dfdx, dir, length, restlen, stiffness);
|
||||
dfdv_damp(dfdv, dir, damping);
|
||||
/* compute plasticity offset factor */
|
||||
if (do_plast && (restlenorig > 0.0f) && (length > restlen * yield_fact)) {
|
||||
restlen += ((length / yield_fact) - restlen) * plasticity;
|
||||
*lenfact = restlen / restlenorig;
|
||||
}
|
||||
}
|
||||
|
||||
apply_spring(data, i, j, f, dfdx, dfdv);
|
||||
/* Calculate compression forces */
|
||||
/* this is based on the Choi and Ko bending model, which works surprisingly well for compression */
|
||||
else if (!no_compress) {
|
||||
float kb = compression;
|
||||
float cb = kb; /* cb equal to kb seems to work, but a factor can be added if necessary */
|
||||
damping = damp_compression;
|
||||
|
||||
return true;
|
||||
mul_v3_v3fl(f, dir, fbstar(length, restlen, kb, cb));
|
||||
|
||||
outerproduct(dfdx, dir, dir);
|
||||
mul_m3_fl(dfdx, fbstar_jacobi(length, restlen, kb, cb));
|
||||
|
||||
/* compute plasticity offset factor */
|
||||
if (do_plast && (restlenorig > 0.0f) && length < restlen / yield_fact) {
|
||||
restlen -= (restlen - (length * yield_fact)) * plasticity;
|
||||
*lenfact = restlen / restlenorig;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
zero_v3(f);
|
||||
zero_m3(dfdx);
|
||||
|
||||
/* compute plasticity offset factor */
|
||||
/* plasticity has to be computed even for non-compressive springs in a compression condition,
|
||||
* otherwise issues occur where shearing gets unconstrained when cloth undergoes compression */
|
||||
if (do_plast && length < restlen / yield_fact) {
|
||||
restlen -= (restlen - (length * yield_fact)) * plasticity;
|
||||
*lenfact = restlen / restlenorig;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate damping forces */
|
||||
madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
|
||||
dfdv_damp(dfdv, dir, damping);
|
||||
|
||||
apply_spring(data, i, j, f, dfdx, dfdv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
|
||||
bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, float kb, float cb)
|
||||
bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen,
|
||||
float kb, float cb)
|
||||
{
|
||||
float extent[3], length, dir[3], vel[3];
|
||||
|
||||
@@ -1641,6 +1692,144 @@ bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, flo
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE bool spring_angle(Implicit_Data *data, int i, int j, int *i_a, int *i_b, int len_a, int len_b,
|
||||
float r_dir_a[3], float r_dir_b[3],
|
||||
float *r_angle, float r_vel_a[3], float r_vel_b[3])
|
||||
{
|
||||
float co_i[3], co_j[3], co_a[3], co_b[3];
|
||||
float tmp1[3], tmp2[3], vec_e[3];
|
||||
float sin, cos;
|
||||
float (*array_a)[3] = MEM_mallocN(sizeof(*array_a) * len_a, "spring angle poly a");
|
||||
float (*array_b)[3] = MEM_mallocN(sizeof(*array_b) * len_b, "spring angle poly b");
|
||||
int x;
|
||||
|
||||
/* assign poly vert coords to arrays */
|
||||
for (x = 0; x < len_a; x++) {
|
||||
copy_v3_v3(array_a[x], data->X[i_a[x]]);
|
||||
}
|
||||
|
||||
for (x = 0; x < len_b; x++) {
|
||||
copy_v3_v3(array_b[x], data->X[i_b[x]]);
|
||||
}
|
||||
|
||||
/* get edge vert coords and poly centroid coords. */
|
||||
copy_v3_v3(co_i, data->X[i]);
|
||||
copy_v3_v3(co_j, data->X[j]);
|
||||
mid_v3_v3_array(co_a, array_a, len_a);
|
||||
mid_v3_v3_array(co_b, array_b, len_b);
|
||||
|
||||
/* find dir for poly a */
|
||||
sub_v3_v3v3(tmp1, co_j, co_a);
|
||||
sub_v3_v3v3(tmp2, co_i, co_a);
|
||||
|
||||
cross_v3_v3v3(r_dir_a, tmp1, tmp2);
|
||||
normalize_v3(r_dir_a);
|
||||
|
||||
/* find dir for poly b */
|
||||
sub_v3_v3v3(tmp1, co_i, co_b);
|
||||
sub_v3_v3v3(tmp2, co_j, co_b);
|
||||
|
||||
cross_v3_v3v3(r_dir_b, tmp1, tmp2);
|
||||
normalize_v3(r_dir_b);
|
||||
|
||||
/* find edge direction */
|
||||
sub_v3_v3v3(vec_e, co_i, co_j);
|
||||
normalize_v3(vec_e);
|
||||
|
||||
/* calculate angle between polys */
|
||||
cos = dot_v3v3(r_dir_a, r_dir_b);
|
||||
|
||||
cross_v3_v3v3(tmp1, r_dir_a, r_dir_b);
|
||||
sin = dot_v3v3(tmp1, vec_e);
|
||||
|
||||
*r_angle = atan2(sin, cos);
|
||||
|
||||
/* assign poly vert velocities to arrays */
|
||||
for (x = 0; x < len_a; x++) {
|
||||
copy_v3_v3(array_a[x], data->V[i_a[x]]);
|
||||
}
|
||||
|
||||
for (x = 0; x < len_b; x++) {
|
||||
copy_v3_v3(array_b[x], data->V[i_b[x]]);
|
||||
}
|
||||
|
||||
/* calculate poly centroid velocities */
|
||||
mid_v3_v3_array(r_vel_a, array_a, len_a);
|
||||
mid_v3_v3_array(r_vel_b, array_b, len_b);
|
||||
|
||||
/* edge velocity, to remove rigid body velocity component from centroid velocities */
|
||||
add_v3_v3v3(tmp1, data->V[i], data->V[j]);
|
||||
mul_v3_fl(tmp1, 0.5f);
|
||||
|
||||
sub_v3_v3(r_vel_a, tmp1);
|
||||
sub_v3_v3(r_vel_b, tmp1);
|
||||
|
||||
MEM_freeN(array_a);
|
||||
MEM_freeN(array_b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Angular springs roughly based on the bending model proposed by Baraff and Witkin in "Large Steps in Cloth Simulation" */
|
||||
bool BPH_mass_spring_force_spring_angular(Implicit_Data *data, int i, int j, int *i_a, int *i_b, int len_a, int len_b,
|
||||
float restangorig, float *angoffset, float stiffness, float damping,
|
||||
float plasticity, float yield_ang, bool do_plast)
|
||||
{
|
||||
float angle, dir_a[3], dir_b[3], vel_a[3], vel_b[3];
|
||||
float f_a[3], f_b[3], f_e[3];
|
||||
float force;
|
||||
float restang;
|
||||
int x;
|
||||
|
||||
restang = restangorig + *angoffset;
|
||||
|
||||
spring_angle(data, i, j, i_a, i_b, len_a, len_b,
|
||||
dir_a, dir_b, &angle, vel_a, vel_b);
|
||||
|
||||
/* spring force */
|
||||
force = stiffness * (angle - restang);
|
||||
|
||||
/* compute plasticity offset */
|
||||
if (do_plast) {
|
||||
if (angle > restang) {
|
||||
if (angle - restang > yield_ang) {
|
||||
restang += (angle - restang - yield_ang) * plasticity;
|
||||
*angoffset = restang - restangorig;
|
||||
}
|
||||
}
|
||||
else if (angle < restang) {
|
||||
if (restang - angle > yield_ang) {
|
||||
restang -= (restang - angle - yield_ang) * plasticity;
|
||||
*angoffset = restang - restangorig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* damping force */
|
||||
force += -damping * (dot_v3v3(vel_a, dir_a) + dot_v3v3(vel_b, dir_b));
|
||||
|
||||
mul_v3_v3fl(f_a, dir_a, force / len_a);
|
||||
mul_v3_v3fl(f_b, dir_b, force / len_b);
|
||||
|
||||
for (x = 0; x < len_a; x++) {
|
||||
add_v3_v3(data->F[i_a[x]], f_a);
|
||||
}
|
||||
|
||||
for (x = 0; x < len_b; x++) {
|
||||
add_v3_v3(data->F[i_b[x]], f_b);
|
||||
}
|
||||
|
||||
mul_v3_v3fl(f_a, dir_a, force * 0.5f);
|
||||
mul_v3_v3fl(f_b, dir_b, force * 0.5f);
|
||||
|
||||
add_v3_v3v3(f_e, f_a, f_b);
|
||||
|
||||
sub_v3_v3(data->F[i], f_e);
|
||||
sub_v3_v3(data->F[j], f_e);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Jacobian of a direction vector.
|
||||
* Basically the part of the differential orthogonal to the direction,
|
||||
* inversely proportional to the length of the edge.
|
||||
@@ -1664,7 +1853,7 @@ BLI_INLINE void spring_grad_dir(Implicit_Data *data, int i, int j, float edge[3]
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE void spring_angbend_forces(Implicit_Data *data, int i, int j, int k,
|
||||
BLI_INLINE void spring_hairbend_forces(Implicit_Data *data, int i, int j, int k,
|
||||
const float goal[3],
|
||||
float stiffness, float damping,
|
||||
int q, const float dx[3], const float dv[3],
|
||||
@@ -1713,7 +1902,7 @@ BLI_INLINE void spring_angbend_forces(Implicit_Data *data, int i, int j, int k,
|
||||
}
|
||||
|
||||
/* Finite Differences method for estimating the jacobian of the force */
|
||||
BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int i, int j, int k,
|
||||
BLI_INLINE void spring_hairbend_estimate_dfdx(Implicit_Data *data, int i, int j, int k,
|
||||
const float goal[3],
|
||||
float stiffness, float damping,
|
||||
int q, float dfdx[3][3])
|
||||
@@ -1732,11 +1921,11 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int i, int j,
|
||||
/* XXX TODO offset targets to account for position dependency */
|
||||
|
||||
for (a = 0; a < 3; ++a) {
|
||||
spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
spring_hairbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
q, dvec_pos[a], dvec_null[a], f);
|
||||
copy_v3_v3(dfdx[a], f);
|
||||
|
||||
spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
spring_hairbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
q, dvec_neg[a], dvec_null[a], f);
|
||||
sub_v3_v3(dfdx[a], f);
|
||||
|
||||
@@ -1747,7 +1936,7 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data, int i, int j,
|
||||
}
|
||||
|
||||
/* Finite Differences method for estimating the jacobian of the force */
|
||||
BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int i, int j, int k,
|
||||
BLI_INLINE void spring_hairbend_estimate_dfdv(Implicit_Data *data, int i, int j, int k,
|
||||
const float goal[3],
|
||||
float stiffness, float damping,
|
||||
int q, float dfdv[3][3])
|
||||
@@ -1766,11 +1955,11 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int i, int j,
|
||||
/* XXX TODO offset targets to account for position dependency */
|
||||
|
||||
for (a = 0; a < 3; ++a) {
|
||||
spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
spring_hairbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
q, dvec_null[a], dvec_pos[a], f);
|
||||
copy_v3_v3(dfdv[a], f);
|
||||
|
||||
spring_angbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
spring_hairbend_forces(data, i, j, k, goal, stiffness, damping,
|
||||
q, dvec_null[a], dvec_neg[a], f);
|
||||
sub_v3_v3(dfdv[a], f);
|
||||
|
||||
@@ -1783,7 +1972,7 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data, int i, int j,
|
||||
/* Angular spring that pulls the vertex toward the local target
|
||||
* See "Artistic Simulation of Curly Hair" (Pixar technical memo #12-03a)
|
||||
*/
|
||||
bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, int j, int k,
|
||||
bool BPH_mass_spring_force_spring_bending_hair(Implicit_Data *data, int i, int j, int k,
|
||||
const float target[3], float stiffness, float damping)
|
||||
{
|
||||
float goal[3];
|
||||
@@ -1799,18 +1988,18 @@ bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, in
|
||||
|
||||
world_to_root_v3(data, j, goal, target);
|
||||
|
||||
spring_angbend_forces(data, i, j, k, goal, stiffness, damping, k, vecnull, vecnull, fk);
|
||||
spring_hairbend_forces(data, i, j, k, goal, stiffness, damping, k, vecnull, vecnull, fk);
|
||||
negate_v3_v3(fj, fk); /* counterforce */
|
||||
|
||||
spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, i, dfk_dxi);
|
||||
spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, j, dfk_dxj);
|
||||
spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, k, dfk_dxk);
|
||||
spring_hairbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, i, dfk_dxi);
|
||||
spring_hairbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, j, dfk_dxj);
|
||||
spring_hairbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, k, dfk_dxk);
|
||||
copy_m3_m3(dfj_dxi, dfk_dxi); negate_m3(dfj_dxi);
|
||||
copy_m3_m3(dfj_dxj, dfk_dxj); negate_m3(dfj_dxj);
|
||||
|
||||
spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, i, dfk_dvi);
|
||||
spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, j, dfk_dvj);
|
||||
spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, k, dfk_dvk);
|
||||
spring_hairbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, i, dfk_dvi);
|
||||
spring_hairbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, j, dfk_dvj);
|
||||
spring_hairbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, k, dfk_dvk);
|
||||
copy_m3_m3(dfj_dvi, dfk_dvi); negate_m3(dfj_dvi);
|
||||
copy_m3_m3(dfj_dvj, dfk_dvj); negate_m3(dfj_dvj);
|
||||
|
||||
|
@@ -162,6 +162,7 @@ endif()
|
||||
extern_wcwidth
|
||||
bf_intern_libmv
|
||||
extern_sdlew
|
||||
extern_bullet
|
||||
)
|
||||
|
||||
if(NOT WITH_SYSTEM_GLOG)
|
||||
|
@@ -533,6 +533,7 @@ void ED_object_constraint_tag_update(struct Main *bmain, struct Object *ob, stru
|
||||
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE
|
||||
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE
|
||||
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO
|
||||
float ED_vgroup_combined_vert_weight(const struct Object *ob, const int vertnum, const int mode) RET_ZERO
|
||||
int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode) RET_ZERO
|
||||
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode) RET_ZERO
|
||||
|
||||
|
Submodule source/tools updated: 87f7038ee8...896c5f7895
Reference in New Issue
Block a user