UV/prim aware AbstractControl

   3040   23   4
User Avatar
Member
219 posts
Joined: March 2023
Offline
Hello, I really love the AbstractControl on apex!

I was experimenting with doing a kind of controller I always dreamed to be able to do with rig, but often work so badly in other DCC it not worth it, but it seem to work pretty well on apex with the animation state.
Basically, controller constrained to a primitive on an predefined uv space, here a demonstration :

Image Not Found


I'm simply using the 'y' input of the AbstractController and a CurveConstraint and use the result Xform on the abstractController :



Here the main problem : this only work by moving the mouse up and down, which mean depending on the view angle, it can become counter intuitive.
Could it be possible to have special controller that could rely on a specific 'closest point on' primitive that could work on curve or/and primitive with custom uv space ?

I see lot of application for this kind of controller, one exemple being constraining a 'Mouth corner' controller, which would follow a surface plane following the shape of the head.
I'm personnally rigging alien like creature, having controller that could follow a rigged curve like on the video above would make animating these super comfortable ! (even more if we can consider the ability to 'add' object procedurally on these uv space constraint)

Hope I'm making sense
Edited by Jacquesf - Dec. 6, 2023 13:59:00

Attachments:
007460_houdini_rXHSMw8xGy_2023-12-06_19-46-04.webm (1.5 MB)
007462_houdini_Q4MHW8D3Gt_2023-12-06_19-48-04.png (91.4 KB)

Head of Pipeline @ LightVFX
User Avatar
Staff
64 posts
Joined: May 2021
Offline
Hi there, oh that's a beautiful use of it.
Thats a very good suggestion and very much possible. The abstract control is actual also nothing but a graph that interprets the ui event and translates it to control parameters. We are intending to flesh that one a bit more out anyways. So creating a graph that relies on uv values for the closes point on a prim should be possible.

And we still have it on our radar to support completely custom control graphs in the future
User Avatar
Member
219 posts
Joined: March 2023
Offline
Wow, if the abstract controller is the product of a graph instead of being a python script, I'm truly amazed ! this further push the potential of apex, giving more control to the user. I briefly tried to look at the apex animate state to see how control were handled and I had the impression the TransformObject and AbstractController were 'hardcoded' into the initialization phase, so that reassuring !

would you be able to give me some redline to follow concerning where the graph of that abstract controller is ? I'd love to study it !

Btw, we briefly met during the HIVE 20 after your presentation, we talked about the possibility to extend the bookmark system to support channel looping into themselves per bookmark, you told me that they support being extended via an API, do you know where can I start looking up for that ? even if it just pure code.
Thanks you !
Head of Pipeline @ LightVFX
User Avatar
Member
918 posts
Joined: March 2014
Offline
This is a really cool example, thank you for sharing, Jacques.

I'm still struggling hard to split the concept between building graphs by hand and using graphs to build graphs. As I feel the need to understand building manual graphs first before proceeding to the build graph for a graph stage.

In the pillow example, the component graph to build the blend shape abstract control is passing properties to the add node, which provides x y limits to the control. How would I set these limits on the abstract control node if I were to build the graph manually?

Any help is much appreciated.

Andreas

Attachments:
abstract_properties.jpg (173.0 KB)

User Avatar
Member
213 posts
Joined: June 2023
Offline
Andy_23
In the pillow example, the component graph to build the blend shape abstract control is passing properties to the add node, which provides x y limits to the control. How would I set these limits on the abstract control node if I were to build the graph manually?

If by "manually" you mean without Autorig Component, the properties are just point attribute. You can set them in Python or Vex.

If by "manually" you mean without writing code, I don't think you can do it at this point... the node that is supposed to do this is (I guess) APEX Configure Control, but it doesn't have Abstract Control stuff now. Hell, it's even an undocumented SOP itself.
User Avatar
Member
8617 posts
Joined: July 2007
Online
kodra
the node that is supposed to do this is (I guess) APEX Configure Control,
if we are talking about manually building graphs then what is supposed to do this is not a node but APEX Network Editor itself should have a way to set properties and tags for nodes, which I suppose will come in time
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
219 posts
Joined: March 2023
Offline
What I would do as there isn't a way to setup properties of a node in the editor yet, is to create a second graph that take your graph as an input, add the parameter through dict building using the UpdateNode node, and output it back.

It also a good exercise to learn about graph building !
Edited by Jacquesf - Dec. 18, 2023 07:04:12

Attachments:
007535_houdini_MOl5ZTWSM8_2023-12-18_13-02-31.png (862.5 KB)
manuallautomatic.hiplc (106.8 KB)

Head of Pipeline @ LightVFX
User Avatar
Member
213 posts
Joined: June 2023
Offline
tamte
kodra
the node that is supposed to do this is (I guess) APEX Configure Control,
if we are talking about manually building graphs then what is supposed to do this is not a node but APEX Network Editor itself should have a way to set properties and tags for nodes, which I suppose will come in time

APEX Network Editor can't even set the controls' colors (afaik) at this point

But the even bigger problem is that properties are again undocumented too. So even if you're willing to make your own tools, you will need to dive in the few examples files and go back and forth.
Edited by kodra - Dec. 18, 2023 07:25:35
User Avatar
Member
8617 posts
Joined: July 2007
Online
Jacquesf
is to create a second graph that take your graph as an input, add the parameter through dict building using the UpdateNode node, and output it back.
As an exercise, sure

But realistically this is way easier done in a wrangle and more readable as you don't have to go to different graph and try to understand what it does

However the other problem is to know which property names are being looked for by various tools, so it will be very important to have that documented in the future

Also APEX invoke is very strangely designed in an opposite way to all other SOP and it has graph as first input and not the main geo (probably due to preexisting sop input architecture limitations)
Therefore bypassing it breaks the flow which complicates debugging
Edited by tamte - Dec. 18, 2023 07:26:06
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
213 posts
Joined: June 2023
Offline
tamte
Also APEX invoke is very strangely designed in an opposite way to all other SOP and it has graph as first input and not the main geo (probably due to preexisting sop input architecture limitations)
Therefore bypassing it breaks the flow which complicates debugging

That's another example that made I believe when SideFX designed APEX, they used an abstract idea ("APEX graphs are both geo and logic at the same time") rather than concrete use cases ("what happens when the user toggles bypass flag?") as the guideline.

Anyway I've complained too much about APEX... let's just hope when it's more documented the (not-so-big) community's Python and VEX will mitigate those UI paper cuts.
User Avatar
Member
219 posts
Joined: March 2023
Offline
I'm not gonna complain about a system that was prematurely released because an update was long overdue, if they spent the extra time that was needed to get the documentation and all the missing tool there currently see, we wouldn't have seen houdini 20 in another year.

I'm happy that Apex got released in this version at all, I'm not trying to defend sidefx for the lack of all the tool that would make our life easier, but there a point where we need to understand that this is a software in a Alpha stage, remember Solaris ?

I've been rolling with the punch since the beginning, reporting dozens of bug and learning each graph we have access to, and I'm happy to say I can do pretty much all the rig I'm dreaming of now, deciding to use apex early is gonna come with pain, lets just discuss about the amazing thing we will be able to do.

you guys already hijacked my forum post for an unrelated question ! I'm still hopping more conversation about this primuv based abstract control
Head of Pipeline @ LightVFX
User Avatar
Member
918 posts
Joined: March 2014
Offline
Thank you all for your input and @Jacques for that example.

I so wish there were more examples and documentation out there. I cannot wait for the master class.
User Avatar
Member
213 posts
Joined: June 2023
Offline
Jacquesf
you guys already hijacked my forum post for an unrelated question ! I'm still hopping more conversation about this primuv based abstract control

Well, sorry for that. Back to the original topic, I'm quite sure most of the behavior of Abstract Control is "hardcoded" into the animate state, just as you said.

(for reference: line 1708-1757 of apexanimate.py and "AbstractControl" class in control_2.py define how the "mapping" happens)

I'd like to know more details if esttri doesn't mind to enlighten us, but I think when she said "abstract control is nothing but a graph..." it definitely didn't mean we can just plug in a graph and change how it works without changing (many lines of) animate state's python implementation.
Edited by kodra - Dec. 18, 2023 08:04:36
User Avatar
Member
219 posts
Joined: March 2023
Offline
I believe the goal is that we can create our own gizmo and controller by building apex graph, even if it not the case now, I heard that being repeated a few time in a few different place.
Head of Pipeline @ LightVFX
User Avatar
Member
177 posts
Joined: Jan. 2014
Offline
Jacquesf
What I would do as there isn't a way to setup properties of a node in the editor yet, is to create a second graph that take your graph as an input, add the parameter through dict building using the UpdateNode node, and output it back.

It also a good exercise to learn about graph building !
How do you know that graph__UpdateNode1has that x_min property? the apex data logic is still black magic for me😭
Edited by Ivan L - Dec. 18, 2023 11:22:44
I contribute to the beauty of this world
User Avatar
Member
219 posts
Joined: March 2023
Offline
Ivan L
How do you know that graph__UpdateNode1has that x_min property? the apex data logic is still black magic for me😭

I don't, I just saw it on the screenshot, everything is pure guess at this point.
also, it not the UpdateNode1 that have the x_min attribute, UpdateNode simple take the graph as an input as well as an nodeId and update the corresponding node, the x_min attribute is added to the AbstractControll node instead
Edited by Jacquesf - Dec. 18, 2023 11:45:35
Head of Pipeline @ LightVFX
User Avatar
Member
8617 posts
Joined: July 2007
Online
Jacquesf
Ivan L
How do you know that graph__UpdateNode1has that x_min property? the apex data logic is still black magic for me😭

I don't, I just saw it on the screenshot, everything is pure guess at this point.
also, it not the UpdateNode1 that have the x_min attribute, UpdateNode simple take the graph as an input as well as an nodeId and update the corresponding node, the x_min attribute is added to the AbstractControll node instead
per my observations, the properties of the nodes are arbitrary, meaning any node can have any properties you want which on their own are just data storage similar to attributes or user data

