Jump to content


  • Content count

  • Donations

    0.00 CAD 
  • Joined

  • Last visited

Everything posted by Alain2131

  1. Hey Masoud, a quick Google search and you'd have found a few places telling you the answer. An odForce search would have also answered you. Real quick, the data is stored into a detail attribute on the node, so using the detail function, you can retrieve it.
  2. Extract rotation from packed geometry to a bone (Python)

    Hey guys ! Just thought I'd come back to this for a bit, adding some functionality. I had completely forgotten about this until I received some notifications of activity on the thread. I'm glad it's useful to some people, at least ! 1) There is now a toggle leaving you the choice between separating each packed pieces into its own geometry node, or to have only one geo with all of the skinning. The previous default was separate pieces for each packed geo, which is heavier in general. 2) I added some UI to be able to name the subnet and the geometry nodes, for convenience. 3) There is also a progress bar showing the progress of the baking process. 4) And finally, I applied a Euler Filter to the rotation. I did some other inconsequential small tweaks. I checked, and having scaled packed pieces works perfectly, no matter if it is before the simulation, after it, or both. Same for pre/post translation/rotation. The extracttransform node really work like a charm. rigidBody_baker_tests.hip RigidBody_Baker.hda P.S. This have now turned more into an Tools (HDA) topic than scripting. If an admin would prefer that I create a new topic in the Tools section, do tell me.
  3. Hello ! I'm trying to get an animation transfer from packed geometry to bone to work. It works when transferring the animation to a geometry (there is no visible problem in the viewport), but in the Animation Editor, the keys are not very clean. See below Here is the nice and tidy one, the source : Here is the result from the script, the baked one : As I said, in the viewport it works, but these keys are not very clean. Why do they look like that ? How to make them cleaner ? (See script and scene below) BUT ! What I really want is to bake the animation on a bone, not on a box. The previous problem still apply to this situation. The position works, but the rotation just fails miserably (with the same code !). The very same rotation is applied to the bone as the previous one that was applied to the test box, but the result in the viewport is not the same at all. The red is the source and the blue is the skinned box (to the visible bone). Why is that ? What am I missing ? Here's the code : node = hou.pwd() obj = hou.node("/obj") def extractEulerRotates(self, rotate_order="xyz"): # Thanks to the Houdini help page for that. But there is a problem here though return hou.Matrix4(self.extractRotationMatrix3()).explode(rotate_order=rotate_order)["rotate"] # The extracted rotation from this function is incorrect. def bakePackedAnim(): # Saving out some time-related variables intialFrame = hou.intFrame() startFrame = int(hou.hscriptExpression("$RFSTART")) # Don't know how to do it in Python endFrame = int(hou.hscriptExpression("$RFEND")) # Don't know how to do it in Python hou.setFrame(startFrame) # ''' # Initial setup : Creates a bone and a box, and then skins the box to the bone with a Capture Proximity. theBone = obj.createNode("bone", "tranformed_bone") # Create only one bone. Would put it in a loop to create multiple. # theBone.moveToGoodPosition() # Easier to work without it. Will uncomment in the end # TO REMOVE... But weirdly with -not a bone- it's working. Hmmm. testGeo = obj.createNode("geo", "test_geo") fileNode = testGeo.allSubChildren()[0] testTransform = testGeo.createNode("xform") testTransform.setFirstInput(fileNode) testTransform.moveToGoodPosition() testTransform.setDisplayFlag(True) testTransform.setRenderFlag(True) # Remove up to here skinnedGeo = obj.createNode("geo", "skinned_geo") # skinnedGeo.moveToGoodPosition() # Easier to work without it. Will uncomment in the end skinnedGeo.deleteItems(skinnedGeo.allSubChildren()) # Removes the file node boxNode = skinnedGeo.createNode("box") captureProximNode = skinnedGeo.createNode("captureproximity") captureProximNode.setFirstInput(boxNode) captureProximNode.moveToGoodPosition() captureProximNode.parm("rootpath").set(str(theBone.path())) deformNode = skinnedGeo.createNode("deform") deformNode.setFirstInput(captureProximNode) deformNode.moveToGoodPosition() #deformNode.setDisplayFlag(True) #deformNode.setRenderFlag(True) # Applying some color to the skinned box attribWrangle = skinnedGeo.createNode("attribwrangle", "color") attribWrangle.setFirstInput(deformNode) attribWrangle.parm("snippet").set("@Cd = {0,0,1};") attribWrangle.moveToGoodPosition() attribWrangle.setDisplayFlag(True) attribWrangle.setRenderFlag(True) # ''' # Transfers the animation from the specified geometry to the bone workingNode = hou.node("/obj/animated_box/OUT_script").geometry() # Gets the geometry of my test scenario for i in xrange(startFrame, endFrame+1): # For some reasons, xrange goes from the correct start value to the end value, minus 1. Strange. hou.setFrame(i) theFullTransform = workingNode.prims()[0].fullTransform() thePosition = workingNode.points()[0].attribValue("P") # This code works only for one object. Would do a loop here through all the pack geo. theRotation = extractEulerRotates(theFullTransform) # Got a problem with how this function extracts the rotation # Position key = hou.Keyframe(thePosition[0]) theBone.parm("tx").setKeyframe(key) testTransform.parm("tx").setKeyframe(key) key = hou.Keyframe(thePosition[1]) theBone.parm("ty").setKeyframe(key) testTransform.parm("ty").setKeyframe(key) key = hou.Keyframe(thePosition[2]) theBone.parm("tz").setKeyframe(key) testTransform.parm("tz").setKeyframe(key) # Rotation key = hou.Keyframe(theRotation[0]) theBone.parm("rx").setKeyframe(key) testTransform.parm("rx").setKeyframe(key) key = hou.Keyframe(theRotation[1]) theBone.parm("ry").setKeyframe(key) testTransform.parm("ry").setKeyframe(key) key = hou.Keyframe(theRotation[2]) theBone.parm("rz").setKeyframe(key) testTransform.parm("rz").setKeyframe(key) hou.setFrame(intialFrame) bakePackedAnim() # Would need to create a UI or a button for convenience, calling this out. And the scene : packed_anim_baker.hip Thanks ! EDIT : P.S. If I copy and paste relative reference from the source's rotation to the bone's rotation, the result is the same : obviously wrong rotation.
  4. Pop source

    Hi there ! Let's break it down a bit, and start just by emitting particles from frame 30 To do that, we can use a comparison with the current frame "Is the current frame above 30" So this is really simple ↓ @Frame >= 30 // The equal to make sure that it is true as soon as frame 30 is reached This will evaluate as 0 before frame 30, then 1 at the frame 30 and after. For emitting below frame 40, the logic is the same, with the comparison sign changing direction @Frame <= 40 But you want above frame 30 and below frame 40 There is an "and" for this, the double ampersand → && So those two separate expressions becomes @Frame >= 30 && @Frame <= 40 Hope that helps !
  5. Hey Atom ! Removing the Output sadly didn't work. But I did find a workaround ! If I put the Group node in a subnet, then it works ! It's in there, alone, and in the Type Properties I specify only the Subnets themselves as Editable Nodes. And when I do the selecting, Houdini automatically places a null between the input #1 and the group node So at least now it works, but if someone has an idea so that I don't need this hack, I'd appreciate it !
  6. Hey there ! I've got an issue where I have a group on my HDA (or multiple, doesn't matter) to do some stuff, but when I click the "select button" to start the selecting in the viewport, the display flag doesn't go on the group node. It stays where it was set when the HDA was saved. So in this example, the display flag is set on the Output node, and when selecting the prim or the point, we stay on the tube geo instead of going to the cube or the sphere I made sure to have all the nodes as "Editable" in the HDA, just in case. Here's a bare-bone setup showcasing the issue. The Group parameters on the HDA were created by drag-and-dropping each group nodes' parameter on the HDA, and I changed the Action Button Script a little bit to make it work. In this gif I tried with two version of the same HDA, one at the OBJ level, the other at the SOP level. Both have the same behavior. Looks like the display flag isn't able to be changed, since the HDA is locked. So when I unlock the HDA, then the selection stuff works correctly ! Until I lock it back up. I would assume that even when locked, the display flag would do that stuff with the render/display flags combo where upon clicking the "start selection" button, the render flag stays on the currently-displayed node, and the display flag moves (temporarily) onto the parent of the group node, until the selection is done. I swear that worked before.. I seem to remember that I had to specify the parent of the group node as an Editable Node in the HDA, and then the render/display flag combo worked... But I might be mistaken ..? Is there a workaround ? Did it really work before ? Thanks ! groupDisplayFlagHDA.hipnc test_groupSelect_obj.hdanc test_groupSelect_sop.hdanc
  7. Wrangle Cook Time

    Hello ! I noticed that the Last Cook info to know how long the node has cooked for is "wrong" for Wrangle Nodes. This can be seen easily when using the Performance Monitor to get the real data When we look at the values in the Performance Monitor itself, we can see that the Last Cook Time for a Wrangle Node is actually only the Output VEX Code step. This seems to ignore the whole attribvop step. This doesn't occur for other nodes, such as the blast or delete nodes. Is this an expected behavior regarding the Wrangle Nodes ? Attached is the test file, where I compare the speed of four methods to isolate the points I want. 1 - blast, cook time 0.189s 2 - delete, cook time 1.193s 3 - wrangle (pt), cook time 0.56ms ("real" is 1.632s) 4 - wrangle (detail), cook time 0.13ms ("real" is 4.189s) At first, I thought "hey, wrangles are sooo much faster than even the blast node, so why not use them always instead" But then, I noticed that the wait time I felt when cooking the node was a bit longer on the wrangle, despite the Cook Time telling me otherwise. This is what sparked this whole investigation wrangleCookTime.hipnc Thanks !
  8. Vellum wire not wrapping right

    Here's the most bare-bones setup for this vellumWireAroundTube.hipnc
  9. Vellum wire not wrapping right

    Hi Adam I don't know what you are missing, but I know for sure that we are missing a scene file to be of any help I can only guess that the scale of your scene is too large. I noticed that Vellum isn't very good on large scales (a few tens of meters), and your wire seems to be like 30 meters long Also, vellum likes to have a few substeps; the default of 1 is often not good enough. Try to put like 5 or 10, or even more (shouldn't have to go crazy with 50, something else is most likely the problem at this point) Hope that helps ! Otherwise, as I said, please post a scene file !
  10. Vellum semi rigid Helix type hose

    Hey Vinz ! Awesome ! Glad it works well One thing I would recommend is lowering the amount of points in the second resample.. I put it at 1200 points (which was your original amount), but that is a bit intense just for visual feedback. You can easily halve it with basically no visual impact, which resulted in 23-24fps playback on my side with 600 points. Even 300 points might be good enough. You might even be able to consider lowering the amount of points being simulated if you don't need that much precision. Although I do appreciate the offer, I decline. Also, the software I used for the gif is ScreenToGif It's pretty light and works well for my needs, and saving the gif using the Octree Encoder yields good result
  11. Vellum semi rigid Helix type hose

    Here's another (arguably too long) gif, just for funsies Adding an outer shell for the spring to collide against, and exaggerating the animation to force interpenetration of the spring with itself at the bottom to see how vellum handles that The answer - surprisingly well ! (with enough constraint and collision iteration) This is stable and not exploding in any way. Noice By the way, this simulated at 1.8fps, so it took 2m20s for the 240 frames at this quality.
  12. Vellum semi rigid Helix type hose

    Hi Vincent ! I think your issue is because you are trying to simulate the whole wire geometry Keeping it as a polyline will be both faster and work better for what you want Here's my take on it using your file (sorry for the absolute chonker of a gif, a few minutes long) I am aware this is not a sexy spring, but I guess it kinda works. I'm by no means a Vellum expert, but I hope that's at least a good start for you ! The key is to have enough Substeps. And if you want self-collisions, prepare for a slower feedback. I recommend setting it all up without collisions, and turning them on at the end when quality is required. Hope that helps ! Vellum_Helix.hipnc
  13. nearpoint() loop/exclude group.

    Hello Martin ! As you noticed, there is a ptgroup argument to the nearpoint function. If we read the description, this part is very interesting.. "[...] Can be a SOP-style group pattern such as 0-10 or @Cd.x>0.5. [...]" What that means is that you can do some nice inclusion/exclusion based on not only point groups per se, but even attributes on your geometry ! This odForce thread talks about this. So in your case, what you want is to find the nearest point that does not have the same id value as the current one. This might be a bit confusing, but this is the logic I went through while investigating this. So, keeping in mind that the ptgroup should be a string (check the doc), something like "@id != @id" should do it ?.. But this doesn't work. For what I understand is that since this is SOP-style statement, it works a bit different than in VEX, and doesn't have direct access to the attribute value of the current point. So instead of trying to get the current id value in the statement, we should get it "outside". Since this is a string, we can use the sprintf function to "insert" the id value into it. And thus, "sprintf("@id != %d", i@id)". I don't know if I'm making any sense, so here's a gif of my solution I run for a single point for example sake, coloring the source green and the found point red. Hope that helps ! nearpointWithGroup.hipnc
  14. Python du vex string manipulation

    Bonjour David, A quick Google Search gives this as the first result → find This gives the first occurrence instead of the last one. To find the last one, I would invert the string temporarily. Although it looks like you are trying to split a path to get the name of the file (or the last folder) There is the splitpath function that does just that. Hope that helps !
  15. evaluating display flag in OBJ level

    Hi avak ! I suggest you to look at the documentation page for the ObjNode If you search for "display" in the page, you'll see that indeed, "getDisplayFlag" doesn't exist Instead, it is called isDisplayFlagSet Hope that helps !
  16. Animating Vellum stopped attribute trouble

    Hi Tom ! The issue you are having is because the vellum geometry passed to the solver is actually frozen at the creation frame, and does not update the animated attributes. What you need is to have access to that animated geo So in your popwrangle, you can specify the input 2 to be your animated geometry (it can be anything from your maskfromgeometry to the vellumstructs), and then refer to that geo instead of the dop geometry Hope that helps ! vellum_falloff.hiplc
  17. Hi Mikel, I believe this question should be posted in the Scripting Forum But here's how I would do it Inside a Python Processor, from os import listdir path = r"C:\someFolder" allFiles = listdir(path) for file in allFiles: newItem = item_holder.addWorkItem() newItem.setStringAttrib("file", file) newItem.setStringAttrib("path", path + "\\" + file) Basically, using this documentation page, you can see how to add a work item This tells you that the resulting object is → pdg.WorkItem If you follow it to its documentation page, there you can see how to add an attribute to said work item
  18. Issue ?Solved

    Hi Librarian ! I'm guessing your issue is that the attribwrangle4 node doesn't output anything ? If that is so, then your issue is with the "|+" conditional operator I don't know what it is, but I assume you want to isolate the points that has the same value as the current loop of your foreach_end1 So replacing the |+ with != should work If the attribute pairID of the current point is not equal to the current loop iteration value, then remove it Hopefully that fixes your issue ! Otherwise, please elaborate
  19. Rotation Trouble

    Hey loudsubs ! So, I really am not an expert on matrix or quaternions, but I managed to come up with something that works for you, even though I can not explain it very well -.- That means that I cannot debug your setup itself, but I made a version using some VEX and a Solver The idea is to compute the rotation that a point would have at a given frame (based on its velocity and the sphere radius) using this float radius = chf("radius"); // Get distance traveled from previous frame vector prevPos = point(1, "P", @ptnum); float zeDist = distance(@P, prevPos); float rotation = zeDist / ((2*radius) * $PI); Then, we rotate a matrix using this rotation value using this float angle = radians(rotation*360); vector axis = normalize(v@dir); // Rotate the matrix (this is only one frame's worth of rotation) rotate(3@m, angle, axis); And finally, we accumulate the matrix m using the previous' frame matrix matrix3 prevMatrix = point(1, "m", @ptnum); 3@m = prevMatrix * 3@m; Notice how I specified "3@m = prevMatrix * 3@m;" instead of simply doing "3@m *= prevMatrix;" (which is the same as doing "3@m = 3@m* prevMatrix;") I think something like this was the issue with your setup, since when I used "3@m *= prevMatrix;", my setup behaved sort of like yours I believe this has to do with right/left multiplication order, affecting the local/global rotation or something I encourage you to try it out, using the Visualize node to see the animated angles resulting from it Note that this was all in a single wrangle running over Points, inside a Solver (input 0 is Current frame, input 1 is Prev_Frame) And then I rotated the matrix by 90 degrees in Y (unsure why, but note that we are outside the Solver at this point), and we're done Converting the matrix to orient and passing it into the copytopoints gives the right result Hopefully there is something that makes sense in all of that ! pathsolver04.hiplc
  20. [SOLVED] Compute angle between unshared edges

    Hi @Aizatulin, that works like a charm ! To be honest, I tried to figure out the logic of it, but I guess my intuition and understanding will develop as I use it in various situation. Right now, I'm having trouble wrapping my head around it, even if it's just a simple dot product -_-' @eimk, thanks for the alternative method ! I'll have to take a look at it later, and figure out that determinant thing Thanks to you both again, I appreciate it !
  21. Hi there ! The title might not be clear much, so let me try to explain. I'm trying to compute the angle of each points inside of a hole in a geometry. By searching a bit, I found float angle = degrees(acos(dot(normal_pt, nn_pt)));, which works, but there is an issue with my specific case. The blue angles are fine (simply by luck, coming from the shape of the hole), but the red ones are incorrect. Instead, I want to get the orange angle. That's pretty easy, I can do 360-angle. But the issue is when. How do I detect those issues, to be able to apply the fix ? Alternatively, I tried using the Measure SOP to compute this all for me, but I didn't find how to use it in this manner. But knowing Houdini, there probably is some node or VEX function that can compute this for me already =P Thanks ! getHoleAngles.hipnc
  22. PDG - Remove work item

    Welp, that sure wasn't helping =P My bad - but looks like they fixed the weirdness in .532, vs .348 Lemme explain - I'm testing this out on my work PC (that has 18.0.348 installed), but can't upload a file from it, so I recreated the same setup on my personal computer (with 18.0.532). I messed up writing that part, but here's the behavior attached I was having on my work PC And when redoing the setup on my personal one, I mis-typed this part, and assumed that the problem just got worse in .532, but no ! Without the typo, that weird behavior seen in the attached video is no more ! .. Or is it ? There is some more weirdness coming from the other branch. The discard_files_with_no_match1 shows the same behavior when set to Automatic. Set it to Dynamic, and now it works. Sorry for the multiple edits. Here's the video of it happening in the .532 version.
  23. Hello ! I'm trying to learn a bit of PDG since it might be useful for some of my projects. But I'm having a few issues For one, I wasn't able to find how to remove a work item. What I'm trying to do is search for a string in a bunch of files, and based on that I'll do some other things. Right now I'm simply trying to get to find the string in the files, but first I need the relevant files. So I use the filepattern node for that, but there is a few files for which I don't want. I use a pattern for the extension (*.txt), but there is some files with a specific string (in this case "proxy") in the filename that I would like to ignore. I tried something like "thePath\*.txt ^*proxy*" to get all the txt files without the ones with "proxy" in the name. Didn't work, maybe the syntax is wrong, but moving on. So I have a bunch of files (aka work item) that I want to get rid of. I tried using the split node, but I don't know how to work with PDG attributes. It always either error out, or gives me this I tried "@filename="file.txt" | @pdg_filename="file.txt" | I tried without the quotes, I tried with backticks around the filename part, without any success. What's the correct syntax for this ? I tried reading this, but without much results. I would need an example to understand it. So using expressions didn't work. I then moved on trying it out with Python. There is the "work_item.dirty(True, True)" command, which works as I want, I see the work item being removed in the node UI, but then Houdini freezes, then crashes. So I'm seemingly out of options. There is multiple questions, which are as follows : 1 - Is there a syntax for the file pattern that allows to get all .txt files, without the ones with a specific pattern in the name ? (mockup - "*.txt ^*proxy*") 2 - How to use PDG attributes in a node, as part of an expression ? Kinda like something simple like "@Frame=2", but in this fashion '@filename="file.txt" ' 3 - Why does the work_item.dirty() python command crashes Houdini ? Am I doing something wrong ? Test file attached. The zip contains some random .txt files with names to test out what I want, along with the hip file. pdg_test.zip
  24. PDG - Remove work item

    Hi James ! So you're basically using Python in the expression box. I totally didn't think about that, and yeah, that works ! Thank you for that insight, much appreciated Oh and I figured out the second question ! Turns out I was trying to match strings, which has to be through the "strmatch" function. I was doing an "==" comparison, which doesn't work for strings. So strmatch("*proxy*", @filename) for string comparison and @intAttr=4 for int/float attributes works fine. There are some weirdness from attributes created within a Python Script node (has to set the subsequent nodes trying to access the attribute to Dynamic, else it's as if the attribute doesn't exist, and other disparities), so that's something to keep in mind (see attached hip file). pdg_test.zip
  25. PDG - Remove work item

    I wasn't able to answer any of my questions yet, but I found a workaround. This doesn't mean that I don't need an answer to the previous questions, so feel free to reply My workaround for getting rid of those pesky work_item that contains the dreaded "proxy" keyword is using the Python Processor node. I noticed that placing this bad boi in a chain blocks all traffic from coming through, and that I would need to police each of the work_items to decide which one I let through. And this is exactly what I want to do ! So the concept is really simple, for each of the upstream work item, check if "proxy" is NOT in the filename. In that case, yeah ! Let 'im through ! for item in upstream_items: if "proxy" not in item.attribValue("filename"): newItem = item_holder.addWorkItem(parent=item) # parent copies the original work_item's attributes So instead of deleting the ones I want to remove, I'm actually regenerating the whole graph, copying only the ones I want. I feel like this is really not optimal, so using an actual node made for that purpose (like split) would surely be a lot better. Attached is the updated hip file, along with a quick mockup of that "find string in files" idea I mentioned. pdg_test.zip