infinity_spiral Posted July 4, 2012 Share Posted July 4, 2012 (edited) Is it possible to create bones from multiple curve primitives? I am creating multiple curves with the add sop than when I run "bones from curve" button on the shelf it creates bones only for the last curve primitive.I tried to look for the python script for this command so I can modify it but couldn't find it. Anyone have an idea how I can automate creation of the bones on multiple curves? And one more question: Is it possible to paint the wire capture per curve primitive if I have multiple curves?The default setup it doesn't give me a way to paint but I think this should be possible trough paint node and attribute create.The problem is that I can't get it to work.Any ideas how I can do that? Edited July 4, 2012 by T.I.M. Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 5, 2012 Author Share Posted July 5, 2012 So I tried to write a shelf tool that fetch each curve primitive to separate obj,since the "bones from curve" doesn't work in SOP level. And than my idea was to loop trough each Geo and run the command "bones to curve" .But the looping just doesn't work.I thought that this is maybe related to the fact that you have to exit from currentState for the tool but I am not sure if I am doing it right since there is no documentation on this. Am I doing something wrong or this is just not possible?Maybe I have to write my own Bones to curves function...?I think this is very basic thing and SESI should make the default tool to work on multiple curve primitives. Hope someone can help me with that. You have to select the multiple curves in sop level before run it: import hou import objecttoolutils import toolutils def timBonesfromCurves(): sel = hou.selectedNodes()[0] obj = hou.node("obj") geo = sel.geometry() prim = geo.prims() for j,i in enumerate(prim): p = obj.createNode("geo","curveFetch") p.setPosition((0,-j)) p.node("file1").destroy() f = p.createNode("object_merge") f.parm("objpath1").set(sel.path()) d = f.createOutputNode("delete") d.setRenderFlag(1) d.setDisplayFlag(1) d.parm("negate").set(1) d.parm("pattern").set(str(j)) p.setSelected(1) #This part just doesn't work in this loop: objecttoolutils.customStateTool(kwargs, 'bonesfromcurve') #pane.enterViewState() timBonesfromCurves() Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 8, 2012 Author Share Posted July 8, 2012 Anyone? Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted July 8, 2012 Share Posted July 8, 2012 Why you create object merge ? you got selected nodes so why not just loop thru them ? Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted July 8, 2012 Share Posted July 8, 2012 (edited) With this: import hou import toolutils def UserInput(): sv = toolutils.sceneViewer() curves = sv.selectObjects('Select curves, press enter to accept', allowed_types=('geo', )) if curves == (): hou.ui.displayMessage('Curves not selected, terminating tool', severity=hou.severityType.Error) return None return curves def BonesfromCurves_Tool(kwargs): curves = UserInput() if curves == None: return for curve in curves: print(curve) curve.setSelected(1) toolutils.genericStateTool(kwargs, 'bonesfromcurve') if you select couple geo nodes that contains curve, for example 2, it will create "bonesfromcurve" only for last one in the list/loop. It print both curves, so it looks that last loop operation is translated as 'enter confirmation'. I don't know is there a way to "simulate enter" for genericStateTool() somehow. Edited July 8, 2012 by mantragora Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 8, 2012 Author Share Posted July 8, 2012 (edited) Why you create object merge ? you got selected nodes so why not just loop thru them ? I hope | understand your question. What I am doing actually in my case is that I am extracting curves from geometry by using add sop witch generates multiple curve primitives.I'm not using merge node. Than I need to create bone chain for each curve primitive.So I got the script to the point that creates multiple geo nodes for each curve primitive the problem is that the "bones from curve" command doesn't work in the loop.So my question is how I can automate the creation of "bones from curve" for each curve primitive because right now this command doesn't work in the loop.I have a lot curve primitives and will be crazy to go and apply the command one by one. I saw in the SESI forum that someone asked how we can paint the wire capture. http://www.sidefx.com/index.php?option=com_forum&Itemid=172&page=viewtopic&t=25826&highlight=wire+capture If there is some simple way to do that this will be great and the creation of bones will be unnecessary in my case. I just couldn't get this to work well for multiple curves.It kind of works for one curve but if you have many curves close to each other it fails. If someone can post some example on this will be really great. Edit:Obviously I misunderstood your question.Sorry sometimes my English sucks I am creating object merge because "Bones From curve" works in object level.And than I want each bone chain to follow each curve witch can't happen if I don't have them in separate object. Edited July 8, 2012 by T.I.M. Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 8, 2012 Author Share Posted July 8, 2012 With this: import hou import toolutils def UserInput(): sv = toolutils.sceneViewer() curves = sv.selectObjects('Select curves, press enter to accept', allowed_types=('geo', )) if curves == (): hou.ui.displayMessage('Curves not selected, terminating tool', severity=hou.severityType.Error) return None return curves def BonesfromCurves_Tool(kwargs): curves = UserInput() if curves == None: return for curve in curves: print(curve) curve.setSelected(1) toolutils.genericStateTool(kwargs, 'bonesfromcurve') if you select couple geo nodes that contains curve, for example 2, it will create curve only for last one in the list/loop. It print both curves, so it looks that last loop operation is translated as 'enter confirmation'. I don't know is there a way to "simulate enter" for genericStateTool() somehow. Thanks for your time! I will take a look now. Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 8, 2012 Author Share Posted July 8, 2012 (edited) if you select couple geo nodes that contains curve, for example 2, it will create curve only for last one in the list/loop. It print both curves, so it looks that last loop operation is translated as 'enter confirmation'. I don't know is there a way to "simulate enter" for genericStateTool() somehow. Yea that is the problem I faced .And I used this command in the end of the loop to simulate the 'enter' : import hou import toolutils as t pane = t.activePane(kwargs) pane.enterViewState() But I am not sure if it's right way because it still doesn't work in the loop. Edited July 8, 2012 by T.I.M. Quote Link to comment Share on other sites More sharing options...
infinity_spiral Posted July 11, 2012 Author Share Posted July 11, 2012 I feel bad that this thing left unsolved.Is there any other ideas on this matter or I have to dive deeper and write my own function for creation of the bones....(if i find enough documentation on that)?I just don't want to leave this unsolved.... I manged to do what I need it but in the hard way. Hope someone can help. Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted July 11, 2012 Share Posted July 11, 2012 (edited) well, if you put your code pane = t.activePane(kwargs) pane.enterViewState() at the end of main version you will see that it will not execute properly, so definitely this is not the way to simulate "enter". I supose there should be a way to simulate it. We need Graham's power for this ! CaptainHammy to the rescue ! He is one with python in Houdini Edited July 11, 2012 by mantragora Quote Link to comment Share on other sites More sharing options...
90ender Posted January 5, 2015 Share Posted January 5, 2015 (edited) So this is probably too late for the OP, but here a solution I slapped together that doesn't require calling the "bones from curve" tool. Hope it helps someone. #Bones From Multiple Curves Tool - By 90ender ''' Given a node containing more than one curve, the tool loops over each creating a bone chain that matches it's curvature and position. The tool is still in development and currently does not take user input. ''' #create a normal given two points def normalFromPoints(pfrom = hou.Vector3(3,2,1), pto = hou.Vector3(10,5,2)): x = pto[0] - pfrom[0] y = pto[1] - pfrom[1] z = pto[2] - pfrom[2] return hou.Vector3(x,y,z) # convert a normal to a euler rotation def normalToEuler(nto = hou.Vector3(1,1,0), nfrom = hou.Vector3(0,1,0)): a = nto.normalized() b = nfrom.normalized() matrix = b.matrixToRotateTo(a) euler = matrix.extractRotates('srt','xyz',hou.Vector3(0,0,0)) return euler def buildBone(parent = None, pos = hou.Vector3(0,0,0), rot = hou.Vector3(0,0,0), len = 1.0, name = "chain_bone1", container = None): if container == None: container = hou.node("obj") bone = container.createNode("bone", name) bone.parm("length").set(len) bone.parmTuple("t").set(pos) rot[2] = 0.0 bone.parmTuple("r").set(rot) if parent != None: bone.parm("keeppos").set(1) bone.setFirstInput(parent) bone.parm("keeppos").set(0) bone.moveParmTransformIntoPreTransform() return bone def buildRoot(name = "chain_root", container = None, parent = None): if container == None: container = hou.node("obj") root = container.createNode("null", name) root.parm("keeppos").set(1) root.parm("use_dcolor").set(0) root.parm("geoscale").set(0.5) root.parm("controltype").set(1) root.parm("shadedmode").set(1) if parent != None: root.setFirstInput(parent) return root #build chain of n bones along curve #POSSIBLE TO DO: if curve has length attrib then add bones based on length. def bonesFromCurve(curve = None, segments = 5, container = None): #initialize curve position and variables div = 1.0 / segments u = 0 v = 0 apos = curve.positionAtInterior(u,v) boneDir = hou.Vector3(0,0,-1) #get names rootName = "root1" boneName = "curve_bone1" if curve.geometry().findPrimAttrib("name") != None: name = curve.stringAttribValue("name") rootName = name + "_root1" boneName = name + "_bone1" #build root root = buildRoot(rootName, container) chainpos = root.moveToGoodPosition() parent = root bonesLst = [root] for x in range(0, segments): #get bone start and end positions on curve u += div bpos = curve.positionAtInterior(u,v) len = apos.distanceTo(bpos) #Calculate bone rotation along curve from up vector n = normalFromPoints(apos, bpos) rot = normalToEuler(n, boneDir) #create bones here and orient and parent them bone = buildBone(parent, apos, rot, len, boneName, container) bone.moveToGoodPosition() parent = bone bonesLst.append(bone) #set next position apos = bpos #need to return a bone or list of bones return bonesLst #TO DO: Find out how to put parameters into operation controls toolbar #main() selected = hou.selectedNodes() if len(selected) < 1: hou.ui.displayMessage("No Nodes Selected") else: #get curves from node child = selected[0].displayNode() curves = child.geometry().prims() #TO DO: check if geo is curve #TO DO: User input here. Check if zero input = 10 #create subnet container subnet = hou.node("obj").createNode("subnet", "tree_rig1") subnet.moveToGoodPosition() geoInSubnet = [] #iterate over curves for i in curves: bonesLst = bonesFromCurve(i, input, subnet) #we may need another parm for chain parents print "done!\n" Edited January 5, 2015 by 90ender 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.