Description
I recently finished a heat/tension based deformer / Maya-API plug-in. Depending on the amount of stretching and compression on the surface, vertices get deformed along the normal or with blendshapes. The most common application would be to blend in wrinkles on skin and clothing.
Motivation
To have an extra tool to improve deformation for many different types of rigs. I was also personally interested in the subject, and I had some downtime between projects.
Video
prHeatDeformer - deformer (custom node) from Parzival Roethlein on Vimeo.
Breakdown
- I had not used the Maya API for over half a year, so I was a bit rusty at first.
- I always had to take a break when there was a project I had to work on. Which is less efficient for me than continuously working on it, because it always takes a bit to get back into it.
- The first two weeks were spent writing a complete Python API version. I implemented all features, but with little calculation optimization. I always like writing Python versions, because you do not have to compile, so the iterations are really fast. On the downside I have to use a lot of printing and complex debugging is actually more easy in C++ / Visual Studio, because you can set breakpoints and use "attach to process" for interactive debugging, which I used the first time on this plug-in. So in retrospect it definitely would have been faster to skip the Python version. But I got more experience with the Python API.
- After the Python version was working (and terribly slow) I wrote the C++ version in one week. This was the hardest part, because I had to implement a lot of performance increasing stuff, so that the deformer does not slow down the rig as much. There will definitely be a geometry resolution switch for the animators, but I still want them to be able to see the heatdeformed highres mesh with decent speed and also when working with it as a rigger it is always better to have the deformer as fast as possible. To make the deform fully production ready it had to work with transforms that have any number of shapes and each shapes vertices can be inside or outside of the deformer membership. Combined with the speed improvements they were the most difficult things to get done.
- I wrote a lot of common features for the first time (tangent space, smooth, grow, some of the speed optimizations). So that slowed me down. And will improve development time on future nodes.
- The Python version has 800 lines, the C++ version 1400 lines (including header file, comments etc)
In retrospect I was surprised how quickly it was done. Especially if I had skipped the Python API implementation. Because it is one of the more technical and difficult tasks in rigging, it also feels quite rewarding when you get it done.
Todo
Additional features and performance improvements
Related
- (2007) Siggraph 2007 presentation "Realtime wrinkles, Christopher Oat": This is the oldest reference I could find for this idea. The second half has "dynamic wrinkles" that are tension based.
- (2008 or earlier) The Maya (Comet) muscle skinDeformer has a "wrinkle" option included to the "relax" feature. It moves vertices along the normal vector when being compressed. This feature is not usable, because there is only one global attribute to control the strength and one paintable map. So there is no limit and no way to control the acceleration etc. And the biggest problem is that the algorithm does only work properly on primitive geometry (sphere,..) because it is only considering neighbor vertices that have continuous numbering (or a random one, if there is no proper neighbor id). This is a bit hard to explain, but the result on a production mesh is that it calculates the compression differently on neighbor vertices (except if you scale everything from the same pivot), so you get spikes and have no real control over the shape.
- (2010) fStretch: I think this is the most well known version of this technique. It is a commercial plug-in by Matthieu Fiorilli. It seems very sophisticated, but it is a commercial plug-in that costs money/effort and the license model is not so good for the place I work at.
- (2012) tenshionBlendshape: Inside of the SOuP plug-ins, it does not have tangent space, which makes it unusable and I also did miss some other features and the base algorithm also had some problems with different sized geometries. I did send them the feedback thou, so maybe some day there will be a usable free version of this technique.
Great post and work!
ReplyDeleteHow are you calculating the amount some edge/vertex has been compressed or stretched compared to the original mesh? Do you store all the neighbouring vertices and compare the distances with the original distances?
ReplyDeleteThat was also my first approach, to compare the connected edge lengths for each vertex in the current position to the bindPosition (origShape or custom shape). You can store the bindPose values in the code, so it does not slow down the scene as much.
DeleteThen I compared it to using the connected face areas, which works better, since it is more accurate and in my test it calculated just as fast. So I see no reason to use edge-lengths. But I left in the option just in case.
Hey Parzival, thanks for your reply! Really helps. :) Using face areas is clever.
DeleteHope you're willing to share source code one day. And keep on creating awesome stuff. :)
Cheers,
Roy