Monday, September 2, 2013

Depsgraph - Transform Component Graph Building

Following on from yesterday's notes about the stages for how Pose Component graphs are constructed, this post covers the graph for the "Transform" Component. Once again, I've had these notes lying around for a while (in fact, this particular notes dates back from the start of August, and predates much of the current work that's in place now), and haven't really had time to scan them in or post them until now (BTW, I've decided to just split these up into smaller chunks for easier handling).

Transform Component
The Transform component basically encapsulates all evaluation operations/data related to the transforms of Objects. In other words, this is in many ways analogous to the situation with the Pose Component (for bone transforms), which also amount to a 4x4 matrix describing the relevant transform for that element being computed.

Examples of operations involved here include:
1) Transform Matrix (T) - A 4x4 matrix which results from taking the transform properties that users set using transform tools/animation and converting those properties (i.e. vectors, quaternions, axis-angles, etc.) into a form more suitable for further processing.

2) Delta Transforms Matrix (D) - Similar to the Transform Matrix, except that these are the transform properties labelled "delta" transforms. The result of this is once again a 4x4 matrix which gets combined with the standard transform matrix (i.e. it is applied on top of it, so, using standard mathematical notation, this is D*T = M  or  D(T) = M).

3) Parenting (P) - Apply transform derived from some aspect of a parent entity (e.g. object transform, bone transform, vertex geometry, vertex-group geometry, etc.) on top of transform stack. Takes 4x4 D*T and applies Parent Transform on top (i.e. P * D * T = M)

4) Constraints Stack (C) - Self explanatory. This just runs each constraint in order, passing it the current 4x4 matrix, and getting it to perform its magic on that.

5) Rigidbody Simulation (R)  - This step is really just taking the results cached from the simulation engine and applying it as our base transform (effectively overwriting D*T, though the sim itself depends on P*D*T...)

So, how detailed do we get in trying to represent all this?

Version 1 - Fine-Grained (Each Constraint = 1 Operation Node)

- This is needed for node-based constraints, and doing this would set us up for that eventual move
- The constraints evaluation process is highly modular as it is, and would easily fit within such a framework

- We'd get no real performance benefits from this. Namely, the constraint stacks current work such that each constraint requires the output of the previous constraint in the stack before it can run. That means that all the constraints can effectively only ever be scheduled up sequentially. Thus, we wouldn't be able to really multithread that evaluation process anyways...
- Exploding the stack results in many times more nodes - and thus, relationships to test/manage, and several other related problems
- We'd probably need a second sub-component here to successfully manage the complexity of building the constraint-stack. That won't work too well with Pose/Bones, which is already a 2-tiered component situation.

Version 2 - Breakdown according to key evaluation steps now (with finer relationship detail-level)

Basically, instead of exploding the constraints stack, we just keep the constraints stack as a single node for now. Ultimately, this is easier in the short term to get working, and requires less complex graph building code. Only if later on we find that this limits the types of setups we need (or node constraints work starts up), only then will we need to consider breaking down this stack into separate components.

Solution
We're currently using the unexploded version to keep things under control for now.