Reevaluating Worldspace and Localspace Treatment (need some dev triage)

I am currently about to publish an addon for that, one of its main usages is to solve the whole handling of worldspace and localspace discussed here. I put quite some time into it to offer a complete and intuitive treatment with visual feedback for blenders transform spaces. Currently testing that everything works fine with 3.0.

2 Likes

Cool, looking forward to try it!
If you need testers ill gladly help with that

1 Like

image

Oh my, this is so handy even as is!

I miss being able to either animate in Local of World with Local or World keyframes sets, but this helps at least to position numerically in this case.

Agree, it is a good starting point and base to develop upon, I guess, once it gets rotation, scale and the possibility to animate in local space would be great. Although as far as I understood, Blender animation works in local space, the difference is that once it gets parented the object doest shift because there is that hidden inverse transform of the parent that prevents it.
I understand this is how Blender works, but I dont see any reason to not improve this a bit further, specially at the interface level, to make this clearer (what are local coordinates and what are the world coordinates) and also expose that hidden transform matrix

3 Likes

So nobody is looking at & giving feedback on the add-ons that I already made? Here are some screenshots:

Transform Helper:
Transform Helper panel

Copy Real Pose (I didn’t link this before, but I think it’s a nice one to have anyway):
Copy Real Pose panel

The documentation just says:

This addon for Blender 2.80 and up adds local and world location editing for objects.

It doesn’t tell me anything details about what it does, how it manages to do that, and most importantly, it doesn’t tell me which of the things it does are so important for the people here. There is a link to its wiki, but that just leads to a “404 file not found” error.

I circle back to the points I made in an earlier comment: this needs a clear proposal. Just pointing at something and saying “do something like that” isn’t going to help.

1 Like

This was discussed in yesterday’s Animation & Rigging meeting. The conclusions can be found in the meeting notes.

2 Likes

Hi @sybren

First of all, thanks for giving attention to this thread and bringing the discussion in the meeting,
I was personally extremely busy and couldn’t follow the discussion as much as I wished.

I’m not familiar with the matrix math behind the parenting system, so the best I can do is try to explain the desired outcome in a sort of proposal as soon as I can. But on the point of the proposal of “how to fix it”, Unfortunately, as I said, I’m not familiar enough with the math to include that in a proposal.

I’ll be back as soon as I can and try to be as clear as I can!

Again, thanks a lot! It’s great that this is in the discussion in the meeting!!

Gave it a quick whirl, the GUI could use some love, for consistent sliders and display from the other transform panels, also integrations to the typical transform panels.

image

Quick GUI entries suggestions:

Properties Editor > Object Tab > Subtabs

  • Dynamic label + icon (optional) to show if current LocRotScale panel are parented transforms or not (global)
  • Loc/Rot/Scale
  • Delta Loc/Rot/Scale (collapsable)
  • Local Loc/Rot/Scale (collapsable)

3D View > Property Shelf > Item panel

  • Dynamic label + icon (optional) to show if parented transforms or not
  • Loc/Rot/Scale
  • Local Loc/Rot/Scale (collapsable)

image

This GUI feedback of what these matrices are the first milestone. The reason to have a dynamic label is for the UX that there should be a notice to show what mode the transform panel is in, if it’s global absolute space, or if parented and relative to local. Or just split the two transform systems and don’t switch spaces without user notice.

Second milestone… option to keyframe what is local and what is global, or know what is inverse or what is global when animating and being able to see both types of transform Fcurves in the animation editors - but this would be a lot more harder to implement with the current API.

Basically, universal nomeclature is Global and Local. Local is parented matrices. If there is no parent, it would just be the “local” axis of the object and it’s movement in it’s local axis, ei… transfrom in Local mode instead of Global mode using the widget. Origin is it’s world center. With parent, origin is the parent inverse relationship ground zero. That’s about it. In animation, you can either animate globally, or locally. Armature bones are animated in local. Objects in Global. Knowing when and in what case in the GUI is important, atleast being able to see when and why and how with sub-panels or panel notice is enough to begin.

2 Likes

This is the first problem – what those panels are showing is not a matrix. It’s a decomposition of the matrix into transform/rotate/scale, and that decomposition does not capture the entire matrix. It cannot include sheer, which means that the global transform of an object cannot be fully shown in these fields. It also means that you cannot edit those fields, because editing them means that the transform matrix has to be reconstructible from those fields, which is not possible.

