Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joint IDs order in joint groups do not match with values in the matrices #38

Open
xiancg opened this issue Dec 21, 2023 · 7 comments
Open

Comments

@xiancg
Copy link

xiancg commented Dec 21, 2023

Hi Epic-3Lateral!

I'm working my way to be able to read/write from the values matrices for the different joint groups and expressions using the Python DNA API.

The initial assumption is that the order in which the joints are presented in the joint group should help decide where the slopes in the values matrix are. Well this is not only False, but I've found is random (in some joint groups the order in which values are presented match only when I sort the joint IDs in ascending order, just to name an example)

Here is another example with a face I'm working with ATM:
-Joint 324 (FACIAL_R_EyelidUpperA2) and Expression 11 (eye_blink_R)
-Joint Group 51: [321, 338, 322, 326, 324, 340, 341, 339]
-Joint index in joint group: 4
-Expression index in inputs: 15
-Inputs lenght: 41
-Outputs lenght: 48

Using these values I should be able to find the first of 6 output values at these coordinates in the matrix: (24, 15). Or in other words, at index 999 of the values. The remaining values should then be located at 1040, 1081, 1122, 1163 and 1204.

1122, 1163 and 1204 should be the rotation values of the joint when eye_blink_R is set to 1. BUT, they ARE NOT!.

Instead, if I do a manual search for the actual rotation I see in Maya when eye_blink_R is set to 1 (with the help of an IDE and the DNA file as JSON), I find the actual indexes of these values in the matrix are: 753, 794, 835, 876, 917, 958.

Given the first index is 753, the joint index of joint 324 in joint group 51 should be 3, not 4!! So the order in which the Python DNA API is returning these joint IDs is not reliable.

Did I miss something obvious? Or is there a sorting algoritm we should be aware of?

@xiancg
Copy link
Author

xiancg commented Dec 22, 2023

I wrote a small function to backtrack the correct joint order and for this particular case (Joint Group 51) it should be: [321, 338, 322, 324, 326, 339, 340, 341]. Seems to me like this sorting comes from the hierarchy matrices.

@mad-guru
Copy link

I'm looking into Joint Groups as well. My assumption was that the Joint Group contains indices of the Joints used in that particular pose in the Rig Logic that corresponds to a Facial Control.

So, I can get the following data:
joint names using dnaReader.getJointName(num)
face control names using dnaReader.getGUIControlName(num)

I created lists based on that order. My assumption is that Joint Groups are listed in the same order as face control names and that the Joint Group Joint indices would correspond to the index numbers of the joint names, but that does not seem to be the case.

How do you figure out which face control a Joint Group corresponds to and which joint each of the Joint Group Indices corresponds to?

It seems we should be able to update these values in the rig logic and then save that to the DNA file to deal with correcting poses that are not working on a custom mesh.

Thank you.

@xiancg
Copy link
Author

xiancg commented Jan 22, 2024

My assumption was that the Joint Group contains indices of the Joints used in that particular pose in the Rig Logic that corresponds to a Facial Control.

Not exaclty. Joint Groups contain the indices of the joints, yes, but they are also placed together with the set of expressions where those joints are used.

My assumption is that Joint Groups are listed in the same order as face control names

Nope, they use an order which to me comes from the hierarchy matrix, but to be honest I sticked to my workaround cus it works, at least until they answer to this issue or to my post on the Epic Forums.

How do you figure out which face control a Joint Group corresponds to and which joint each of the Joint Group Indices corresponds to?

You don't need to focus that much on face controls but on expressions, which are not exactly the same thing, but really similar. Look for the CTRL_Expressions node in Maya. As for the rest, it is a matter of understanding what relationships the matrices encode and how they encode it.

It seems we should be able to update these values in the rig logic and then save that to the DNA file to deal with correcting poses that are not working on a custom mesh.

Yes, the lowest level API allows for the finest control of all the DNA layers. You can manipulate absolutely everything.

I highly encourage you to convert a DNA file into JSON and analize that.

