1
1

Compare commits

...

109 Commits

Author SHA1 Message Date
ceddd2bcd9 Fix collision multithreading inconsistency
Multithreading makes collisions be detected in different orders, causing
the clustering step of collision resolution to generate possibly
slightly different results on each run. This commit makes collision
order consistent.
2018-09-19 15:55:53 +02:00
f47ace53f2 Fix mistake in collision indexing 2018-09-19 15:55:53 +02:00
7eb44c2f1b Fix incorrect poll function signature in rna_cloth.c 2018-07-23 01:36:39 +02:00
13818c47cf Merge branch 'master' into cloth-improvements 2018-07-19 16:33:44 +02:00
d7f5520fdf Merge branch 'master' into cloth-improvements 2017-04-20 18:37:07 +02:00
bbf2f3ac2a Merge branch 'master' into cloth-improvements 2017-04-13 15:48:55 +02:00
320771dc74 Copy cache when copying cloth object 2017-04-04 11:56:25 +02:00
607a2d80d3 Replace collision spinlocks with atomic_ops 2017-04-03 16:49:38 +02:00
bc738592df Multithread self collision detection 2017-04-03 16:04:41 +02:00
6b818dcf79 Self collision refactor (prep for threading) 2017-04-03 16:04:41 +02:00
102b2a7418 Multithread object collision detection 2017-04-03 16:04:32 +02:00
5d07a070cb Collision refactor (prep for threading) 2017-04-03 12:00:23 +02:00
87825084d5 Implement cloth trouble indication map
This allows one to set a vertex group, to which "trouble" data is
written. This allows one to see where issues occured for instance in the
event of a cloth explosion.
2017-03-30 19:51:53 +02:00
d6a6417e3b Fix silly mistake in collision impulse clamping
Forgot to ignore clamping when set to zero, so collisions were just
being completely ignored at that value :\
2017-03-19 12:34:11 -03:00
03412896f6 Fix vertex group influence UI 2017-03-18 19:41:34 -03:00
87625ccce9 Fix blenderplayer linking 2017-03-18 19:35:41 -03:00
666a9385c4 Implement collision impulse clamping (to prevent explosions) 2017-03-18 16:53:12 -03:00
6249fb68e0 Fix max subframe handling in adaptive subframes 2017-03-18 13:04:19 -03:00
6edd60d959 Implement instability compensation 2017-03-18 13:03:54 -03:00
fe9debc47b Fix critical collision bug
Collision object coordinates were not being updated when moving back in
time, causing simulation recalculations to somethimes have the collision
object only at the final position on the first simulated frame.

