Showing posts with label houville. Show all posts
Showing posts with label houville. Show all posts

Sunday, March 3, 2024

Polygon tidy up after mirroring in Houdini

Here's some help with simple things that are all too easy to forget if you don't work in Houdini for a while while. Courtesy of a talent Houdini artist Mohan Pugaz.

Tuesday, March 29, 2022

Houville :: Execute code on a node

Per Mestela.

exec(kwargs['node'].parm('Code').eval())

Houville :: VEX circular points

Just a quick one

Saturday, July 14, 2018

Houville :: Alembic transform theft

Now that I'm typing this I'll probably not forget it. If I don't post this, I'll definitely forget it.
//Alembic packed info put onto existing geo.
matrix abc = primintrinsic(1,'packedfulltransform',0);
P *= abc;


This is kind of messed up, but handy if you want to freeze geo, affect it, but then have it resume animation from an incoming abc transform animation. Input 1 is the frozen and tweaked geo, 2 is the animated abc and 3 is the abc frozen on the same frame as 1.
//Alembic packed info from static frame subtracted out, then a the animated one put back in/
matrix abc = primintrinsic(1,'packedfulltransform',0);
matrix abcRef = primintrinsic(2,'packedfulltransform',0);

P *= invert(abcRef) * abc;

Friday, June 29, 2018

Houville :: Looping RBD Sims



So the concept here was run a sim, reverse it and blend the two together so that the beginning and the end are the same.

Pretty logical right?

Well as you can see from the top gif, when the blend back occurred, chunks would squish through themselves to resolve the different orientations.

After a bit of messing around I realised rather than deal with the chunks, just keep the point data from the sim and use a for-each loop to copy each chunk back onto the corresponding point afterwards.  This resolved the squish but then there was a pop as the orientation attribute was not blended by the blendShape SOP.

The way around that was to use a wrangle that blended @P with a lerp, and then did exactly the same with the @orient attribute.

Plugging that in to the for-each copy chunks loop made everything work as expected :)

Sunday, April 15, 2018

Houville :: Get selections from Scene Views

This is one of those obvious needs that ends up being a frustrating "how do you even..?"

In Houdini 16.5 and up it's pretty simple:
import toolutils
sv = toolutils.sceneView()
str(hou.SceneViewer.currentGeometrySelection(sv))


However in 16.0 it's a bit more fiddly as currentGeometrySelection doesnt exist. hicon:/SVGIcons.index?book.svg
import toolutils
selection = toolutils.sceneViewer().selectGeometry() ## this annoyingly unselects your selection
print selection
## lets also get this in the clipboard so we can past it in a node.
Here's a good reference: https://www.sidefx.com/forum/topic/30353/
As is this in the docs: http://www.sidefx.com/docs/houdini/hom/tool_script.html

Saturday, November 18, 2017

Houville :: iterating in VEX

Urgh, I keep forgetting this. So to iterate in VEX:
//fix negative colours per channel
for ( int i = 0; i < int (3); i++)
{
    if (@Cd[i] < 0) { @Cd[i] *= -1;}
}

Thursday, October 26, 2017

Houville :: customising node attributes

Create a text file called "OPcustomize" in your houdini16.0 (or corresponding) folder. Here you can describe the new defaults you want to use with your nodes. For colours
opdefaultcolor Sop null 'RGB 0.0 0.0 0.0';
opdefaultcolor Sop dopnet 'RGB 0.5 0.0 0.0';
opdefaultcolor Sop dopimport 'RGB 0.5 0.0 0.0';
opdefaultcolor Sop object_merge 'RGB 0.475 0.812 0.204';
Thanks to Amber for this one.

Going beyond this:

We can grab the type from a python shell with drag-drop then append ".type()". And we can also work with default and user-defined shapes, and grab the colour info.
# good if you manually selected a new shape.
n.userData("nodeshape");

# good for finding the session default shape for the node
n.type().defaultShape();

# for getting the colour that has been user assigned
n.color()


Example:
opdefaultcolor Driver null 'RGB 0.478 0.478 0.478';
opdefaultshape Driver null 'circle';
opdefaultcolor Driver merge 'RGB 0.65 0.65 0.65';
opdefaultshape Driver merge 'circle';
opdefaultcolor Driver geometry 'RGB 0.145 0.667 0.557';
opdefaultshape Driver geometry 'tabbed_left';

opdefaultcolor Driver gridmarkets::render_submit::1.5.2 'RGB 0.45 0.12 0.6';
opdefaultcolor Driver gridmarkets::nuke::1.19 'RGB 0.976 0.78 0.263';

opdefaultcolor Driver gridmarkets::transcode::1.8 'RGB 0.25 0.5 1';
opdefaultshape Driver gridmarkets::transcode::1.8 'wave';
opdefaultcolor Driver ifd 'RGB 1 .976 0.666';

opdefaultcolor Sop null 'RGB 0.0 0.0 0.0';
opdefaultcolor Sop dopnet 'RGB 1 0 0';
opdefaultcolor Sop gridmarkets::cloud_cache::1 'RGB 0.145 0.667 0.557';
opdefaultshape Sop gridmarkets::cloud_cache::1 'tabbed_left';
opdefaultcolor Sop file 'RGB 0.616 0.871 0.769';

Thursday, September 7, 2017

Houville :: how to not go insane with Nuke vs Houdini hotkeys

Display shortcuts: I have these set as F9-F12
import os,glob
def visualise(flag):
    if flag ==1: hou.selectedNodes()[0].setDisplayFlag(1)
    if flag ==2: hou.selectedNodes()[0].setRenderFlag(1)
    if flag ==3:
        if len(hou.selectedNodes())>0:
            state = 1-hou.selectedNodes()[0].isTemplateFlagSet()
            for i in hou.node(os.path.dirname(hou.selectedNodes()[0].path())).glob('*'): i.setTemplateFlag(0)
            for i in hou.selectedNodes():
                i.setTemplateFlag(state)
    if flag ==4:
        state = 1-hou.selectedNodes()[0].isBypassed()
        for i in hou.selectedNodes():
            i.bypass(state)

visualise(4)


This is straight out of Nukeland for snapping your nodes to the grid intersections. I have it set as Shift+\

And finally the most common one I need to not yell at the everlasting cookfests. I have it set to Alt+Shift+U, which is a bit Vulcan MindMeldy but it works. I also set Alt+U to "/Houdini/Force Update"
import hou
mode = hou.updateModeSetting().name()
if mode == 'AutoUpdate':
    hou.setUpdateMode(hou.updateMode.Manual)
if mode == 'Manual':
    hou.setUpdateMode(hou.updateMode.OnMouseUp)
if mode == 'OnMouseUp':
    hou.setUpdateMode(hou.updateMode.AutoUpdate)

Saturday, April 1, 2017

Houville :: nice up vectors

This is for arranging your geo for nice behaviour with the copy sop. If you want to distibute geo, like trees or whatever, and control orientation but still respect the angle to the surface this is for you.


You'll need some way to connect the target points with the surface prim they relate to. Scatter has the sourceprim option which is cool, but if you want to manually do it you'll need a pre-pass. Here's an example using the 'stick a point in the middle of the face' technique. This should run over prims.
int newPtNum = addpoint(0,@P);
addpointattrib(0,"sourceprim", 0);
setpointattrib(0,"sourceprim", newPtNum, @primnum, 'set');
removeprim(0,@primnum,1);


Now lets get the surface geo ready. Here we will sneakily say normals run along the U direction and Up is what would typically be considered a normal. This makes sure our orientation makes sense.

Run this over points, assuming point source is in OpInput1, and reference geo for orientation is OpInput2.
vector center = primuv(s@OpInput2, 'P', i@sourceprim, {0.5,0.5,0.0});
vector dPdu = primuv(s@OpInput2, 'P', i@sourceprim, {0.51,0.5,0.0});
vector dPdv = primuv(s@OpInput2, 'P', i@sourceprim, {0.5,0.51,0.0});

vector u = normalize(dPdu - center);
vector v = normalize(dPdv - center);

v@up = normalize(cross(u,v));
v@N = u;

//matrix rotation shiz!
vector rot[];
rot[0] = u;
rot[1] = v@up;
rot[2] = v;
matrix3 mtx[] = unserialize(serialize(rot));
rotate(mtx[0], radians(chf('heading')), v@up);
rot = unserialize(serialize(mtx));
v@N = rot[0];
v@up = rot[1];



** for another post - passing colour information through points to be picked up by "Point Instance Procedural" as material overrides:
string r = sprintf("%d", @Cd.x);
string g = sprintf("%d", @Cd.y);
string b = sprintf("%d", @Cd.z);


s@shop_materialpath = chs('../theInstancesShaderPath');
s@material_override = "{'basecolorr':" + r + ",'basecolorg':" + g + ",'basecolorb':" + b + ",}";



Soooooo.. some of that was overkill. Here are a few ways to optimise that.

You can for example dispense with the serialise/unserialise phase by seting to the matrix directly. Also you can use quarternion to directly pull rotation information out of the matrix. Bear in mind Houdini understands '@orient' as a vector4 aka p@orient.
## direct casting and assignment of a matrix, rotation, extraction as a quaternion.
matrix3 rot = set(u,v@up,v)
rotate(rot, radians(chf('heading')), v@up);
p@orient = quaternion(rot)


And finally, you don't have to derive a @up if you have a normal. Have the points (scattered or otherwise) pick up their normals from the source they are based on. addpointattrib(0,"N",{0,0,0}); setpointattrib(0,"N",newPtNum,@N,"set");

Friday, March 10, 2017

Houville :: rop presets

nodePath = ropnet.createNode('ifd',node_name).path()
hscript = "oppresetloadfile %s %s" % (nodePath, "niceRopLayout.preset")
hou.hscript(hscript)

Sunday, February 19, 2017

Houville :: adding params to a obj

Another one I keep forgetting... Here's how to add params to a node in houdini.
n = hou.node('/obj/geo1')
n.addSpareParmTuple(hou.IntParmTemplate('intParm','',1, default_value=(10,),min = 0, max = 20))
n.addSpareParmTuple(hou.FloatParmTemplate('floatParm','',1, default_value=(10,),min = 0, max = 20))


#define some multi line code.  Like a python script
code = """print 'some stuff'
print 'more stuffs'
print 'an\\\\' ting'"""

# is hidden is good for hiding code away
n.addSpareParmTuple(hou.StringParmTemplate('stringParm','',1,default_value=(code,), is_hidden=0))
n.addSpareParmTuple(hou.ButtonParmTemplate('Button','', join_with_next=0, script_callback='exec(hou.parm("stringParm").evalAsString())', script_callback_language=hou.scriptLanguage.Python))

And when you want to delete some parms, remember to get rid of the tuple.  You can access that easily like this:
n.removeSpareParmTuple(n.parm('stringParm').tuple())

And finally, if you don't want to add params one by one you can make a Parameter Template Group to then add as a lump later.
ptg = n.parmTemplateGroup()
ptg.append(hou.IntParmTemplate('intParm','',1, default_value=(10,),min = 0, max = 20))
n.setParmTemplateGroup(ptg)

Not quite sure yet why this is better, but I'll probably find out one day.