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

add support for manipulating point instances via UFE #1241

Merged
merged 12 commits into from
Mar 12, 2021

Conversation

mattyjams
Copy link
Contributor

I've been having trouble finding the time to root out the remaining issues with point instance manipulation, so I wanted to just post what I've got so far. Feel free to review (read: ridicule) whenever you have a chance. :)

At a high level, this probably most closely aligns with the XformCommonAPI Transform3d implementation where instead of authoring translation, rotation, and scale values to xformOps dedicated to those operations, we author the values at the appropriate index in the PointInstancer prim's positions, orientations, and scales array attributes instead.

At the bottom, there is a UsdPointInstanceModifierBase class that handles most of the work of getting and setting individual element values in a PointInstancer prim's array attributes. This is then specialized into concrete subclasses for position, orientation, and scale modifiers.

Above that, there are a set of undoable commands that use the modifiers for redo'ing and undo'ing their respective operations.

There's then a UsdTransform3dPointInstance subclass of Ufe::Transform3d that creates commands of the appropriate type, and manages getting a point instance's current translation, rotation, and scale. It also supports querying the inclusive and exclusive matrices of an instance, and setting the instance's matrix (non-interactively).

One wrinkle is that for rotation, Maya/UFE speaks in terms of Euler angles while the PointInstancer schema stores the orientations attribute as quaternions (GfQuath). I have an (admittedly ham-handed) conversion for that in the orientation modifier, but it makes for some pretty jittery manipulation as you drag the handles, and I don't think it's actually working correctly when multiple manipulations are strung together.

The scale manipulator seems to work at least for the initial manipulation, but I'm seeing an odd issue when pulling on one handle then pulling on another where the second pull often scales along both axes rather than only along the second handle's axis.

The position manipulator luckily seems to be working correctly though, so at least that seems to be a win.

I'm hopeful that the things that aren't working are just small mistakes in my implementation stemming from unfamiliarity with the interface. Curious to hear what you all think!

@mattyjams mattyjams added enhancement New feature or request help wanted Extra attention is needed adsk Related to Autodesk plugin ufe Related to UFE component in Maya ufe-usd Related to UFE-USD plugin in Maya-Usd labels Mar 9, 2021
@kxl-adsk kxl-adsk requested a review from ppt-adsk March 9, 2021 00:39
Copy link
Collaborator

@ppt-adsk ppt-adsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good to me from a code structure point of view! Left a few comments / questions, and there is UFE_V2 conditional compilation work that needs a bit of clarification, but this is close to being ready, in my opinion.

I cannot tell at a glance why rotation and scaling manipulation are causing trouble. I have had trouble in the past using matrix decomposition code from Pixar, and had to change to Maya API matrix decomposition to get proper manipulation --- see

// Decompose new matrix to extract TRS. Neither GfMatrix4d::Factor

Possibly something to try later on; I don't feel we should delay converting this from a draft pull request to a pull request because of this issue.

