Need help on python scripting ( Real-time viewport recorder)

   4295   7   2
User Avatar
Member
12 posts
Joined: Jan. 2016
Offline
I am working on a python script that bakes the hand movement of geometry with mouse in the viewport over the time and creates keys on each frame. In other word, I want to move my object with mouse in the view port and get the Transform/Rotation/Scale keyed on each frame.

Currently I am using hou.selectedNode() and the hou.parm() to access the specific parameters that I want to bake.
Then I use a for loop to generate key on each frame. Immediately after pushing the bake button, the script bakes the parameters value on the first frame for entire time line. I have tried using while loop with time.sleep() to wait for a bit after setting key on each frame, but it freeze the view port and I cant move my geometry. Is there anyway to make my code somehow that constantly check the new values of object parameters on each frame and allow me to work on the view port while it does its job in the background? Is this related to multi threading?

Here is my for loop
for f in timeline:
setKey = hou.Keyframe()
setKey.setFrame(f)
setKey.setValue( keyValue )
ParmList.setKeyframe(setKey)
hou.setFrame(f)

Thanks,
Edited by Blacko0ps - March 2, 2017 12:09:00
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Moin,

you may have to set up an array in a
solver
to store the recorded data. The for-loop you are using runs within one frame, so it doesn't record over time.
In theory (actually in reality, too) you can keep a local variable (including an array) in a python node without having to loop, so you'd simply grab the current frame number and store the read data in the array. The problem with this is that evaluation of that python node is not “guaranteed”.
Maybe there is a more elegant solution, though: If you can grab an item (a null) and move it while recording, you could simply capture the position data of that null. No need for code at all.

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
12 posts
Joined: Jan. 2016
Offline
Thank you Marc for the reply! Sorry, I am still new in python, Do you mean to use a solver node or its a function? could please explain it more in detail.

Thank you
Edited by Blacko0ps - March 3, 2017 21:26:46
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Hi, anonymous “Blacko0ps”(?),

a “solver” (node) gives you access to values from the previous frame in a running timeline. That is Houdini's (only) way to provide consistent data, except for setting global (environment) variables. If you want to build an array that holds XFOs (transforms) in an array “over time”, this is the reliable way to do it. Look for tutorials on “using a solver node”, also check the documentation on that node. In general I think that Houdini's documentation does a very good job, what it is lacking you can really only learn from trying things out for yourself.

The alternative approach I mentioned is a Python script node. I assume that such nodes get included once per compilation in Houdini and called as a function, and since all variables in Python are “global”, they keep their values “over time”. So you can check if a variable (e.g. an array) exists and, if not (i.e. on frame 1), initialize it, then add the current XFO to it.

In the end both solutions work the same - only that the pure Python method, in theory, also works without the timeline running (but, unfortunately, not very reliably so).

The easiest way to store transformations is to set keyframes on an object that gets moved (like I suggested above). If your setup allows for an item to be controlled by your mouse in order to capture data, I would choose this solution.
For example: If you want to capture camera motion, you can do so “live”:



Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
12 posts
Joined: Jan. 2016
Offline
Thanks Marc, For this project I am limited to use python. So your python node sounds more suitable for my project. Currently, I am writing my code through new tool on shelf. I assume when I use python node, I should connect my geometry to the node and use the first input in the node to collect the data, please correct me if I am wrong. But, do you think using this method won't freeze the viewport? The main issue is that, while the code is running, I don't have any access to the viewport.

Thanks,
Alireza
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Hi, Alireza,

I am not sure I can follow …

The way I understand your task is this:
- you have an item (Null, geometry, whatever)
- that item has an initial XFO
- you want to transform that item over time
- and store that (ongoing) transformation sampled by frames on the timeline

If that is correct, then capturing the transform into auto-keyframes is the easiest way.
If you *want* to use a Python node to capture the data into an array, what I would do is object-merge the (moving) geometry node into your “scripting node”, set its import options to “transform into this item” (this way you get global positions instead of local) and connect the output of the merge node to your script node.
Inside the script node you then can access the point attribute from that input (for position) or address the merge node through Houdini's Python API. Something along this idea:

currentposition = hou.Vector3(node.parm('whatever_your_geo_node/tx').eval(),node.parm('whatever_your_geo_node/ty').eval(),node.parm('whatever_your_geo_node/tz').eval()) # create Vector3 from node's transform parameter channels

That's the current position (as the variable name suggests), now if you create an array on frame 1 (checking current frame) and only add the current position indexed to its frame into that array (only initializing the array on Frame 1), you get a “history of transforms”. Since Python nodes remain in memory, that array is a global variable.
The more elegant way, as pointed out above, is to check if the array exists yet and initialize it if not (that way the node can get baked fresh even if it is not at frame 1).

This gets executed/evaluated ONCE each frame, so there cannot be any lockup. If you need a higher resolution than 1/frame, you may have to increase the subframe count, but the tech will still be the same.
The question remains why recording that data to keyframes isn't sufficient - if you don't want to use the captured data to manipulate other channels right away (which was what I did, and that does not work very well in Houdini).

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
12 posts
Joined: Jan. 2016
Offline
Ok, now I totally get what you mean by using auto-keyframes and object merge node.It works perfectly, and gives me the values for transformation on each frame. Thanks a lot!

Now I am trying to figure out how to make my object merge node dynamic. I mean is that every time I select a node my object merge path changes. Is there anyway to do that?
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
> I mean is that every time I select a node my object merge path changes. Is there anyway to do that?

Not sure how this is meant … there is a “get selected node” feature in the Python API (I am not familiar enough with that to tell offhand how it's named), so you could have a Python node question the currently selected object and, e.g., capture position data from that into an array as scribbled above.

But … I am not sure if that is what you're after …

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
  • Quick Links