This also changes collision objects to use static bvh (like the cloth
bvh), which should cause a slight performance improvement.
2017-03-17 00:49:58 -03:00
84213a3ce1 Fix basemesh target object poll function 2017-03-16 22:42:50 -03:00
3f0b3a4fb0 Merge branch 'master' into cloth-develop 2017-03-16 17:56:34 -03:00
5ad6bdb021 Implement rest planarity factor scaling 2017-03-15 05:36:44 -03:00
d6bee4bffd Implement weight keys for pinning 2017-03-14 02:50:49 -03:00
b034660643 Implement combined vertex weight by group influeces (Weight Keys) 2017-03-14 02:50:49 -03:00
dbb20c3913 Refactor: remove unnecessary re-initialization
Cloth was being re-initialized whenever pinning settings were changed.
This has been necessary in the past, as pins were only computed during
initialization, but ever since animated vertex weight support was added,
by having pins recalculate on every step, this re-initialization has
become unnecessary.
2017-03-14 02:50:40 -03:00
5315339162 Refactor: remove goal springs in favor of per vert computation 2017-03-14 01:00:16 -03:00
7fa9ab01d6 Implement animated cloth velocity initialization
This allows the initial cloth velocity to be set by the vertex
velocities in the underlying animation.
2017-03-13 01:31:10 -03:00
c6f05db912 Add support for external basemesh object
This allows the usage of a different object as the rest shape, which
enables more flexibility regarding animated rest shapes.
2017-03-12 16:26:49 -03:00
a87cd01425 Remove a few warnings and some cleanup 2017-03-04 01:38:44 -03:00
77df327fa8 Implement normal override for the new collision function 2017-03-04 01:12:11 -03:00
0607cd2e15 Replace plNearestPoints with a deticated solution
Implement a dedicated collision detection function (was previously
relying on Bullet's generic `plNearestPoints`).
This function computes all the collision data to be used for response:
coordinates, distance, direction vector.

This new function has three advantages:

* Remove a dependency from cloth simulation (Bullet).
* Give more pleasing collision results (this function is tailored
specifically for our collision response method).
* Much faster computation (not benchmarked extensively, but observed
overal simulation time was cut roughly in half with "collision-heavy"
simulations).
2017-03-04 00:24:35 -03:00
9f0176d795 Simplify impulse clustering pointer stuff 2017-03-03 20:41:34 -03:00
215df08c0f Expose slice intersection function (math_geom) 2017-03-03 20:36:50 -03:00
7b6d09e9bd Fix stack overflow in spring angle calculation 2017-02-12 01:48:10 -02:00
5e28df26de Fix regression on plasticity caused by sewing springs
I must have been sleeping when I committed the fix for the sewing
springs regression, causing another silly regression on plasticity...
2017-02-04 03:57:26 -02:00
e3b5229da2 Add collision response quality control 2017-02-03 19:59:08 -02:00
bc3b482b9d Implement separate normal override and single sided collisions
This adds single sided collisions without necessarily using normal
override, and adds a separate normal override option. (code can do with
some cosmetic cleanup)

Also removed a printf I had forgotten.
2017-02-01 14:00:13 -02:00
6f9cddec21 Implement collision impulse based adaptive step size calculation 2017-02-01 04:09:54 -02:00
1cc8f2d79b Apply all object collisions simultaneously
This makes all multi-object collisions be solved simultaneously, as not
to give any of them priority over the others (as in the sequential
collision solve that was implemented)

Note that self collisions have not been integrated, and are instead
solved independently after the object collisions. This is so that they
don't have to fight against the object collisions, as those are
generally more robust, and might cause issues with the self collisions.
2017-02-01 01:17:00 -02:00
fdea8ecb5b Implement velocity based adaptive step size calculation 2017-02-01 01:15:13 -02:00
06090d7a31 Implement usage of dt property (preparation for adaptive time steps) 2017-01-31 17:32:18 -02:00
8d1b6b76a2 Use impulse clustering for self collisions
Also adjust impulse scaling to work better with the new clustering.
2017-01-31 03:14:56 -02:00
a32251b4ed Use optimized approximated impulse clustering 2017-01-31 01:53:46 -02:00
4e42d01c65 Implement directional cluster based impulse pruning 2017-01-31 01:39:52 -02:00
ade28fe8a2 Optimization: Use inertial solve for pre-collision
Instead of doing a full implicit pre-collision solve, do a simple
inertial solve (avance using velocities from previous step), this saves
time by doing one less solve per step, and also improves resting
stability by eliminating the influence of external forces disturbing the
mesh in contacting areas.

This improves general cloth performance by about 30-40% in relation to
the new cloth code, and improves performance by about 3 times in
relation to the original cloth code. This also makes collisions more
reliable by removing the need for positional interpolation, and thus
decreases the number of subframes required for a successful solve.
2017-01-30 03:47:11 -02:00
115aea5f2f Optimization: Use static BVH for collision intersection
No need to use moving BVH for intersection checking, as in the end
collisions are only evaluated at the next state anyway, so can use
static BVH to reduce the amount of intersections to check.

Moving BVH will only make sense if ccd is implemented.
2017-01-29 20:40:43 -02:00
5de2fc2679 Use pre-solved locations for col response evaluation 2017-01-29 20:35:46 -02:00
e735eda393 Bring back impulse scaled repulses
It seems I was a bit too optimistic in thinking that just distance based
repulses could handle contacts nicely. Turns out impulse scaled repulses
really have enough of an influence in making the collision response more
effective, that it is worth keeping it for now, even if at the cost of a
very slight stability reduction and and a bit of an increase in
collision elasticity.

I hope to come up with a better solution, and elliminate this, after
cluster based impulse pruning is implemented.
2017-01-28 02:40:14 -02:00
6054fff2a6 Fix regression on sewing springs caused by plasticity 2017-01-24 00:25:45 -02:00
7d99e1418b Remove epsilon from velocity conditional.
Also added a comment about the wrong duplicate impulse elimination being
used.
2017-01-23 17:25:05 -02:00
983d671df8 Fix mistake with backside relative velocities
also removed unused include...
2017-01-22 04:00:38 -02:00
0018eae5ed Enable compression springs for hair 2017-01-21 00:46:30 -02:00
add9835df6 Clean-up some collision data allocation stuff
Self collision pointer logic has been simplified and allocations
reduced, as it only collides with one object (self).

Also, allocation size for all collisions has been reduced to 1/4,
because it was allocating extra space for deprecated stuff.
2017-01-20 02:31:04 -02:00
309b12ac27 Implement self col groups for new self col system 2017-01-20 02:03:05 -02:00
0f5dc7ad80 Remove edgeset stuff (no longer used) 2017-01-20 00:42:43 -02:00
82d3cd586c Remove unused selfbvh stuff 2017-01-19 22:12:48 -02:00
73b9899c92 Move use_normal to col object settings (was in cloth settings) 2017-01-19 22:10:14 -02:00
b2dc669ee7 Use proper friction property for self col and redesign col UI 2017-01-19 22:08:25 -02:00
8d454ff13a Separate self collision distance from object collision distance 2017-01-19 21:23:31 -02:00
998900794d Remove self collision quality (integrated with object collision)
Self collisions are now impulse based, and utilize the same solver as
the object collisions. Having separate quality controls would cause
issues when self and object collisions occur simultaneously.
2017-01-19 20:10:05 -02:00
61f8a1cfd7 Remove old repulsion stuff
Repulsions were long unused, and are now more obsolete than ever, with
the more stable collision response.
2017-01-19 20:06:58 -02:00
403b835992 Remove unused functions in collision.c 2017-01-19 19:38:55 -02:00
8759ec4eae Move fricion to collider object settings 2017-01-19 12:38:07 -02:00
80ed76cb66 New self collision implementation (needs some cleanup) 2017-01-19 02:13:01 -02:00
2d48769a8b Fix stability issue and further make collisions inelastic
The repulse when colliding points are approaching was being scaled
incorrectly by the impulse, causing some undesired elasticity in the
collision. I imagine this was a workaround to avoid penetrations
because the collision responce was being calculated with respect to
the incorrect state, but this is no longer necessary now that that has
been fixed. (had missed this case in my previous elasticity commit)

Other than that, I have bary interpolated the static repulses to avoid a
nasty instability issue in some corner cases.
2017-01-18 23:06:33 -02:00
c8d1bbf31c Fix collision distance calculation (makes collisions perfectly inelastic)
Collision distance was computed with respect to the positions before the
pre-collision solve, but should rather be computed with respect to the
newly solved positions.

This fixes the issue of the collisions being semi-elastic (bouncy),
making them pretty much perfectly inelastic. This also improves the
effectiveness of the collision response, preventing penetrations even
with far less collision steps.
2017-01-17 22:05:25 -02:00
d4a46809d0 Implement single sided collisions 2017-01-16 23:31:22 -02:00
9596871292 Fix collision response scalings (had missed a few before) 2017-01-16 01:42:13 -02:00
22f67557d1 Make caching a bit more sane (fixes plasticity issue)
This cleans up the cloth caching logic a bit.

Now, a simulation step only occurs if the current time is exactly one
frame after the last simulated step, thus preventing time gaps and
runtime data corruption. Also, now the cloth is only re-initialized
if the cache is actually outdated, instead of always being reset when
on the first frame.

This solves a bug where the cache was freed when moving the time to
a point within the cached period.

These changes also fix the issue of non-cached runtime simulation state
properties (e.g. plasticity) being reset when going to the first frame
or retaining a future state when simulating over an existing cache with
time gaps.
2017-01-13 20:10:22 -02:00
63f023111d Apply collision responce on state before pre-collision solve (breaks selfcol)
This uses the pre-collision solve result only to find the collisions and
calculate the responce impulses, but rolls back to before the
pre-collision solve when it is time to actually apply the responce.

This prevents the cloth from undergoing a double solve per time-step,
which essentially made colliding clothes move much faster than
non-colliding clothes.
2017-01-12 22:41:50 -02:00
66d19ebeb3 Remove weird impulse scaling 2017-01-12 14:54:43 -02:00
69e8ee7851 Fix collision extra solve update and remove redundant result applies 2017-01-12 02:05:28 -02:00
5aacca55fa UI Cleanup: Add new property scaling panel 2017-01-07 02:04:57 -02:00
a6c0ab8cb5 UI Cleanup: Add dedicated cloth shape panel 2017-01-07 00:44:25 -02:00
fb542eadd4 UI Cleanup: Separate object collisions from self collisions 2017-01-07 00:44:25 -02:00
f30048504b UI Cleanup: Remove scaling flag 2017-01-07 00:44:24 -02:00
e3df66f1b7 UI Cleanup: Separate shrinking from sewing 2017-01-07 00:44:24 -02:00
d1b25a08d7 UI Cleanup: Remove cloth pin flag 2017-01-07 00:44:24 -02:00
3fb5d20cc0 UI Cleanup: Reorganize main cloth panel and improve tool-tips
Also removed the "vel_damping" option from the UI, because it sucks,
and nobody shall ever use, or speak of it again. (though I left its
implementation and RNA definition, for historic reasons perhaps?)
2017-01-07 00:44:24 -02:00
63aaa7c84a Fix artifacts caused by double plastic computation whith collisions 2017-01-06 18:00:23 -02:00
929aa7c046 Fix plasticity issue with shearing springs 2017-01-06 04:45:37 -02:00
55b9eebede Implement rest planarity factor option 2017-01-06 04:45:26 -02:00
887dfc298d Refactor/Optimization: Integrate bend springs into struct/shear
A bending spring runs along each structural and shearing spring. Taking
advantage of that, this integrates the required data for both into the
same spring struct instance. This greatly simplifies bending spring
generation code, and also reduces the memory usage for spring storage
in about 40-50%.

This change also fixes minor memory management issues.
2017-01-05 20:48:48 -02:00
a2dbe9f340 Cleanup: Fix some returns and potential memory leaks 2017-01-05 00:43:54 -02:00
81a8a015b8 Cleanup: fix some types, and remove unused var 2017-01-05 00:38:31 -02:00
4cbb4bc6be Fix mistake in angular spring generation 2017-01-05 00:33:19 -02:00
85af281f85 Implement angular spring support for dynamic mesh 2017-01-04 21:49:56 -02:00
d12c650349 Implement proper sub-step independent plasticity scaling 2017-01-04 19:47:48 -02:00
bb32d9240f Implement angular plasticity (has issues)
Same issues as the previous structural plasticity commit.
2016-12-15 21:10:27 -02:00
eca3877ac4 Implement structural plasticity (has issues)
The issue here is that the rest length factor isn't cached, because the
cache only allows you to store a single type of data per cache (I'll try
to fix this later), so if you interrupt the simulation midway through,
going to the start frame, the plastic deformations will be reset.
2016-12-15 21:10:11 -02:00
e843c10ad5 Fixed some typos, and missing initializations 2016-12-15 15:21:29 -02:00
dc526671c7 Implement angular bending damping 2016-12-08 19:35:33 -02:00
1d8a08fb9f Add some comments about methods used for mass-spring model 2016-12-08 16:32:09 -02:00
54186c5aa9 Set better default values for the new mass-spring model 2016-12-08 16:32:08 -02:00
f9dad94d9e Implement bending springs along shear springs within polygons
This adds bending springs within polygons, so that they resist
changing planarity.
2016-12-08 16:32:08 -02:00
8a0d8ddf27 Implement shear springs for ngons 2016-12-08 16:32:08 -02:00
cb4d349803 Initial implementation of angular bending springs
This implements bending resistant forces between adjacent polygons in
cloth simulation. Note that derivatives are not yet included in the
computations (and might not even be needed, as the simulation is already
quite stable). Angular damping is not yet implemented either.
2016-12-08 16:31:51 -02:00
ce6227b6be Add cent_poly_v3 function 2016-12-06 22:04:59 -02:00
04e157e44a Rename angular hair spring things to hair instead of angular
This is to make a clear distinction between the existing angular hair
springs, and the new generic angular springs.
2016-12-05 21:39:29 -02:00
5d2a092f40 Scale damping by spring length as well
I had forgotten to scale the damping forces...
This made for uneven damping on irregular meshes.
2016-12-05 13:01:55 -02:00
73fd331025 Fix previous error with spring length scaling
Zero-length springs weren't being scaled properly, leading to phantom
forces that introduced rigid-body motion into the simulation.
2016-12-05 12:58:57 -02:00
56c21ff707 Implement improved compression model
This implements the Choi and Ko compression model, with an added damping
component, instead of using the same model as for tension, which
improves stability of the internal forces.
2016-12-05 12:15:12 -02:00
c03db4c501 Code clean-up (remove unnecessary struct members and add comments)
Spring forces and jacobians (f, dfdx and dfdv), were unnecessarily being
stored in sring struct. They are only used locally at computation time,
and don't have to remain in memory.

editrestlen was unused.
2016-12-04 01:49:57 -02:00
fa5669164b Implement separate tension and compression components 2016-12-01 10:15:36 -02:00
5721918848 Separate shear damping from structural damping 2016-11-30 17:44:27 -02:00
dc6fd8a257 Make structural springs act in both extension and compression 2016-11-30 17:05:35 -02:00
fe5735c6cf Fix spring force scaling based on length 2016-11-30 17:04:59 -02:00
97b232ec70 Separate cloth shear from structural stiffness 2016-11-30 00:26:13 -02:00
34 changed files with 3210 additions and 1491 deletions

View File

@@ -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"

View File

@@ -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,
)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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]);

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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 = &lt->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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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 = {

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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],

View File

@@ -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);

View File

@@ -162,6 +162,7 @@ endif()
extern_wcwidth
bf_intern_libmv
extern_sdlew
extern_bullet
)
if(NOT WITH_SYSTEM_GLOG)

View File

@@ -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