
Recently, I started to think about how to rig a snake, with all the scales. After a few researches, it turns out different snakes have different type of scales, sometimes stretchy and flexible, sometimes more rigid. The stretchy ones are not much of a concern and should be handled in texturing if no animation control is required on them. Instead, I decided to focus on how to fake collision without a realistic solver driven by CFX. In this tutorial, we're gonna look at a possible solution fast enough to be used by animators. Please note this is not something you want to keep in your low rez rig, but rather something to add in your high rez rig, along with fur, possibly face rig, and anything too heavy for blocking. Furthermore, this might be too heavy/cumbersome with maya nodes only; when I did it, it was with a c++ custom node, and if you have 200+ scales to handle, that's what I'd suggest. Let's break down the problem into 2 different smaller problems!
Let's focus only on 2 scales; if we get it working for those 2, we can then expand to the entire snake. Introducing a rotation in scale B (yellow), we can easily picture a triangle with how scale A (blue) should be.
a = c * cos(beta) - sqrt(b*b - c*c * sin(beta)*sin(beta)) alpha = -beta - sqrt(b*b - c*c * sin(beta)*sin(beta))
a = sqrt(b*b - c*c * sin(beta)*sin(beta)) + c * cos(beta) alpha = PI - beta - arcsin( c*sin(beta) / b)
Now that we figured the math, we can implement it in maya. I used an expression, just because it's simple to prototype things without using a thousand nodes. Remember, we know b (that's the length of one scale, defined by a user input), we know c (magnitude of scaleA-scaleB), and we know Beta.
Now all we have to do is replacing what we know in the previous equation.
I built a basic maya scene, if you really struggle with the math part, feel free to have a look at it if it helps. You can download it here
Now we have a working solution in 2D, let's introduce some twist in our scales. As you can see, the first equation is satisfied, yet we have some collision on the sides. In order to address this, we need to find by which angle we should twist scale A to match exactly scale B
In other words, we need to find an angle theta by which we will rotate scale A.
We don't care how far P is along the edge of scale A. All we want is to have it somewhere on that edge. To do so, we can just add F.z/|F.z| to O (the Z vector of our frame, normalized)
This one may be a little bit more complicated on the math side, and would require a tutorial on its own, so I'll just explain the idea, without going into too much detail. Basically, once we have the angle P, we need to cast a ray from P, in the direction of the scale normal. Then, we get the intersection point of this ray onto scale B, and that'll give us P'. Luckily, a ray/plane intersection is a super light operation. All it takes is a point (P), a direction (the Y axis of our frame, or maybe another one depending on your orientations), and a target plane, defined by a point (position of the next scale) and a normal (Y axis of the next scale). Once you have this, the math is pretty standard, but again, I'm not onna cover it here (maybe in a future tuto?). You can still have a look at the maya scene available to see how it works.
Again, if you struggle, you can simply download this sample scene (maya 2019)
Now that we have resolved the collision in 2D and expanded it to a 3d world, we can propagate the exact same operation to all the scales to get the desired effect. As mentioned in the introduction, I would not recommand doing it with maya nodes for many scales, but instead doing it via a custom node.