Inverting constraints function or attributes #105882

Open
opened 2023-03-18 15:00:20 +01:00 by Tal Hershkovich · 8 comments

Adding a function that inverts constraints calculation or an attribute that shows how much value was added to an object from each constraint

I was discussing with Dr.Sybren and Brad Clark about the 'Copy Global Transform' addon.
I have an addon called animtoolbox, and one of the tools is similiar and called 'Copy World Matrix'. (I didn't realize it's already inside Blender)
It is available to download here
https://gitlab.com/dancingshapes/animtoolbox

However the main difference is that animtoolbox is calculating also the "child of" constraint inverse
I've made a video that compare the two addons with different child of constraints and different influences. you can see how it's always pasting into the same final world matrix
youtu.be/Qj33wXRbpz4

Eventually I want to invert all the constraints calculations (that don't have 'replace' mode).
Dr.Sybren suggested that instead of each addon inverting constraints by itself, there could be a built-in function. I'm suggesting to have an attribute that shows how much value is being added. Maybe this could be eventually also related to everything nodes.

The child of constraint currently already has the attribute constraint.inverse_matrix in the api, so it could be similiar attribute, but showing the whole value that comes from each constraint

In case this can help with the design, here are examples from animtoolbox addon. What I'm currently using to revert the child of' constraint the base formula that I use to find the offset is

offset = con.inverse_matrix.inverted() @ con.target.matrix_world.inverted()

To calculate it also with the influence I use this formula to append and calculate each constraint offset

offset = Matrix.Identity(4) + con.influence * (parent_matrix @ con.inverse_matrix - Matrix.Identity(4))

This works good for location, for rotation and scale I use lerp

offset_lerp = Matrix.Identity(4).lerp(parent_matrix @ con.inverse_matrix, con.influence)

and then invert and multiply all the offsets with the desired matrix.

For all the other tranformation constraints I found that I could find the difference between matrix world and matrix basis and then multiplying the inverted difference, but this requires to isolate each constraint, which can cause issues when drivers are applied.

diff = basis.inverted() @ obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix_world 
obj.matrix_basis = obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix @ diff.inverted()
Adding a function that inverts constraints calculation or an attribute that shows how much value was added to an object from each constraint I was discussing with Dr.Sybren and Brad Clark about the 'Copy Global Transform' addon. I have an addon called animtoolbox, and one of the tools is similiar and called 'Copy World Matrix'. (I didn't realize it's already inside Blender) It is available to download here https://gitlab.com/dancingshapes/animtoolbox However the main difference is that animtoolbox is calculating also the "child of" constraint inverse I've made a video that compare the two addons with different child of constraints and different influences. you can see how it's always pasting into the same final world matrix [youtu.be/Qj33wXRbpz4](https://youtu.be/Qj33wXRbpz4) Eventually I want to invert all the constraints calculations (that don't have 'replace' mode). Dr.Sybren suggested that instead of each addon inverting constraints by itself, there could be a built-in function. I'm suggesting to have an attribute that shows how much value is being added. Maybe this could be eventually also related to everything nodes. The child of constraint currently already has the attribute constraint.inverse_matrix in the api, so it could be similiar attribute, but showing the whole value that comes from each constraint In case this can help with the design, here are examples from animtoolbox addon. What I'm currently using to revert the child of' constraint the base formula that I use to find the offset is ``` offset = con.inverse_matrix.inverted() @ con.target.matrix_world.inverted() ``` To calculate it also with the influence I use this formula to append and calculate each constraint offset ``` offset = Matrix.Identity(4) + con.influence * (parent_matrix @ con.inverse_matrix - Matrix.Identity(4)) ``` This works good for location, for rotation and scale I use lerp ``` offset_lerp = Matrix.Identity(4).lerp(parent_matrix @ con.inverse_matrix, con.influence) ``` and then **invert and multiply all the offsets** with the desired matrix. For all the other tranformation constraints I found that I could find the difference between matrix world and matrix basis and then multiplying the inverted difference, but this requires to isolate each constraint, which can cause issues when drivers are applied. ``` diff = basis.inverted() @ obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix_world obj.matrix_basis = obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix @ diff.inverted() ```
Tal Hershkovich added the
Type
Design
label 2023-03-18 15:00:20 +01:00
Tal Hershkovich changed title from Adding to constraints an invert function, or attributes that show how much value comes from each constraint to Adding an invert function to constraints, or attributes that show how much value comes from each constraint 2023-03-18 15:24:12 +01:00
Tal Hershkovich changed title from Adding an invert function to constraints, or attributes that show how much value comes from each constraint to Inverting constraints function or attributes 2023-03-18 15:32:52 +01:00
Brad Clark added this to the Animation & Rigging project 2023-03-20 00:50:51 +01:00
Member

Just leaving a comment to say that I support the idea of adding inverse functions per constraint. I've already done so but it is a bit more involved than just an inverse per constraint. This design outline is missing a focused goal though. Adding an inverse describes the technical part that you want added, but doesn't describe the intended animator/rigger workflows. The video shows it better but it should be explicit in the description.

As I understand it, this would eventually be the basis for improved visual keying and having Blender's core animation tools work properly even when the character is rigged. Something as basic as Copy+Pasting a pose, Snap Bone To Cursor, etc doesn't work and can't work unless Blender can solve a rig backwards.

Visual keying, to me, means preserving an initial pose after modifying the character's rig. The conventional meaning is a special case where the rig is completely removed. Snapping IK from FK is visual keying where an IK rig is added. Space switching is visual keying where a Space rig is added or removed. With support for a more generalized visual keying, you can also develop tools for animation retargeting, the ability to update rigs w/o breaking animation, adhoc rigging w/o breaking the animation. Finally, rigs would become simpler. For an IK/FK snap rig, you'd no longer need 3 chains (FK chain, IK chain, blended deformer chain). You'd only need one, the deformer chain.

Just leaving a comment to say that I support the idea of adding inverse functions per constraint. I've already done so but it is a bit more involved than just an inverse per constraint. This design outline is missing a focused goal though. Adding an inverse describes the technical part that you want added, but doesn't describe the intended animator/rigger workflows. The video shows it better but it should be explicit in the description. As I understand it, this would eventually be the basis for improved **visual keying** and having Blender's core animation tools work properly even when the character is rigged. Something as basic as Copy+Pasting a pose, Snap Bone To Cursor, etc doesn't work and can't work unless Blender can solve a rig backwards. Visual keying, to me, means preserving an initial pose after modifying the character's rig. The conventional meaning is a special case where the rig is completely removed. Snapping IK from FK is visual keying where an IK rig is added. Space switching is visual keying where a Space rig is added or removed. With support for a more generalized visual keying, you can also develop tools for animation retargeting, the ability to update rigs w/o breaking animation, adhoc rigging w/o breaking the animation. Finally, rigs would become simpler. For an IK/FK snap rig, you'd no longer need 3 chains (FK chain, IK chain, blended deformer chain). You'd only need one, the deformer chain.

@wbmoss_dev Thanks for your feedback!

As I understand it, this would eventually be the basis for improved visual keying and having Blender's core animation tools work properly even when the character is rigged. Something as basic as Copy+Pasting a pose, Snap Bone To Cursor, etc doesn't work and can't work unless Blender can solve a rig backwards.

Yep, improved visual keying is pretty spot-on. I tried in the past to use bone to curser, like you mentioned, but there were always issues with 'child of' constraints, also with Blender's copy global transforms addon, and other addon's with the same similiar function.

My copy world matrix from animtoolbox is working good with inversing child of constraints evaluation, eventually I want to extend it to all constraints, but it might be tedious.

I think this is a property or function that will be eventually more of a use for riggers / TDs,

Maybe it's something that could be already part of a rigging nodes project, if something like this is planned in the near future, then maybe it should be part of a bigger design discussion. For example it could be just
attributes in the spreadsheet editor showing the values that are coming from each constraint or drive

or if not going into this direction then just
properties or function in the constraints accesed via python api

Space switching is visual keying where a Space rig is added or removed. With support for a more generalized visual keying, you can also develop tools for animation retargeting,

Yep, It's kind of what I'm currently working on at https://gitlab.com/dancingshapes/animtoolbox
I've also started to work more on its documentation that explains it.

@wbmoss_dev Thanks for your feedback! > As I understand it, this would eventually be the basis for improved visual keying and having Blender's core animation tools work properly even when the character is rigged. Something as basic as Copy+Pasting a pose, Snap Bone To Cursor, etc doesn't work and can't work unless Blender can solve a rig backwards. Yep, improved visual keying is pretty spot-on. I tried in the past to use bone to curser, like you mentioned, but there were always issues with 'child of' constraints, also with Blender's copy global transforms addon, and other addon's with the same similiar function. My copy world matrix from animtoolbox is working good with inversing child of constraints evaluation, eventually I want to extend it to all constraints, but it might be tedious. I think this is a property or function that will be eventually more of a use for riggers / TDs, Maybe it's something that could be already part of a rigging nodes project, if something like this is planned in the near future, then maybe it should be part of a bigger design discussion. For example it could be just **attributes in the spreadsheet editor showing the values that are coming from each constraint or drive** or if not going into this direction then just **properties or function in the constraints accesed via python api** > Space switching is visual keying where a Space rig is added or removed. With support for a more generalized visual keying, you can also develop tools for animation retargeting, Yep, It's kind of what I'm currently working on at https://gitlab.com/dancingshapes/animtoolbox I've also started to work more on its documentation that explains it.
Member

I think this is a property or function that will be eventually more of a use for riggers / TDs

Simpler rigging makes it more accessible to animators too. If you only know the basics of constraints, making an IK/FK rig is simplified to just having an FK chain and adding an IK target/pole. You wouldn't even need to properly place them in edit mode. You would just reset the character to T-pose then visual key to properly place the IK target and pole, then Apply As Restpose. Now you have a reasonable default for the IK bones.

Maybe it's something that could be already part of a rigging nodes project

Yeah, I hope whoever is designing rigging nodes also accounts for backwards evaluation.

For example it could be just attributes in the spreadsheet editor showing the values that are coming from each constraint or drive or if not going into this direction then just properties or function in the constraints accesed via python api

I'm not sure what you meant here. If you're talking about displaying offset matrices: For a TrackTo constraint, the owner's offset matrix isn't used to inverse solve it. You just have to place the target bone in front (tracking axis) of the owner.

Yep, It's kind of what I'm currently working on at https://gitlab.com/dancingshapes/animtoolbox

Same here. I've been working on non-public addon trying to figure all this stuff out. I don't know what to do with it yet so I'm just trying to bring awareness to the underlying workflows. I only know of @BClark and the creator of RigOnTheFly as the only ones to talk about it in the Blender community.

> I think this is a property or function that will be eventually more of a use for riggers / TDs Simpler rigging makes it more accessible to animators too. If you only know the basics of constraints, making an IK/FK rig is simplified to just having an FK chain and adding an IK target/pole. You wouldn't even need to properly place them in edit mode. You would just reset the character to T-pose then visual key to properly place the IK target and pole, then Apply As Restpose. Now you have a reasonable default for the IK bones. > Maybe it's something that could be already part of a rigging nodes project Yeah, I hope whoever is designing rigging nodes also accounts for backwards evaluation. >For example it could be just attributes in the spreadsheet editor showing the values that are coming from each constraint or drive or if not going into this direction then just properties or function in the constraints accesed via python api I'm not sure what you meant here. If you're talking about displaying offset matrices: For a TrackTo constraint, the owner's offset matrix isn't used to inverse solve it. You just have to place the target bone in front (tracking axis) of the owner. > Yep, It's kind of what I'm currently working on at https://gitlab.com/dancingshapes/animtoolbox Same here. I've been working on non-public addon trying to figure all this stuff out. I don't know what to do with it yet so I'm just trying to bring awareness to the underlying workflows. I only know of @BClark and the creator of RigOnTheFly as the only ones to talk about it in the Blender community.

I'm not sure what you meant here. If you're talking about displaying offset matrices: For a TrackTo constraint, the owner's offset matrix isn't used to inverse solve it. You just have to place the target bone in front (tracking axis) of the owner.

I meant a way to see how much value is added to the bone or object from each constraint, driver, or any connection.
In the case of TrackTo constraint it would show the rotation value added to the bone from the constraint.

right now in the properties panel we see only the basis values, the constraints are not influencing any values.
In maya for example these values are normally getting updated from all the constraints.

In python api we can access only matrix basis and matrix world. The easiest way I found so far to get the matrix value that comes from a constraint, is if I isolate the constraint (mute all the others) and then use the calculation like I mentioned in the begining
basis.inverted() @ matrix_world
or when including parent then
basis.inverted() @ obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix_world
at least with transform constraints it seemed to work, I think with child of constraint it didn't work and I had to calculate everything backward anyway.

These offset values are anyway being calculated inside blender and are just doing matrix multiplication to the base value, so it would be great if they woud be somewhere also visualized in the viewport or just python

> I'm not sure what you meant here. If you're talking about displaying offset matrices: For a TrackTo constraint, the owner's offset matrix isn't used to inverse solve it. You just have to place the target bone in front (tracking axis) of the owner. I meant a way to see how much value is added to the bone or object from each constraint, driver, or any connection. In the case of TrackTo constraint it would show the rotation value added to the bone from the constraint. right now in the properties panel we see only the basis values, the constraints are not influencing any values. In maya for example these values are normally getting updated from all the constraints. In python api we can access only matrix basis and matrix world. The easiest way I found so far to get the matrix value that comes from a constraint, is if I isolate the constraint (mute all the others) and then use the calculation like I mentioned in the begining `basis.inverted() @ matrix_world ` or when including parent then `basis.inverted() @ obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ matrix_world ` at least with transform constraints it seemed to work, I think with child of constraint it didn't work and I had to calculate everything backward anyway. These offset values are anyway being calculated inside blender and are just doing matrix multiplication to the base value, so it would be great if they woud be somewhere also visualized in the viewport or just python

The following video
https://youtu.be/zJLgnJrkzq0?si=3R5InaOCrB7GRqZW
is showing another use case for having access to the values before and after each constraint in Blender.
It's showing the limitation of current Blender bake, and how I solved it with a new bake using the same formula in the begining of this thread for inverting child of constraints, which I'm also using for copy paste world/relative matrix.

I'm not sure if I should start a new ticket for this with a new name: Getting access to values coming from constraints and drivers?
In python api and eventually blender ui (rigging nodes?)

The following video [https://youtu.be/zJLgnJrkzq0?si=3R5InaOCrB7GRqZW](https://youtu.be/zJLgnJrkzq0?si=3R5InaOCrB7GRqZW) is showing another **use case** for having access to the values before and after each constraint in Blender. It's showing the limitation of current Blender bake, and how I solved it with a new bake using the same formula in the begining of this thread for inverting child of constraints, which I'm also using for copy paste world/relative matrix. I'm not sure if I should start a new ticket for this with a new name: _Getting access to values coming from constraints and drivers_? In python api and eventually blender ui (rigging nodes?)

hey tal
I made a prototype in C for copy/pasting world space. I haven't tested against the case using the child of constraint but the idea is that it would support that. In python you can then just use the operator instead of adding a temporary constraint into the stack
#115675: WIP: world space copy/paste prototype

hey tal I made a prototype in C for copy/pasting world space. I haven't tested against the case using the child of constraint but the idea is that it would support that. In python you can then just use the operator instead of adding a temporary constraint into the stack [#115675: WIP: world space copy/paste prototype](https://projects.blender.org/blender/blender/pulls/115675)

Hi @ChrisLend
That's great, especially if it's written in C. is it available somewhere? I could give it a test if you want.

My addon actually already has copy paste world and relative matrices (written in python) which works good also with child of constraints, but in general I use temp ctrls because it's easier and quicker (and has a "smartbake") for different space switching technics.

The main issue is about having access to the values coming from constraints (or drivers or any other input).
So my temp controls bake and copy paste world matrix works good with child of constraints, but it's running again into the same issue with other additive constraints, which I also need to add by myself into the calculation.

The problem in Blender is that you see only the values before the constraints being applied. not only you can't see the value coming from each constraint, but you also can't see the overall value (unless maybe you use marix_world in the python api)
This issue is relevant everywhere, also on the gizmo manipulators.

For example, if you turn on the gimbal manipulator, and a bone/object has some constraints applied, they will not affect the manipulator rotation (at least when I tested it with child of constraints).
In maya for example when I'm using a temp control/locator, I can see how it affects the manipulator on the original constrained controller.
This way I can see what rotation order works the best on the controller while it's still being constrained to the temp ctrl.

I hope it makes somehow sense and not more confusing :)

Hi @ChrisLend That's great, especially if it's written in C. is it available somewhere? I could give it a test if you want. My addon actually already has copy paste world and relative matrices (written in python) which works good also with child of constraints, but in general I use temp ctrls because it's easier and quicker (and has a "smartbake") for different space switching technics. The main issue is about having access to the values coming from constraints (or drivers or any other input). So my temp controls bake and copy paste world matrix works good with child of constraints, but it's running again into the same issue with other additive constraints, which I also need to add by myself into the calculation. The problem in Blender is that you see only **the values before the constraints being applied**. not only you can't see the value coming from each constraint, but you also can't see the overall value (unless maybe you use marix_world in the python api) This issue is relevant everywhere, also on the gizmo manipulators. For example, if you turn on the gimbal manipulator, and a bone/object has some constraints applied, they will not affect the manipulator rotation (at least when I tested it with child of constraints). In maya for example when I'm using a temp control/locator, I can see how it affects the manipulator on the original constrained controller. This way I can see what rotation order works the best on the controller while it's still being constrained to the temp ctrl. I hope it makes somehow sense and not more confusing :)

There's no build for it right now. Also it's a prototype and doesn't work with bones right now. Pretty sure it will have other issues too.
It was more exploratory work than a thing that will actually go into blender.

Yeah the issue with constraints not applying to gizmos is known. I made a bug report ages ago about the cursor snap not working if there are constraints on the object.

There's no build for it right now. Also it's a prototype and doesn't work with bones right now. Pretty sure it will have other issues too. It was more exploratory work than a thing that will actually go into blender. Yeah the issue with constraints not applying to gizmos is known. I made a bug report ages ago about the cursor snap not working if there are constraints on the object.
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser Project (Legacy)
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#105882
No description provided.