however the individual tools like Amimate APEX Python State may be looking for some specific ones, in this case you can see them defined in the Animate Python State:
                if isinstance(ctrl, AbstractControl):
                    mapping_parms["x"] = ctrl_mapping.x
                    mapping_parms["y"] = ctrl_mapping.y
                    input_parms = self.scene.getData(f"{ctrl.rig_path}/graph_parms")
                    if input_parms.contains(ctrl_mapping.x):
                        ctrl_parms["x"] = input_parms[ctrl_mapping.x]
                        has_abstract = True
                    if input_parms.contains(ctrl_mapping.y):
                        ctrl_parms["y"] = input_parms[ctrl_mapping.y]
                        has_abstract = True
                    ctrl_parms['x_min'] = ctrl.x_min
                    ctrl_parms['y_min'] = ctrl.y_min
                    ctrl_parms['x_max'] = ctrl.x_max
                    ctrl_parms['y_max'] = ctrl.y_max
                    ctrl_parms['show_x'] = ctrl.show_x
                    ctrl_parms['show_y'] = ctrl.show_y
                    ctrl_parms['lock_range'] = ctrl.lock_range

that's why I mentioned it's important that the Docs mention which properties the tool can look for on particular node types, as that's similar to RBD or Vellum solver docs whcih mention which attributes they can use if found
Meaning its not the node like AbstractControl that has specific property names, but the individual tools that look for specific names
Edited by tamte - Dec. 18, 2023 11:57:21
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
213 posts
Joined: June 2023
Offline
I think the problem isn't Python or graph, it's more about how the API is designed and how it's taught.

It seems like quite some UI logic is defined as graph, but at its current state it only makes things harder not easier. Briefly skimping control_2.py#buildControlGraph and ApexScheduler made me realize how tightly the graph logic and python are coupled.

I guess it's possible to skip TransformObject and AbstractControl and build those graphs directly? People who are more confident with their Python reading comprehension might try it. Not me tho.
Edited by kodra - Dec. 18, 2023 13:58:23
User Avatar
Staff
64 posts
Joined: May 2021
Offline
Hi there,
a few more answers from my side. And sorry for the late reply, I am recharging batteries a bit and stayed away from my machine for a bit.

Yes the state manages indeed quite a large number of graphs and a lot of these graphs get created or modified on the fly. That keeps our viewer state flexible fast and light weight. Managing the actual execution via graphs is a big advantage for performance. When it comes to modifying the graphs we execute then its a bit different because we are not running that on every mouse drag on playback, so we have a bit more wiggle room. So you can modify all of those graphs either via python or via other graphs. both ways are legit. Some sections in the viewport are currently managed with python as has been correctly observed.

One of theses graphs that constantly changes depending on what you do in the state is the scheduler graph. That one manages which bits of graphs/rigs are evaluated when. It is in a way the control centre of your interactive state. That scheduler gets especially important as soon as you have dependencies between rigs, e.g. by using constraints. The order of invocations and the updating of the data is all being managed here.

The controls are indeed nothing but graphs that define how the ui event is interpreted and translated to parameters that the rig understands. And every time you interact with a control that control graph is in fact dynamically added to the execution in you scheduler. So first the control graph is being evaluates and updates your current rig input parms and then the rig is being run with the updated parms.

The abstract control and the transform control are currently hard coded in in terms of the management around them. The actual core of them is still just a graph though. The state might be more opened up in the future. Ideally we would support that without the user needing to change the state code. This is what i meant with the fact that we have it on our radar

Coming more to the abstract control and node properties. Properties are nothing but custom metadata stored as a dictionary per node. You can store anything you want there. When the state creates controls then some metadate can be read from the node properties that can help define how that control looks. Configure controls is in the end just updating that dictionary per control node. The configure control node definitely needs the helper card, ill keep you posted once its added early January, when I am back.

Here is a quick description of what you can use to change how your control looks like. A bit rough, but it should give you an idea 😊:

properties: - dict
control: - dict
shapeoverride: str, - defines the shape name you want to assign to you control. the transform control has some default you can choose from. you see them in the dropdown of the configure controls node, you can also provide your own to a character if you pack them up using the second input of the configure controls node.
color: - vector3, matrix, defines the color of your control as a normalized rgb vector
shapeoffset: - matrix4, defines an offset of the shape that allows you to adjust the transformation of the control to fit more to your character

more specific for the abstract control

properties:
control:
parms:
lock_range: - int: 0 or 1: defines if you want to lock the min and max range of you control or if you want to go above it
x_max: defines the max value for the horizontal drag, if lock range is to you can not set a value higher than that. Otherwise it will be used as an orientation for the range when you drag on the given control in the viewport
x_min: defines the min value for the horizontal drag
y_max: defniens the max value for the vertical drag
y_min: defines the min value that can be set using the vertical drag, aka the y value to connected it to in the abstract control node in the rig
Edited by esttri - Dec. 19, 2023 17:35:55
User Avatar
Member
219 posts
Joined: March 2023
Offline
Thanks a lot of this amazing insight esttri !

I just can't wait to see the state evolve toward something we can easily update with our own graph, is this something we can expect while in H20 or is that planned for a futur houdini release ?
Head of Pipeline @ LightVFX
  • Quick Links