Pre-tranform, Parenting and More
Recently I faced a problem when I was playing with the parenting of Geometry node in Houdini. I thought it wouldn't be a big deal at the beginning. However, the contents behind this node are much more than I expected.
Problem description
Let's take a look at what happened during my experiment.
First I created a parent geometry and applied a scaling in the Y direction. Then I connected a child geometry to it. As we know, Houdini would automatically match the transformation of the child to the parent. As it operated, I got the handle on the child squashed showing as below:
It is not a problem since we can fix it by using the clean transform option in geometry. By doing this, I solved the handle squashing problem for some child, which means I can apply a scaling on the child, and its handle appears correctly. However, the solution didn't apply to all children; some children got more handle squashing on it.
Problem reproducing
After tweaking a bit on the experiment, I noticed that the order of connecting the child to the parent caused the wired squashing. For better demonstrate the problem, I created two instances to reproduce it as below with the operation steps I took:
Step.1: I created a parent box and applied the scaling 0.5 in the Y direction.
Step.2: I checked on the "keep position when parenting" option for two children, namely, child A and child B.
Step.3: For child A, I used the workflow that I mentioned above, and I got the right result.
Step.4: For child B, instead of connecting B to parent box, I scaled it by 0.2 first, then connected it to the parent box and cleared the transformation at last.
As a result, A brought me what I expected, but therefore,the handle scaling of B was squashed more than the status before applying clean-transform operation. (check the following video see the whole problem reproduction)
Apparently, the operation that applied to A is the right way to implement child scaling without affecting by the parent. However, the question is why different operation order make a different outcome?
Solution & Explanation
Houdini Documents offer the answer:
The pre-transform uses a fixed, non-configurable transform order. If you try to copy a non-uniform scale into the pre-transform, you can get shearing."
(Houdini 17.5 documentation: Working with objects, Pre-transform section)
The answer is pretty straight forward. For B, because I added scaling to the child box on Y-axis before connecting it to the parent box, so I got it shearing.
Behind the Pre-transform
I came across the word "Pre-transform" from the answer. So what is pre-transform? What a kind of role is it playing in the geometry at the object level?
To better answer this question, we should figure out how HOUDINI handles those data. The process involves some stuff which we are going to spend some time to discuss: world space, local space, and pre-transform.
World & Local Space
World space is the coordinate system for the entire scene. Its origin is at the center of the scene. On the other hands, the local space refers to the object space, which is the coordinate system from an object’s point of view. The origin of object space is at the object’s pivot point, and its axis are rotated with the object. The only difference between local space and object space is if there are a hierarchy exists, then the local space of the child will refer to the origin and axis of the parent.
What is pre-transform?
When doing parenting in 3D software, sometimes, especially when doing rigging, we may want to do transformation to the child, and keep the result of the transformation when connecting to the parent. In Houdini, we can do this by checking on the "Keep Position When Parenting" option before connecting it to the parent. However, to maintain the position of the child in world space, Houdini has to cancel the transformation where comes from the parent, that is:
- In a usual way, as we are parenting, the position of a child in local space should refer to the parent, and the child is no longer maintain the original position in world space when parenting.
- Now we want to maintain the position of the child in world space; That means the position of the child in the parent's space would change.
The picture shows an example with/without "keep the position when parenting" in translation, it is playing addition and subtraction between translation vectors. However, we should notice the position of the two boxes changed in the different space, respectively.
For most of the time, when we enabled "Keep Position When Parenting" option, Houdini stored some information in the position of child of local space to represent the relative position of the child in parent's space. Nevertheless, sometimes we want to keep the position but setting the position of the child in local space as "zero" state. At this stage, Houdini uses "Pre-transform" to store the transformation information of the child's transformation in local space.
Using Pre-transform in Houdini
There are three major operations that allow us to manipulate the Pre-transform:
- Clean Transform: store the current local transform into the pre-transform and set the local transform to the zero state.
- Extract Pre-transform: Bring what we stored in pre-transform to the current local transform.
- Reset Pre-transform: clean what info we stored in pre-transform.
These operations are useful if you need to swap the transform info frequently.
Tips for Pre-transform
So far, from my understanding, the non-uniform scaling can't be applied to the child correctly when parenting. I will spend some time to figure out what is going on behind the limitation.
Unlike the general Houdini workflow, the pre-transform value can be overwritten; we should pay special attention when using clean transform and reset pre-transform. These options can apply multiple times on pre-transform values and may cause you to lose the info you need.
If you want to perform non-uniform scaling on the child, use clean transform to zero the child's position in local space first. Otherwise, you may find the parent's scaling would cause the child shearing.