@@ -46,6 +47,10 @@ Ufe::Transform3d::Ptr UsdTransform3dHandler::transform3d(const Ufe::SceneItem::P
assert(usdItem);
#endif

if (usdItem->isPointInstance()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the old Transform3d handling scheme, correct? I see you've adjusted the chain of responsibility for the new scheme in adsk/plugin/plugin.cpp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, yeah. My main concern here was if you have multiple point instances for the same PointInstancer selected, we don't want to fall through to the "usual" Transform3d which may result in many objects that all try to treat their item as a discrete prim and attempt to create the same xformOps on the PointInstancer.

Do you think it's clearer or more safe to just not support point instances in this old handler? Maybe we're planning to get rid of it soon anyway?

lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
public:
using Ptr = std::shared_ptr<UsdPointInstanceUndoableCommandBase>;

#ifdef UFE_V2_FEATURES_AVAILABLE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If UsdTransform3dPointInstance depends on UFE_V2, does it make sense to conditionally compile in UsdPointInstanceUndoableCommands for UFE_V1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I admittedly have only been working with this code against PR 122, so there's an excellent chance this doesn't even build successfully against Maya 2020 as it is right now.

I think my intent was to gracefully ignore attempts to manipulate point instances for UFE v1. The way things are currently setup, it should be possible in UFE v1 to have UFE selections that include scene items representing point instances, even though point instance selection in the viewport is UFE v2 only. In that case, I was aiming for requests to manipulate point instance items in UFE v1 basically becoming no-ops. That was why I had the modifiers and the commands included in the CMakeLists.txt for both UFE v1 and UFE v2.

So I think what I actually have to do is ensure that all of the new files here are compiled for both UFE versions. Does all of this sound right/reasonable to you?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If UFE v1 is intended to be a no-op, then it seems to me that you could just return null pointers when you're asked for commands. That way, you wouldn't need to compile commands against UFE v1 --- and if the commands are the only clients of the modifiers, then the modifiers wouldn't need to be compiled against UFE v1 either. Does this align with your thinking?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, thanks! In the most recent changes, UsdPointInstanceUndoableCommands.h is only included for UFE v2.

I ended up leaving the modifiers in for both versions of UFE, since strictly speaking there's nothing in them that requires v2, so they could theoretically get used for non-Transform3d authoring operations.

Copy link
Contributor Author

@mattyjams mattyjams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback, @ppt-adsk! All great notes.

I'll see if I can "finish" this by addressing what you've noted so far, and add at least a few simple tests for the new functionality. I'll then convert it to a non-draft PR.

I'm a little concerned that the unit tests wouldn't actually cover the issues I was seeing when interactively pulling on the manipulator handles, since just doing cmds.move(), cmds.rotate(), etc. seem to work. Thanks for noting the issues you saw with the USD-side Decompose() though. I can give the Maya-side versions of that a try and see whether that makes a difference.

I'm also still a little concerned about how performance scales with having a Transform3d per point instance scene item and the the single-element modifications that each of those are doing. With the API that's currently available on both the USD side and the UFE side, I'm not sure there's much of a way around that at the moment.

public:
using Ptr = std::shared_ptr<UsdPointInstanceUndoableCommandBase>;

#ifdef UFE_V2_FEATURES_AVAILABLE
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I admittedly have only been working with this code against PR 122, so there's an excellent chance this doesn't even build successfully against Maya 2020 as it is right now.

I think my intent was to gracefully ignore attempts to manipulate point instances for UFE v1. The way things are currently setup, it should be possible in UFE v1 to have UFE selections that include scene items representing point instances, even though point instance selection in the viewport is UFE v2 only. In that case, I was aiming for requests to manipulate point instance items in UFE v1 basically becoming no-ops. That was why I had the modifiers and the commands included in the CMakeLists.txt for both UFE v1 and UFE v2.

So I think what I actually have to do is ensure that all of the new files here are compiled for both UFE versions. Does all of this sound right/reasonable to you?

@@ -46,6 +47,10 @@ Ufe::Transform3d::Ptr UsdTransform3dHandler::transform3d(const Ufe::SceneItem::P
assert(usdItem);
#endif

if (usdItem->isPointInstance()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, yeah. My main concern here was if you have multiple point instances for the same PointInstancer selected, we don't want to fall through to the "usual" Transform3d which may result in many objects that all try to treat their item as a discrete prim and attempt to create the same xformOps on the PointInstancer.

Do you think it's clearer or more safe to just not support point instances in this old handler? Maybe we're planning to get rid of it soon anyway?

lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
lib/mayaUsd/ufe/UsdTransform3dPointInstance.cpp Outdated Show resolved Hide resolved
…tInstancers

This adds a UsdPointInstanceModifierBase class which will be specialized to
create modifiers for the "positions", "orientations", and "scales" attributes
of PointInstancer prims. Derived classes of this base class should implement
the functions to directly get and create the USD attribute on the
PointInstancer (typically with a call to UsdGeomPointInstancer::Get...Attr()
and UsdGeomPointInstancer::Create...Attr(), respectively), functions to convert
values between USD and UFE types, and a function to retrieve the default value
in the USD type.
@mattyjams mattyjams force-pushed the pr/ufe_point_instance_manipulation branch from 090a33e to 41db66b Compare March 10, 2021 22:08
@mattyjams
Copy link
Contributor Author

I got some great notes on this offline from @kxl-adsk and @ppt-adsk, so the newly pushed changes here seem to resolve all of the issues I was previously seeing. There were two important changes necessary:

  • The UFE StagesSubject needed to monitor for change notifications from USD when paths to PointInstancer schema positions, orientations, or scales attributes were modified. It was already doing something similar for xformOpOrder and specific xformOp attributes for the other transform types. That addition is represented in 15ab1de. The somewhat unsavory aspect of that though is that we can't tell which specific instances were updated, so we have to issue notifications for all of them.
  • The value conversion functions for the orientations modifier were rewritten to use Maya's rotation and transform handling utilities rather than USD/Gf's. The manipulation is much smoother now when dragging the handles in the viewport.

I still need to validate this against UFE v1 and then finish up the unit tests, but it looks to be in much better shape now. Should hopefully be ready to convert this to a regular pull request soon.

Copy link
Collaborator

@ppt-adsk ppt-adsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notification scheme is the more troublesome part, but at least we have correctness, if not performance :) Perhaps given the fairly urgent time constraints this is sufficient, and we can move to creating a test and converting this draft to an actual pull request?

I'm still hopeful that we can provide a no-op implementation of the point instancer Transform3d for UFE v1 (i.e. Maya 2020) by returning null pointers instead of compiling actual code --- please set me straight on this if I've misunderstood.

lib/mayaUsd/ufe/StagesSubject.cpp Show resolved Hide resolved
…sponse to USD notices

When individual point instances are manipulated, the change is represented in
USD as an update to the "positions", "orientations", or "scales" array
attribute(s) on the PointInstancer prim that generated the point instance.

Unfortunately though, there is no way for us to know which point instance(s)
were actually affected based on the USD change notification. This means that we
have to assume that *all* of the PointInstancer prim's instances may have been
affected. We therefore need to construct UFE paths for every instance and issue
a notification for each one.
…dler

Point instance manipulation using the older UsdTransform3dHandler is only
supported with UFE v2. Otherwise, we disallow any manipulation for point
instance scene items.
@mattyjams mattyjams force-pushed the pr/ufe_point_instance_manipulation branch from 41db66b to 8c9a659 Compare March 11, 2021 20:17
@mattyjams mattyjams removed the help wanted Extra attention is needed label Mar 11, 2021
@mattyjams mattyjams marked this pull request as ready for review March 11, 2021 20:31
@mattyjams
Copy link
Contributor Author

I converted this to a regular PR, as I believe what we've got now is functionally correct and the major performance concerns we can currently tackle have been addressed. Tests are still missing, but I'll append another commit for that soon.

Thanks again @ppt-adsk and @kxl-adsk for all of your help with this!

@mattyjams
Copy link
Contributor Author

And now with tests in e4d1e20. Kicking off a preflight run.

Thanks again!

@mattyjams
Copy link
Contributor Author

Hopefully addressed the preflight build failures with bf4cbb2. I failed to notice that VtArray::AsConst() was a recent addition in USD 21.02.

The range() function returns lists in Python 2 which can be added together with
the '+' operator, but that's not the case in Python 3.
@mattyjams
Copy link
Contributor Author

There was one more remaining issue in the unit test when running with Python 3 which was addressed in d504519. Other than that, I think the remaining preflight failures are the spurious kind we've seen before.

@kxl-adsk
Copy link

I also run the remaining set of tests. All that is left is the review and we can merge it.

Copy link

@kxl-adsk kxl-adsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good. Thank you @mattyjams !

Copy link
Collaborator

@ppt-adsk ppt-adsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work Matt! Thanks for sticking with this and bringing it over the finish line.

@kxl-adsk kxl-adsk added the ready-for-merge Development process is finished, PR is ready for merge label Mar 12, 2021
@ppt-adsk
Copy link
Collaborator

Agree with Matt, the single failing Maya 2020 Windows python 2 test run appears to be build pipeline related, all tests pass.

@kxl-adsk kxl-adsk merged commit 9a96421 into Autodesk:dev Mar 12, 2021
@mattyjams mattyjams deleted the pr/ufe_point_instance_manipulation branch March 12, 2021 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adsk Related to Autodesk plugin enhancement New feature or request ready-for-merge Development process is finished, PR is ready for merge ufe Related to UFE component in Maya ufe-usd Related to UFE-USD plugin in Maya-Usd
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants