利用者:Revzin/ShapesProposal2
目次
- 1 List of what's good about the original proposal
- 2 List of what's bad about the original proposal
- 3 List of things than aren't decided to be useful or not yet
- 4 List of things considered useful that weren't in the original proposal
- 5 What is going to make it and how?
- 6 Midterm Deliverable Detials
- 6.1 Alternative anim-independent mix for editmode
- 6.2 More efficient shapekey recalculation
- 6.3 PE for Blend from Shape and quick blending in editmode
- 6.4 Shapekey compression on disk save
- 6.5 Optimization of mesh editmode undo memory usage
- 6.6 Adding a Value Range for Shape Keys
- 6.7 Commit to New Shape Key
- 6.8 Bug fixes / TODOs
- 7 Implementation notes
List of what's good about the original proposal
- Under-the-hood
- Speeding up shape key recalculations by avoiding doing total mesh recalculations if topology didn't change is probably good
- Memory undo optimizations via storing only the changed shape key if possible are hardly bad
- Compressing shapekey data by storing only the changed vertices (from the Key->refkey) can deflate the files by some percent
- Proportional editing for blending is good
- User Interface
- Scratch is a good concept by itself
- Improving Blend from Shape is a good thing, quick blending in editmode is a good thing
List of what's bad about the original proposal
- Over-engineered and complicated
- Too much checkboxes, need as few as possible
- Blending with sliders is inconsistent with other parts of Blener
- Scratch key doesn't have that many applications to be in the user's face
- Introduces some complicated local UI in one place
- Four-way slider is probably useless and not Blender-ish
- Modifier keys already taken and we don't want to break them, same with Y-dragging
List of things than aren't decided to be useful or not yet
- Having an alternative mix in Edit Mode in case there is animation
Do we need a fast way to preview a shape key while working on top of a mix?-- seems there already is a way!Is Apply Shape Keys in Edit Mode worth getting rid of?-- this needs to be reverted back to master. The only thing we actually need is recalc speedup, not emulation of Shapekey Modifier. Why would I do it in the first place? :|
List of things considered useful that weren't in the original proposal
- Make shape keys that come from linked library animatable with a proxy (suggested by an artist via email)
- Add in a system to define custom evaluation routines for a shapekey (see this email)
- Allow local deformations to act as drivers for further deformations (see this other email)
- Make driving Shape Keys easier by adding a Value Range
- Add support for Shape Key grouping in the list - add support for groups in UILists in general. (these last ones are suggested in here by Derek Root)
- Add a "Shape Key Brush" brush that blends in the selected shape key in the active shape key (suggested by qurq on IRC)
What is going to make it and how?
Midterm
- Having an alternative animation-independent mix is a good idea
- Proportional editing and quick editmode blending can make it in form in a modal Blend from Shape operator conceptually doing the same as the slider (how do we choose the shape key to blend to/from here?)
- Shapekey compression on disk save
- Undo memory optimizations
- Value Ranges
- Scratch key can be internal and concealed from the user (minus one checkbox - Auto-Commit). If the user accidently edits the wrong key, we can have a special operator that reverts the current key and commits the edit into a new one. Commit to Different Shape Key or in the likes of that.
- Fix T40505
- Fix T35170 Kinda already fixed this (in patch tracker for a bunch of months), but still
- Make the added shape keys have value = 1.0 after adding in them Sculpt Mode (small thing, suggested by qurq)
Finals
- Make shape keys that come from linked library animatable with a proxy.
- Add a "Shape Key Brush" brush that blends in the selected shape key in the active shape key
- Add in a system to define custom evaluation routines for a shape key.
- Add support for groups in UILists in general.
- ???
Midterm Deliverable Detials
Alternative anim-independent mix for editmode
The user, while sculpting on top of a mix in edit mode, can switch to an alternative mix values, in case the 'main' mix is already driven by animation.
This is already in the shapekey branch: 63a7fbe3a0
More efficient shapekey recalculation
In the master branch, switching between different shapekeys in editmode is internally re-entering editmode with a different shape key loaded. Offset propagation is done by a heavy-duty function from bmesh_mesh_conv.c. While this is a very safe method that accounts for topology and customdata changes, it's slow due to memory reallocations.
It is uncommon to edit topology while sculpting shape keys. It happens, of course, but not often, so it's rather pointless to run heavy-duty conversion functions each time (and reallocate everything) since
Most shape keys don't change in a deform-only edit, just the current one. Usually the number of basis shape keys is very small compared to the total number of keys. If the mesh topology can be assumed to be unchanged, we can avoid rebuilding the whole RealMesh, but only edit the affected shape keys. To help determine if the topology has been changed, a hash of the BMesh topology-related data is computed (see this commit. This is a cheat somewhat, as it doesn't check the topology itself, but the memory layout, so a copy of the current editmesh will be treated as a different mesh... but that doesn't seem to be a problem, editmesh reallocation doesn't happen much without real topology changes.
This is already in shapekey branch, though not really final. Benchmark results can be seen later on this page; it suggest it is a good idea!
PE for Blend from Shape and quick blending in editmode
Blend from Shape is to recieve Proportional Editing (all types of it) and modal behavior which will be reminiscent of the planned four-way slider: horizontal drag adjusts mix intensity; vertical drag -- falloff distance (can change that to Mousewheel for consistency with other Editmode operations...) The shapekey to blend from can be chosen on op invoke from a dropdown and then changed with some other key (maybe PgUp/PgDown or some other).
Shapekey compression on disk save
While saving shape keys, we're going to write only the vertices positions that are changed from the reference key (after a certain total vertex count). Store an int for the vertex index and a float for the vertex's position. Compressing is to be done on file write and uncompress on file read.
Optimization of mesh editmode undo memory usage
Currently mesh editmode undo stores the whole mesh after any edit, that includes full copy of all keyblocks. This is not very efficient. We're going to use editmesh topology hashing to check if there weren't topo changes and store only the affected keyblocks then. Just a bit more logic in undo push and pull.
Adding a Value Range for Shape Keys
As suggested in here, add a Value Range property to the keyblocks. The idea is that a shape's value can go anywhere in the user-defined range and then gets clamped to [0-1]. This allows for easier driver setup.
[I’m not sure at all about that… imho it’s not that hard to make clamping/mapping in drivers, don’t really see the point in adding that here? Just adds useless data and UI cluttering in my point of view., --Mont29 15:19, 15 June 2014 (UTC)]
Commit to New Shape Key
A small remain of the Scratch Shape Key, this operator is to revert the current shape to its original position and copy the edit coordinates to a new key. This is useful when you find out you've just edited the wrong shape key...
Bug fixes / TODOs
T40505- make the manipulator handles and constraint lines draw at the deformed (modifier) vertex position. In soc-2014-shapekey now: 516038c983e [I would suggest you add this as a patch asap, you can assign me and ideasman as reviewers - the soonest this goes to master, the better! :) --Mont29 15:18, 15 June 2014 (UTC)]- T35170 - won't be needed after the undo system upgrades come into place, but poke people for review
Implementation notes
Shape key compression on disk save
It has been noted that usually when using shape keys to animate a character's face, only a bunch of vertices are changed from the rest position in each shape key. In the image below, only the vertices that change from the rest position are highlighted:
It's obvious that the current system of storing each vertex's position in each shape key is not exactly space-effective. It has the important bonus of being able to access each vertex's position in O(1), but that isn't exactly needed while storing shape keys on disk (or for undo purposes).
The idea is to store only the changed vertices' positions in the file and in object mode undo. On a test file (4.5 kvert character head mesh with 157 shapes), the size reduction was almost 3x (compressed test file - open only with soc-2014-shapekey branch).
In a compressed shape key, a float3 for coordinates and and int for original vertex index is stored, so it's not a perfect win.
The compression logic checks if there will be a space gain from saving shape key in a compressed format and does that in case there is the gain.
Downside is that master Blender won't be able to open the compressed data correctly. A User Preference was added in File preferences to disable compression.
This is already in soc-2014-shapekey: 4c56a47730b93f4
T40505
What's the problem?
Fixing that is somewhat non-trivial since there can be different modifier situations that require us to use different DerivedMeshes, e. g.:
- If there're only deform modifiers, we just need to use the final cage, and the vertex indeces will be in sync to the editmesh
- If there're some generate modifiers, some vertices can be mapped back to editmesh ones by index (subdiv) or not (remesh).
Solution
- Setup:
- Determine the situation: if there're only deform modifiers, just use the final cage.
- If there're some generate modifiers, try to map new vertices to old vertices. If all vertices are mapped, use the final cage in proceeding calculations.
- Calculation:
- If there's a vert map, use it to get every selected vertex's derived position
- If no vert map, just use the current vertex's index to get the derived position
The setup phase must be a dedicated function since it's gonna be needed in manipulator draw and TransCon drawing too.
Mesh topology hashing
Comparison of execution times
The testfile I used is here.
Tests were done on i7 4770K + GTX 760 Win7 machine, built using VS 2013 in Release configuraions.
Master branch was at ce460c617, soc-2014-shapekey was at 31a1d1cad.
liz_head_rel is a 4.5 KVert mesh with 157 shape keys. liz_head_rel_40 is a 4.5 KVert mesh with 40 shape keys. liz_body_yound is a 4.8 KVert mesh without shapes.
Sampled a dozen values for each cell to avoid noise.
Table
Task | Master branch exec time, in sec | soc-2014-shapekey exec time, in sec |
Editmesh-to-mesh (liz_head_rel), one shape affected Timed OB_MESH case of ED_object_editmode_load_ex() |
avg 0.0848 max 0.1164 min 0.0453 |
avg 0.0839 max 0.1447 min 0.0486 |
Editmesh-from-mesh (liz_head_rel) Timed OB_MESH case of ED_object_editmode_enter(). |
avg 0.0471 max 0.0843 min 0.0268 |
avg 0.0532063 max 0.07304 min 0.026406 |
Editmesh-to-mesh (liz_body_young) | avg 0.0849 max 0.1348 min 0.0344 |
avg 0.07498 max 0.1239 min 0.027 |
Editmesh-from-mesh (liz_body_young) | avg 0.032 max 0.0383 min 0.0172 |
avg 0.0313 max 0.0407 min 0.0102 |
Shape switch, no topology change, no recalc (liz_head_rel). Timed OB_MESH case in rna_Object_active_shape_update(). |
avg 0.1261 max 0.2462 min 0.088585 |
avg 0.0589 max 0.0750 min 0.0223 |
Shape switch, no topology change, no recalc (liz_head_rel_40). | avg 0.0813 max 0.1147 min 0.055 |
avg 0.0426 max 0.0604 min 0.0335 |
Shape switch, no topology change, 157 shapes recalc (liz_head_rel) | avg 0.139 max 0.2166 min 0.1076 |
avg 0.0665 max 0.0817 min 0.0525 |
Shape switch, topology change, no recalc (liz_head_rel). | same as 'no topology change' | same as 'no-topology-change' in master |
Shape switch, topology change, 157 shapes recalc (liz_head_rel) | same as 'no topology change' | same as 'no-topology-change' in master |
Mesh | exec time, in usec |
liz_head_rel | avg 970 max 1350 min 240 |
liz_body_young | avg 1040 max 1740 min 560 |
Notes and conclusions
- On a mesh with shape keys, shape switch operations which happen without topology change are sped up 1.8-2.1 (40 shapes and 1by using the simpler recalculation routines in deform only cases.
- Hashing does not add a significant performance penalty; and there is room for even faster hashing, e. g. loop unrolling since the hash data sizes are constant
Conclusion: using hashing to determine if the mesh's topology hasn't changed and using 'lightweight' shape key recalculations in this case offers 2x speedup on shape key switching. Since most shapekey-related editing operations aren't changing the topology, this is a good thing.