1 Like

So the current transform panels reconstructs the matrix? Shear is currently not exposed in the UI already, I don’t see the need to also expose those in any other transform space. The idea of reconstructing the object matrix is exactly why we need the GUI, breaking down the hidden 4x3 matrix to 3x3 vector GUI entry groups. If the current transform panels do set the matrix, then showing the internal matrix or relative matrix, or “transform, rotation, scale, shear (hidden anyway)” with the other internal matrix systems should be able to be coded. The transform panel GUI already does this, in both spaces depending on the mode and object type- meaning a simple solution is showing the user what space it’s using when it’s using it and showing vectors or extra panels with the extra vectors to help understand globale vs local/inverse parenting matrices and animate/rig properly, and then later add the ability to work the user input from the panels should be able to be coded in as well as the current transform panel, since that panel are made from vectors driving a matrix…

Again…which matrix are we working? We don’t know. How? We also don’t know. Only intuitively can we figure it out. GUI control to the matrix spaces is exactly what we’re looking for in the tranform GUI.

Eg.

  1. Slide Transform X in current transform panel, this is global.
  2. Object matrix 2m in the X transform vector group moves the object in the X axis in global.
  3. Parent keep transform object to null. Current transform panel remains in Global (or the panel space shows a space switch notice). Cube is globally at 2m X. Local is at 0m X, relative to parent.
  4. Local object rotate 90 degrees X then transform in X 3m. Now Global updates to Y 3m and X remains at 2m in the global panel. The local panel only shows X 3m and X rot 90 degrees. Same slider prop type, which is taking the global and local axis, and doing subtract math on location and trig on the the rotation axis to then “get” world matrix and parent inverse roots for local, and to get local axis from the origin, then write values to the slider (like in the transform panel), where the slider then can “add” any local transform and “Set” local position, which is a new global position really. Global position would update, because ultimately everything is in global space first.

As a user, I can see the transforms and move the values from the slider props or widgets, expected to work just like the current transform panels. It is breaking down object matrices in the GUI, trig should be able to get the other matrices without a problem.

It looks like it might be a loop based logic, which the local GUI entries addon mentioned earlier in this thread has had issues with when it comes to Armature posing - but essentially it’s not. I get that it sounds impossible with the current api, but that is because now Armatures move in pose mode are local, instead of global, then it loops when trying to confront that. The panel shows local rotation of bones, not global rotation. No warning on the space switch.

“Global” stores everything, the matrix data. The transform panel gets it and sets it. The origin of the object is the un-looped anchor to store local matrix data, it’s local origin, so trig is able to add or subtract any local transform data from the global matrix data by the object origin and parent origin. Another anchor is the parent matrix redefining the local offset. And working both gets and manages local vs global transform space without looping. You don’t have to read and write to and from local or global matrices seperately referencing one to the other creating issues with looping, but essentially work only global and run the math from the local origin and parent origins. The 3D Widget already does this with it’s Global and Local orientation to a degree and shows expected behaviour, just… it needs a GUI readout and slider props to re-produce the widget transform behaviour. The props read and write of its matrix data should be able to do the same based on that.

If the widget can transform in Local, a panel should be able to show and write the “local transform” space of the selection and be manipulated locally, like we already can - but with GUI readouts and write abilities. If it’s partly done somewhere, it must be possible.

Imagine this:

  1. I move a cube in global X2 and Y3.
  2. I switch to Local Widget mode. I rotate the object 90 degrees on X up.
  3. I then move the local Widget X3. But this time, I use exact numbers in the local transform panel to the right in the sub panel. I write 2.95m in the local X sllder instead of using the widget.
  4. Now the global updates to Y5.95 and X2, and Local is now X2.95 and Xrotation 90 degrees.
  5. I now need to duplicate the cube, and move it up another x1.15m. I can do that.
  6. Now when I move the parent, the local transforms remains fixed… and I can then align the parent to where I’m working, and I can still duplicate child, move precisely in local X from the transform panel and add in another exact measurement.

The widget in its space updates the correct space in current use, just there is no GUI readout of the changes, no origin local offset memory - and I can not have numeric additive control of the transforms relative to local. If we had this, we don’t have to now do trig in the head to understand what we’re doing, or use exclusive local space widgets or hotkey chaining in “local space” to get the values I want to model or layout precisely - even then as is, there is no relative to original local origin transform memory.

And it sounds huge, because you have to think of all object types, all modes, and all secondary modes of special objects (pose in armature). Many don’t have consolidated transform spaces, ei… the edit mode is vastly different from the armature pose mode. So… it would require cleaning up house, then adding the features. Monumental… and … well starting small could help.

  1. Get Local read into GUI with all objects and modes into a sub panel. No user input, but the math to see and understand local vs global matrix is now split and readable in the interface. Data only stored in Global Matrix, exception Armature local pose space. Make individual tasks per mode/object type for the GUI. I’m not sure how you guys manage projects in the tracker, but the smaller the task or prototype, the better. So when I use widget or transform mode in “local” I can see those spaces updating correctly. Keep it minimal, same as the transform panel in layout and design, in a sub panel.

  2. OR create a quick user notice in the Transform Panel to show why and how the transform space is changing, like a label with an icon explaining that the transform panel is now exclusively in “Parent Inverse” mode and not “Global Mode”. Do the same to clarify what space the other transform panels are in. Let the user know how Blender works first from the GUI. It’s a smaller task, and might point out how to consolidate the transform readouts and user control.

Addon feedback:
Your addon with the Transform Helper works alright as a readout, though not a fan of the wide layout and lack of labeling on the axis - they were cut off on default, maybe stacked vector groups like the transform panel will help. The parent inverse group readout also doesn’t seem to update when moving the object in local widget or transform space, even in local transform mode I am moving things in global. Evaluated transform looks like it’s “Global” so might need better labeling there. But I like the initial idea of it. It’s exposing the hidden matrices so it’s understood.

1 Like

Good Point!

You actually can:

You can hit G and then Z and use the num-pad to enter the transformation value along local axis.
It even shows the “Local Z axis” label.
The problem is that you can input that exact value as a single scalar value, but you can’t animate that single value alone, and thus have a single F-Curve in the graph editor to precisely animate the curve. You basically can’t insert single key-frame on that Local Z value. At least as far as I know.
You can certainly animate position, but you end up having 3 F-curves, and none of them represents the Local Z value.

3 Likes

Yes, here is the short coming and UX inconsistency. We can manipulate in local space, but there is no GUI or animation entries for it. You can’t animate local. There is no memory retention of local space, you can only see it on on on operator movement (so you can’t move, work elsewhere, then model additional local space edits intentionally relative to it’s local movement a while back). There is no panel to move the object local space other than with widget or hotkey chaining, making numerical values and matrix retention and additive transforms work hard or feature “missing”/“incomplete”.

The only exception is armature bones, but then that’s all local, and you loose global.

The only workaround that I could find is to parent the child object to its parent before transforming them (pos=(0,0,0), rot= (0,0,0) scale (1,1,1) for both parent and child). In that particular case, the coordinate shown are the same as they were relative to the parent. But it’s not always convenient, since sometimes I have my objects already transformed.

Anyway, this has been brought into discussion by Sybren, and probably this:

could be a step towards having a different parenting behavior option, I personally have to wait until the option gets implemented and put into a patch to see if that’s what we are asking (my fault, not enough familiarity with the parent inverse matrix),

what do you think about it @Draise ?

2 Likes

I think some people are misunderstanding what local & global coordinate systems are. The properties you see in the transform panel are local transforms, i.e. the transform relative to the parent. This is true for both objects and bones. The local translate/rotate/scale properties are combined into a matrix, the local matrix. Doing a matrix multiplication of all the local matrices of the object and its parents (in the right order) will result in the global matrix of the object. It represents the same final transformation, but then expressed relative to the world coordinate system instead of the parent one.

1 Like

Hi Sybren, I suspected that there was a misunderstanding in terminology. I’m probably making confusion with the “Local” and “Global” coordinates system… I’m pretty confident that you are right and I have a misconception of what “relative to the parent” means, but I’ll try to explain my (probably wrong) idea with an example:

If the “local transform” is equivalent to the “transform relative to the parent”, for example, I would expect that entering a (0,0,0) position values in the position properties of the child object, would transform it to the origin of the parent In any case. But that’s not the case, unless the children and the parent aren’t in the same position at the moment of parenting:

I parent a Cube to an Empty, at the moment of parenting they both have a non-zero World position

If I don’t move the empty and enter (0,0,0) in the cube’s Location, it snaps to world’s origin:


In my mind, that’s World’s zero, not relative to Parent zero.

I would expect that entering (0,0,0) position in the position field of the Cube (that is supposed to be expressed in the Parent’s coordinate system), would put the Cube in the same position of the Parent, because in Parent’s space, the (0,0,0) coordinate represents the Parent’s origin (Again, at least in my mind).

Another example (In this case, this makes absolutely sense to me!):

Ok this is an analogy, we don’t have objects parented to other objects BUT…
Let’s pretend for a moment that vertices of a cube are actually objects parented to the cube’s origin. In edit mode we can see and manipulate the position of the vertices in Local and Global space, and they always make sense! No matter what, if I enter (0,0,0) while in Local mode, the selected vertex snap to the origin of the cube, if I enter (0,0,0) in Global mode, the selected vertex snaps to the World’s origin:

That makes totally sense! And that’s always the case, (afaik) and to me, that should be always the case with transformations of objects parented to other objects too! Not only with vertices positions!

6 Likes

You have the right idea, but the hidden parent_inverse matrix is what’s throwing you off. In the sense of “local” and “global” transforms, that matrix works like another parent. Let’s say the objects are called C (for the child we’re looking at here), P (for its parent), and GP (the parent’s parent). Sounting from the child object, these are the matrices that matter:

  1. local transform of C
  2. parent_inverse of C
  3. local transform of P
  4. parent_inverse of P
  5. local transform of GP

Multiply all those matrices, and you’ll get the global transform of C.

Note that for simplicity, this still ignores the “delta transform”. If you do want to take those into account, they go on top of each local transform.

1 Like

This is why it needs to be clarified and explicit in the GUI, at least with labeling or user warning when spaces change. It’s not currently clear and causes confusion where the same panel changes space without user warning and assumes you know what space you’re working in. That is a start, expose the GUI for a better UX of how it works currently. Maybe even just exposing the concept of “parent_inverse” and local tranform, and also the multiplied global readouts as actual tooltip-able readable and noticeable concept in the GUI, instead of learning it kinetically and intuitively and hitting frustration (specially coming from other software that have both spaces in the GUI) using transform operators that doesn’t reflect what they do in the interface (ei, use Local widget space and it tansforms in global/parent inverse panel space and keyframe space).

Currently, when you parent, it doesn’t tell you what space the transform panel is in. When in “global” or relative to world, it also doesn’t show - there also are no tooltips about it. It also is not clear when you have started using inverse parent or local, or when we are keyframing in which space (it assumes you already know the one space you keyframe in or are in). An experienced user would know, but it’s guessing work for most.

The panel or interface needs labeling to show what space we’re moving in. Could be a minimum update to the UX to add tooltips or dynamic labeling to the spaces you’re in, even just for the Blender nomeclature idea of the space “inverse vs local”. Check if parent, update label to be “Parent Inverse Transform Mode”.

I also agree with @RiccardoBancone, the idea is when in “Global” you are relative the world origin, and when you are “local” you are relative to self if not parented, or relative to parent if child.

“Inverse Parent” might be the nomeclature to “relative to parent in local space/local” and the “global” might be “local space without parent/global”. And to get true “global” relative world position, you do the math from Blenders “local space” and world origin - but ideally we shouldn’t have to have a 3d modeling, animation, rigging and layout UX while thinking of math.

The transform GUI just needs some organization, exposure, and clear nomeclature. And also, maybe later, sectorization of the Fcurve data of the separate spaces with keyed transforms relative to self/parent or relative to world origin. It could even have a “Delta Transform” and “Delta Keyframe” and “Delta Autokeyframe” mode too, exposed. Right now animating in Delta is transform, switch space or apply space, each movement a double step. Delta transforms also are not exposed in the property shelf of the 3D view which is inconsistent with the object transform panels.

Clearly deep down, Blender does use the concept correctly where you move relative to world origin or relative to parent/self somewhere - it is just not discoverable very easily as a UX for the end user and their control yet, or it assumes you know of the spaces already - though it’s nomeclature is either unclear, hidden or changes automatically without user knowledge.

I know this could feel like a hot topic, because it’s a core feature of Blender and it’s 3D space since the beginning of its time - but when it comes to crunch and production, sometimes you just wanna animate only in local, then move and parent or unparent anything or reparent and the local keys would remain the same. Same thing with animating in local and offsetting it by global, without needing to make rigs or parent to empties. Same thing with modeling. Or moving things around. Have some local rotations and scale, but position in global, etc. Then globally scale everything without affecting the relative local scale - and all without the need of using empties.

And now, with GN you have to confront that too, are the points positions relative to local? Or relative global world origin? That too would need to be clarified and made a consistent UX. Right now the object nodes has “original” and “relative”… to what? Original to… what space? Consolidating consistent nomeclature also is necessary.

1 Like

Thanks @sybren, that is extremely helpful! And the note about the delta transform is very welcome.

So the parent inverse is like an extra parent that gets created on world origin with (0,0,0) rotation and uniform scale 1. So when you say that those values are “local”, they are actually local to the parent inverse, and not directly to the parent.

Since the parent inverse is hidden, without reading the documentation (I know we should read it!:-P) users intuitively think that the values are local directly to the parent. But they are not, they are local to the parent inverse.

So I’m thinking about a proposal that help improve the UX, @Draise already suggested clear and standard naming of “local” “global” ecc…
I’m not sure I understand if he proposed the naming or just described the current situation, anyway here is my suggestion to the label that any transform field in the interface should somehow have:

World” or “Global” : If an object is not parented to any other object.

Local to Parent”: if an object is parented directly to an object, without the parent inverse (Currently not possible afaik, until the option discussed by @sybren in the meeting is added)

Local to Parent inverse”: if an object is parented to another object with the current blender’s behavior.

About the transform widget orientation:

World or Global: handles aligned to the world

Parent: handles aligned to the parent

Object: handles aligned to self ( I prefer it to the word “local” since “local” is ambiguous without specifying “local to what”)

View: aligned to view

Custom: pick an object and align handles to that object (It could even have two modes, one that just picks and use the orientation and another that keeps the orientation in sync with the picked object, so you can use that object as a ruler)

In general , as @sybren stated, in most of the cases, the values exposed are “local” , so without specifying local to what, that word loses meaning and can get to confusion, I would avoid using it alone.

About the Delta Transform, I think is already great that blender already exposes it’s values in the interface, other software don’t do that afaik.
It’s okay to me if the values stay in the properties editor and are not exposed in the N panel (so it doesn’t get too cluttered), because you generally explicitly apply that on purpose, thus you are generally aware that there is a delta transform. Therefore I don’t like the Idea to add another label “Local to Delta” BUT if there is a non zero Delta, there should be some UI warning that shows at least that it’s there (maybe a “delta” icon near the label that I proposed?).

Speaking of delta transform, afaik there is no way to directly reset it , other than subtracting the values one by one manually. It would be nice to have an operation to do that.

1 Like

This is slightly clearer when you have the Python tooltips enabled, because then you see it’s always the same – object.location, object.rotation_euler, etc. There is no switching of those fields, they always show the same thing.

I know, which is why I personally expanded the manual to explain these concepts better (it was an area equally needing some love, and writing clearly is easier for me than to design a clear and unintrusive UI). You’re preaching to the choir here :wink:

100% agreed here. The UI should be clear & explicit. Right now too many areas are akin to saying “my velocity is 5” – not only do the units matter (5 km/sec vs. 5 mm/hour), but also the terminology (“velocity” includes direction; the number presented in that sentence is “speed”).

This may sound blunt, but please stop repeating these things here. Every time it’s repeated, it takes away clarity and focus from the thread, and eats up time from people reading it. This I already summarized above.

These names are already well-defined, and can be found in any geometry book.

That’s a misconception. Local is local, there is no “local to what”, it’s a mathematically well-defined term. What you mean is called “relative”, which, as @Draise already pointed out, should always be accompanied by the “to what” part.

Me pointing at geometry books may come across as elitist, and that’s not my intention. What I mean is that this is a mathematical topic, and that we shouldn’t reinvent terms for things that have had a name in math for centuries. Doing so helps nobody – people unfamiliar with the maths have to learn the terminology anyway, and people who are familiar with the math will be confused. The latter will include developers, and confusing developers is the best way to get a buggy, hard to work with system.

1 Like