@mad-guru
Copy link

Thanks for the reply! I've been looking more closely at the json generated from the dna file as well as using the commands, and looking at all the documentation I could find. While I understand a bit more than I did before, I'm still at a loss to know how the behavior data in the dna file corresponds to specific ctrl expressions. Is there some documentation that goes more indepth into the behavior data and how we can correlate it to joints, and ctrl expressions?

getJointRowCount() and getJointColumnCount() seem to refer to some large matrix of values perhaps where all of this data has been dumped.

getJointGroupLODs(jointGroupIndex) seems to refer to rows of data and which ones are applicable to each LOD

The number of joint groups does not correspond to the number of ctrl expressions, or curves or controls.

I find the joint hierarchy numbering a bit confusing but it seems I can get around that a bit using dnaReader.getJointName(joint_index) which helps me figure out which index a joint corresponds to, assuming the index is a joint.

This allows me to get more information from the indices returned in getJointGroupInputIndices(jointGroupIndex) getJointGroupOutputIndices(jointGroupIndex)

So, given a joint group, I can find the Input, Output and Group Joints.

How are each of these joint types used? Input joints drive group joints in the shape? Output joints are driven by the group joints? To adjust a shape, which would I edit?

How do I know which joint group corresponds to which ctrl expression?

Then, once i have the ctrl expression for a given joint group, I would need to figure out behavior/conditionals such as slope, which I think is the value that activates a particular ctrl expression, but how to know what each value relates to?

Then there are the rowCounts and colCount, I am not sure how to use that to find the data I need.

So currently, I see many numbers, but am unclear on how they relate to ctrl expressions etc.

Any ideas?

Thanks!

@xiancg
Copy link
Author

xiancg commented Jan 24, 2024

The value matrices in each joint group store the resulting relationship between an input expression and it's output transforms (translation and rotation). They are the slope values of linear equations in the form of y=kx+b, where x is in the input expression, k is the encoded slope value and b is the neutral pose value of each transform.

I think this responds to most of your questions, but just in case, this all can be deducted from the paper they published a couple years ago: https://cdn2.unrealengine.com/rig-logic-whitepaper-v2-5c9f23f7e210.pdf along with the docs of the API (which to my taste are not friendly, but it has everything you need.)

@mad-guru
Copy link

mad-guru commented Jan 25, 2024

Thanks! I reread the documentation and the whitepaper. I spent more time testing data, listing connections etc. I found that I can take the raw control and get the Ctrl_expression parameter that corresponds, easily. From there, I can find the rigLogic input plug that it is connected to. On the rigLogic translation, rotation and scale outputs, I can find the joints that each plug drives.

It's that in between step, of going from the riglogic input plugs to figuring out which joints on the output side are affected by that control that I have not figured out. I see that the joint groups in the dna behavior layer deal with distinct joints and parts of the face mesh that are driven by them via skinCluster. If I can find the joints affected by a particular ctrl expression on the rigLogic node, then I could find the corresponding joint groups and from there, the joints in those groups.

You mentioned that you had written a function to backtrack and correctly reorder the joint indices, I guess to align with the joint values list, so that one could derive data like slope etc by reverse engineering the formula you pointed out.

I looked through the docs and all the materials I could find. Could you point me in the right direction for where you gained more clarity on the uncompressed matrix, and how to find the pieces of data for joints and slopes that go with a given ctrl_expression?

Thanks!

@xiancg
Copy link
Author

xiancg commented Jan 25, 2024

You don't actually need to go through the Maya connections to know what's going on in the matrices. Just look to the joint names and the joint indexes. Then go to each joint group and you'll have a function to get a list of all joints in that joint group. You also have another function to get the id and the name of each expression and you can relate that to the inputs of each joint group.

If you take a look at the first post in this thread, you'll find what you need to understand the relationships in the DNA.

As for the correct order of the joints in the joint groups, I rather prefer to wait for a fix from Epic cus my workaround just works like 95% of the time and well, I'm under NDA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants