Search - User list
Full Version: Post your favourite Wrangle SOP presets
Root » Houdini Lounge » Post your favourite Wrangle SOP presets
jacob clark
Not to rain on anyone's parade, but have you seen the new Attribrandomize SOP?

It's got just about every randomize preset you could want, and even works w/ Quaternions!
jacob clark
And just to remain on topic, here's a quick Point Cloud method to find if a point is inside, or below a surface based on normals.



f@radius = 100000;
i@maxPoints = 10;
i@handle = pcopen(@OpInput2, “P”, @P, @radius,@maxPoints);
@N = pcfilter(@handle,“N”);
v@groundP = pcfilter(@handle,“P”);
v@up = normalize(@P - @groundP);
@Cd = dot(@up,@N);
animatrix_
Jitter with Scale Attribute and Exponent



#include "math.h"
#define PI M_PI

int pt = @ptnum;
if ( chi("id") )
    pt = i@pt;
    
float s = 1;
if ( chi("scale") )
    s = @scaleAttribute;

int maxsafeint = 100000;
float val = pt % maxsafeint + PI * ( pt / maxsafeint ) + ch("seed") * 0.618033988749895;
float x = rand ( val );
float y = rand ( 1231 + val );
float z = rand ( 773 + val );

vector v = ( set ( x, y, z ) - 0.5 ) * chv("s") * ch("amount") * pow ( s, ch("exponent") );
@P += v;
animatrix_
Select Border Points by Primitive Attribute

int pointPrimsHaveDifferentAttribValues ( string input; int pt; string attribute )
{
    int currentValue = 0;
    int initialized = 0;
    int result = 0;
    int pv = pointvertex ( input, pt );
    while ( pv != -1 )
    {
        int vp = vertexprim ( input, pv );
        int value = prim ( input, attribute, vp );
        
        if ( initialized == 0 )
        {
            currentValue = value;
            initialized = 1;
        }
        
        if ( value != currentValue )
        {
            result = 1;
            break;
        }
        
        pv = vertexnext ( input, pv );
    }
    return result;
}

i@borderpts = pointPrimsHaveDifferentAttribValues ( @OpInput1, @ptnum, chs("attribute") );
tjeeds
Convert sphere primitive intrinsic transform to pscale:


matrix3 m3 = primintrinsic(@OpInput1, “transform”, @primnum);
vector extracted = cracktransform(0, 0, 2, { 0, 0, 0 }, m3);
@pscale = max(extracted,max(extracted,extracted));
animatrix_
Gnomon

int createLine ( int pt0; int pt1 )
{
    int pr = addprim ( geoself ( ), "polyline" );
    addvertex ( geoself ( ), pr, pt0 );
    addvertex ( geoself ( ), pr, pt1 );
    return pr;
}

int createPolygon ( int pt0; int pt1; int pt2 )
{
    int pr = addprim ( geoself ( ), "poly" );
    addvertex ( geoself ( ), pr, pt0 );
    addvertex ( geoself ( ), pr, pt1 );
    addvertex ( geoself ( ), pr, pt2 );
    return pr;
}

int createPolygon ( int pt0; int pt1; int pt2; int pt3 )
{
    int pr = addprim ( geoself ( ), "poly" );
    addvertex ( geoself ( ), pr, pt0 );
    addvertex ( geoself ( ), pr, pt1 );
    addvertex ( geoself ( ), pr, pt2 );
    addvertex ( geoself ( ), pr, pt3 );
    return pr;
}

void createAxisGeometry ( float s; vector n; vector t; vector c; int color; int arrow; int scale )
{   
    vector p [ ];
    push ( p, 0 );
    push ( p, set ( s, 0, 0 ) );
    
    if ( arrow )
    {
        float x = scale ? 0.75 * s : s - 0.25;
        float y = 0.03 * ( scale ? s : 1 );
        push ( p, set ( x, y, y ) );
        push ( p, set ( x, y, -y ) );
        push ( p, set ( x, -y, y ) );
        push ( p, set ( x, -y, -y ) );
    }
    
    for ( int i = 0; i < len ( p ); ++i )
    {
        matrix3 xform = dihedral ( { 1, 0, 0 }, { 0, 0, -1 } ) * lookat ( 0, n );
        p [ i ] = p [ i ] * xform + t;
    }
    
    int pt [ ];
    for ( int i = 0; i < len ( p ); ++i )
        pt [ i ] = addpoint ( geoself ( ), p [ i ] );
    
    if ( color )
    {
        for ( int i = 0; i < len ( pt ); ++i )
            setattrib ( geoself ( ), "point", "Cd", pt [ i ], -1, c, "set" );
    }

    createLine ( pt [ 0 ], pt [ 1 ] );
    if ( arrow )
    {
        createPolygon ( pt [ 1 ], pt [ 2 ], pt [ 3 ] );
        createPolygon ( pt [ 1 ], pt [ 3 ], pt [ 5 ] );
        createPolygon ( pt [ 1 ], pt [ 5 ], pt [ 4 ] );
        createPolygon ( pt [ 1 ], pt [ 4 ], pt [ 2 ] );
        createPolygon ( pt [ 2 ], pt [ 4 ], pt [ 5 ], pt [ 3 ] );
    }
}

void createCenterGeometry ( float s; vector t; vector c; int color; int scale )
{
    vector p [ ];
    float x = 0.03 * ( scale ? s : 1 );
    push ( p, set ( x, x, x ) );
    push ( p, set ( x, x, -x ) );
    push ( p, set ( x, -x, -x ) );
    push ( p, set ( x, -x, x ) );
    push ( p, set ( -x, x, x ) );
    push ( p, set ( -x, x, -x ) );
    push ( p, set ( -x, -x, -x ) );
    push ( p, set ( -x, -x, x ) );
    
    for ( int i = 0; i < len ( p ); ++i )
        p [ i ] += t;
    
    int pt [ ];
    for ( int i = 0; i < len ( p ); ++i )
        pt [ i ] = addpoint ( geoself ( ), p [ i ] );
    
    createPolygon ( pt [ 0 ], pt [ 1 ], pt [ 2 ], pt [ 3 ] );
    createPolygon ( pt [ 1 ], pt [ 5 ], pt [ 6 ], pt [ 2 ] );
    createPolygon ( pt [ 5 ], pt [ 4 ], pt [ 7 ], pt [ 6 ] );
    createPolygon ( pt [ 4 ], pt [ 0 ], pt [ 3 ], pt [ 7 ] );
    createPolygon ( pt [ 5 ], pt [ 1 ], pt [ 0 ], pt [ 4 ] );
    createPolygon ( pt [ 7 ], pt [ 3 ], pt [ 2 ], pt [ 6 ] );
    
    if ( color )
    {
        for ( int i = 0; i < len ( pt ); ++i )
            setattrib ( geoself ( ), "point", "Cd", pt [ i ], -1, c, "set" );
    }
}

addattrib ( geoself ( ), "point", "Cd", { 1, 1, 1 } );

if ( chi("x") )
    createAxisGeometry ( ch("s"), { 1, 0, 0 }, chv("t"), { 1, 0, 0 }, 1, chi("arrow"), chi("scale") );
if ( chi("y") )
    createAxisGeometry ( ch("s"), { 0, 1, 0 }, chv("t"), { 0, 1, 0 }, 1, chi("arrow"), chi("scale") );
if ( chi("z") )
    createAxisGeometry ( ch("s"), { 0, 0, 1 }, chv("t"), { 0, 0, 1 }, 1, chi("arrow"), chi("scale") );
if ( chi("center") )
    createCenterGeometry ( ch("s"), chv("t"), { 1, 1, 0 }, 1, chi("scale") );
    
i@gl_lit = 0;
animatrix_
Select Edge Loop

Run Over = Detail

int Contains ( string collection [ ]; string item )
{
    for ( int i = 0; i < arraylength ( collection ); ++i )
        if ( collection [ i ] == item )
            return 1;
    return 0;
}


int Contains ( int collection [ ]; int item )
{
    for ( int i = 0; i < arraylength ( collection ); ++i )
        if ( collection [ i ] == item )
            return 1;
    return 0;
}

string GetPrimsFromEdge ( int input; int pt0; int pt1 )
{
    string prims;
    int hedge = pointedge ( input, pt0, pt1 );
    if ( hedge != -1 )
    {
        int count = hedge_equivcount ( input, hedge );
        for ( int i = 0; i < count; ++i )
        {
            int pr = hedge_prim ( input, hedge );
            if ( pr != -1 )
            {
                prims += itoa ( pr ) + "-";
                hedge = hedge_nextequiv ( input, hedge );
            }
        }
    }
    return prims;
}


int GetNextPoint ( int input; int edgept0; int edgept1; int currentpt )
{
    int pointNeighbors [ ] = neighbours ( input, currentpt );
    
    string sprims = GetPrimsFromEdge ( input, edgept0, edgept1 );
    string aprims [ ] = split ( sprims, "-" );
    int prims [ ];
    foreach ( string s; aprims )
        push ( prims, atoi ( s ) );

    int primPoints [ ];
    for ( int i = 0; i < arraylength ( prims ); ++i )
    {
        int count = primvertexcount ( input, prims [ i ] );
        for ( int f = 0; f < count; ++f )
        {
            int vertIndex = vertexindex ( input, prims [ i ], f );
            int pointIndex = vertexpoint ( input, vertIndex );
            push ( primPoints, pointIndex );
        }
    }

    int uniquePoints [ ];
    for ( int i = 0; i < arraylength ( pointNeighbors ); ++i )
    {
        if ( !Contains ( primPoints, pointNeighbors [ i ] ) )
            push ( uniquePoints, pointNeighbors [ i ] );
    }
    
    if ( arraylength ( uniquePoints ) == 1 )
        return uniquePoints [ 0 ];

    return -1;
}


//  Traverse Edges

string BuildEdgeList ( int input; string edgeCollection )
{
    if ( edgeCollection == "" )
        return "!*";
    
    string edges [ ];
    string sedges [ ] = split ( edgeCollection, " " );
    
    int traverseCount = 0;
    int totalCount = arraylength ( sedges );
    
    while ( arraylength ( sedges ) > 0 )
    {
        string sedge;
        pop ( sedge, sedges );
        string edgePoints [ ] = split ( sedge, "-" );
        
        if ( !Contains ( edges, sedge ) )
        {
            ++traverseCount;
            for ( int c = 0; c < 2; ++c )
            {
                int points [ ];
                int pt0 = atoi ( edgePoints [ c ] );
                int pt1 = atoi ( edgePoints [ 1 - c ] );
                int currentpt = pt0;
                int lastPoint = pt0;
                push ( points, currentpt );
                int nextPoint = GetNextPoint ( input, pt0, pt1, currentpt );
                //printf( "nextpt: %s\n", nextPoint );
                while ( nextPoint != -1 && nextPoint != lastPoint )
                {
                    pt0 = currentpt;
                    pt1 = nextPoint;
                    currentpt = pt1;
                    push ( points, currentpt );
                    nextPoint = GetNextPoint ( input, pt0, pt1, currentpt );
                    //printf( "nextpt: %s\n", nextPoint );
                }
                
                for ( int i = 0; i < arraylength ( points ) - 1; ++i )
                {
                    int p0 = min ( points [ i ], points [ i + 1 ] );
                    int p1 = max ( points [ i ], points [ i + 1 ] );
                    push ( edges, sprintf ( "%s-%s", p0, p1 ) );
                    //printf( "edge: %s\n", sprintf ( "%s-%s", p0, p1 ) );
                }
                //printf( "points: %s\n", points );
            }
            push ( edges, sedge );
        }
        //else
            //printf( "BYPASS: %s\n", sedge );
    }
    
    string edgelist = "";
    foreach ( string s; edges )
        edgelist += "p" + s + " ";
    
    //printf( "Traversed: %s edges out of %s edges\n", traverseCount, totalCount );
    return edgelist;
}

s@edgelist = BuildEdgeList ( 0, chs("edges") );[/code:1]

Add a string parameter called edges and add this Python expression:

[code:1]edges = ""
geo = hou.node ( "." ).geometry ( )
names = hou.evalParm ( "group" ).split ( ' ' )

for name in names:
    try:
        group = geo.globEdges ( name )
    except hou.OperationFailed:
        group = ( )
    
    for e in group:
        p0 = e.points ( ) [ 0 ]
        p1 = e.points ( ) [ 1 ]
        
        try:
            isValidEdge = geo.findEdge ( p0, p1 )
        except:
            isValidEdge = False
        
        if not isValidEdge:
            continue
        
        a = str ( min ( p0.number ( ), p1.number ( ) ) )
        b = str ( max ( p0.number ( ), p1.number ( ) ) )
        edges += "{0}-{1} ".format ( a, b )

return edges[:-1]



Unfortunately working with edges is really hard in VEX. If we had the ability to highlight elements as well as be able to work with edges, it would really help with these kinds of tools. For example we have expandpointgroup, expandprimgroup, but not expandedgegroup, which could return edge points sequentially.
Alexey Vanzhula
insert edges with flow please
animatrix_
vux
insert edges with flow please

That will take quite some work
animatrix_
Color Random with the ability to use attributes (int/float/string) for seed in addition to global seed

Special thanks to SESI for the hash functions workaround

int index = 0;
string name = chs("seedAttribute");
if ( chi("type") == 1 )
    index = @primnum;
else if ( chi("type") == 2 )
    index = @ptnum;
else if ( chi("type") == 3 )
    index = @vtxnum;

if ( chi("useSeed") )
{
    int exist = 0;
    int hash = 1;
    int type = attribtype ( @OpInput1, chs("type"), name );
    if ( type == 0 )
    {
        int value = 0;
        exist = getattribute ( @OpInput1, value, chs("type"), name, index, @vtxnum );
        if ( exist )
            hash = random_ihash ( value ) % 65536;
    }
    else if ( type == 1 )
    {
        float value = 0;
        exist = getattribute ( @OpInput1, value, chs("type"), name, index, @vtxnum );
        if ( exist )
            hash = random_fhash ( value ) % 65536;
    }
    else if ( type == 2 )
    {
        string value = "";
        exist = getattribute ( @OpInput1, value, chs("type"), name, index, @vtxnum );
        if ( exist )
            hash = random_shash ( value ) % 65536;
    }
    if ( exist )
        index = hash;
}

float seed = 0.99 + ch("seed");
float r = rand ( index + seed + sin ( 13 * index + 19 * seed ) );
float s = fit ( random ( 17 * index + 91 * seed ), 0, 1, ch("srangex"), ch("srangey"));
s = ch("s") * ( 1 - ch("srand") ) + s * ch("srand") * ch("s");
float val = fit ( random ( 173 * index + 11 * seed ), 0, 1, ch("vrangex"), ch("vrangey"));
val = ch("v") * ( 1 - ch("vrand") ) + val * ch("vrand") * ch("v");
@Cd = hsvtorgb ( ( r + 0.618033988749895 ) % 1, s, val );



RFE: @elemnum that works based on the current Run Over mode instead of @ptnum, @primnum, @vtxnum
animatrix_
Attribute From Array

Sometimes you need to manually set attribute values by hand for a small set of values. This preset lets you do that and also allows setting indices manually if you don't want the values to be assigned from 0 to N sequentially as they appear in the values array.

Code is dynamically generated so no need to post here.







Anonymous
It would be nice if someone could make this topic STICKY, don't you think?
animatrix_
mantragora
It would be nice if someone could make this topic STICKY, don't you think?

That would be nice, or if SESI integrates some of the useful ones to Houdini as presets (under gear menu)

Attribute Hash

Allows you to generate hash (integer) values from an int/float/string attribute.

int ctype = chi("type");
int primorpt = -1;
if ( ctype == 0 )
    primorpt = @ptnum;
if ( ctype == 1 )
    primorpt = @primnum;
    
int hash = -1;
string name = chs("attribute");
int type = attribtype ( @OpInput1, chs("stype"), name );
if ( type == 0 )
{
    int value = 0;
    int exist = getattribute ( @OpInput1, value, chs("stype"), name, primorpt, @vtxnum );
    if ( exist )
        hash = random_ihash ( value ) % 65536;
}
else if ( type == 1 )
{
    float value = 0;
    int exist = getattribute ( @OpInput1, value, chs("stype"), name, primorpt, @vtxnum );
    if ( exist )
        hash = random_fhash ( value ) % 65536;
}
else if ( type == 2 )
{
    string value = "";
    int exist = getattribute ( @OpInput1, value, chs("stype"), name, primorpt, @vtxnum );
    if ( exist )
        hash = random_shash ( value ) % 65536;
}

i@hash = hash;
animatrix_
Particle Gnomon

int createPolygon ( int pt0; int pt1; int pt2 )
{
    int pr = addprim ( geoself ( ), "poly" );
    addvertex ( geoself ( ), pr, pt0 );
    addvertex ( geoself ( ), pr, pt1 );
    addvertex ( geoself ( ), pr, pt2 );
    return pr;
}

void createGeometry ( float s )
{
    float ss = 0.25 * s;
    
    vector p [ ];
    push ( p, set ( 0, 0, s ) );
    push ( p, set ( -ss, 0, 0 ) );
    push ( p, set ( ss, 0, 0 ) );
    push ( p, set ( 0, 0, 0 ) );
    push ( p, set ( 0, -ss, 0 ) );
    
    int pt [ ];
    for ( int i = 0; i < len ( p ); ++i )
        pt [ i ] = addpoint ( geoself ( ), p [ i ] );
    
    createPolygon ( pt [ 0 ], pt [ 2 ], pt [ 3 ] );
    createPolygon ( pt [ 0 ], pt [ 3 ], pt [ 1 ] );
    createPolygon ( pt [ 0 ], pt [ 4 ], pt [ 3 ] );
    
    setattrib ( geoself ( ), "primitive", "Cd", 0, -1, { 1, 0, 0 }, "set" );
    setattrib ( geoself ( ), "primitive", "Cd", 1, -1, { 0, 0, 1 }, "set" );
    setattrib ( geoself ( ), "primitive", "Cd", 2, -1, { 0, 1, 0 }, "set" );
}

addattrib ( geoself ( ), "primitive", "Cd", { 1, 1, 1 } );
createGeometry ( ch("s") );

i@gl_lit = 0;

NiX
Been using compile sop workflows a lot recently and have been looking for wrangley ways to do some of the things which are not compilable -


//Attribute Transfer

int handle = pcopen(@OpInput2, “P”, @P, chf(“rad”), chi(“num”));
vector lookup_P = pcfilter(handle, “P”); //Average P
vector lookup_attrib = pcfilter(handle, chs(“attrib”)); //Average of attrib

i@many = pcnumfound(handle);
if(i@many>0){
`chs(“attrib_cast”)` = lookup_attrib; //Supply the attribute you want to transfer
v@P = lerp(v@P, lookup_P, chf(“mix”));
}
olivierth
Convert from imperial to metric (feets, inches, numerator/denominator, pounds)

A simple but useful tool. I always find imperial measures online and convert to meters, etc. Does anyone know how to show the detail attributes in the UI of the asset?

float feet = chf("feet");
float inchesperfeet = 12;

float inches = chf("inches");
float inchespermeter = 39.3701;

int numerator = chi("numerator");
int denominator = chi("denominator");
float decimal = float(numerator) / float(denominator);

f@meters = ((feet*inchesperfeet) + inches + decimal)/inchespermeter;

float lbsToKg = 0.45359237;
float lbs = chf("pounds");

f@Kg = lbs * lbsToKg;
twelveplusplus
This is a great thread! I was thinking earlier today that it would be nice to have more wrangle presets (or python, VEXpressions or any code snippets or presets for nodes, really)

I was thinking about the online function of the Game Dev shelf tool. It would be really awesome if there were a way to have more of that type of online modularity in houdini.

Vex wrangle community presets would awesome (or any presets, or even hdas and shelf tools). maybe sidefx forum members could share their best presets public list to a channel. then, anyone using houdini with internet can select a public preset channel and use that person's presets.

I think an online preset ecosystem would be great for everyone:

  • Our precious presets can live safe on a cloud with access from anywhere, and safe from hard drive failure and laptop thief
  • Newbs would have more examples to get to speed
  • There can be a bit of networking, we could subscribe to each others sidefx preset channels similar to youtube. maybe your next good job will have liked and subscribed to your preset channel?
  • Maybe sidefx will have less work to do updating the help card examples, if a good community example is a click away
  • This can encourage all of us to be more organized in our work with houdini (especially me, of course)

What do people think of this idea?





To keep on topic: my finest attribute wrangle preset:

@N = @N;

Because if you are like I am, you have a lack of normal.
Especially when you dive into your new SOP network..

Many times, you wish for normal, though.

Well, friends, there is no easier way than this to have normal!

you can even choose the flavor of your normal. just select an option from the “Run Over” Menu! Houdini will give you that flavor of normal! Point normal, Vertex normal, Primitive, or even a Detail Normal

But don't choose “Numbers” from the menu. numbers can't have normals, due to math. You can trust me, in school I passed Vector Calculus one time (barely). Besides that, houdini won't do anything, except waste a couple of cpu cycles parsing a do-nothing node. So don't be vexed if you don't see a “number normal” in your geometry sheet or your middle mouse menu. There is nothing wrong with your computer just because of that website you visited.

I hope this preset serves you all well.

Maybe next post, I will make and give to you a preset…
to change your normal into a tangent…!

(which is my specialty, of course)
howitzer99
olivierth
Convert from imperial to metric (feets, inches, numerator/denominator, pounds)

Does anyone know how to show the detail attributes in the UI of the asset?

Hi Oliver,

I just stumped-upon your conversion code, thanks for sharing. I was able to update it with the detail attributes visible in the node. I created one for the length and the weight.

In the Edit Parameter Interface, I added a new float called Meters, and then gave it this expression in the Attribute Wrangle:
detail(“op:./”, “meters”, 0)

And then the same approach for the weight.

Hope this helps.


Cheers,
Dave
animatrix_
Reviving an old thread from the dead

Best kind of Wrangle preset is an empty one that (ab)uses the Run Over parameter with an expression:

if(ch("sourcegrouptype") == 4, 0, ch("sourcegrouptype"))

This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB