/ houdini

VEX in Houdini

My life has improved with the wrangle SOP and VEX. I don't know why i did shy away from that the first years I used Houdini, probably because it can look a bit intimidating. As a matter of fact, it is often actually more straightforward as the SOP equivalents. It's especially useful inside a solver sop, too.

Global / external attributes:
@Frame //current frame
@Time //current time, second-wise
@ptnum //this point's id
@primnum //this prim's id
@numprim //total prim number
@numpt //total point number

@P //point position
@N //normal
Setting attributes
//will just create a float attribute.
@myattrib; 
//vector attribute
v@vectValue = {1,1,1};
//float attribute
f@floatValue = 0.2;
//int attribute
i@intValue = 2;
Get user input

Believe it or not, Houdini will auto-create user input for you in a wrangle SOP:

//Create a float slider mapped to myfloat
f@myfloat = ch('float');
//Same with a vector
v@myvec = chv('vec');
//Int
i@myint = chi('int');
//Float ramp. Grab the value at the position ramppos.
float ramppos = 0.5;
f@otherfloat = chramp('ramp', ramppos);
Some snippets

Set point attribute by point id. Useful in loops.

setpointattrib(0, "attribute", @ptnum, val);

Refer to geometry in the second input

point(@OpInput2, "Cd", @ptnum);
Some examples
Randomize normal direction
v@N = normalize(@N + (ch('random_factor')* sample_direction_uniform(random(@P))));
Blur attribute
int pchandle = pcopen(0, 'P', @P, 1, chi('pts_to_average'));
@attrib = pcfilter(pchandle, 'attrib');
Iterate through prim's verts
for (int i=0; i < primvertexcount(0, @primnum) ; i++) {
    vector myP = vertex(0, "P", i);
}
Poor man's uvlayout

Following an uvtexture's face option, you might want to 'fit' uvs proportionally into 0-1 space. You could use uvlayout but that might rotate or such and is very slow depending on your setup.

vector minP = {100000, 100000, 100000};
vector maxP = {-100000, -100000, -100000};

// iterate once, get extents
for (int i=0; i < primvertexcount(0, @primnum) ; i++) {
    vector currentUV = vertex(0, "uv", @primnum, i);
    minP.x = min(minP.x, currentUV.x);
    maxP.x = max(maxP.x, currentUV.x);
    minP.y = min(minP.y, currentUV.y);
    maxP.y = max(maxP.y, currentUV.y);
}
    
// calculate sizes
float xSize = maxP.x - minP.x;
float ySize = maxP.y - minP.y;
float largestSize = max(ySize, xSize);
    
for (int i=0; i < primvertexcount(0, @primnum) ; i++) {
    vector origUV = vertex(0, "uv", @primnum, i);
    // transform to 0,0
    vector correctedUV = set(origUV.x + (minP.x*-1), origUV.y + (minP.y*-1), 0);
    // stretch / shrink to bounds
    correctedUV.x *= 1/largestSize;
    correctedUV.y *= 1/largestSize;
    // set the thing
    setvertexattrib(0, "uv", @primnum, i, correctedUV);
}
    
Packed prims: Add randomness
vector scale = {1,1,1};  
scale = scale * rand(@P);

matrix3 m_trans = primintrinsic(0, "transform", @ptnum);  
matrix scalem = maketransform(0, 0, {0,0,0}, {0,0,0}, scale, @P);  
m_trans *= matrix3(scalem);

//overall randomness: 20 deg around Y
float roat_rand = radians(fit(rand(@P),0,1,-20,20));  
rotate(m_trans, roat_rand, {0,1,0});  
setprimintrinsic(0, "transform", @ptnum, m_trans);
Create points at primitive centers (primitive wrangle)
int pt = addpoint(0, @P);
removeprim(0, @primnum, 1);
setpointattrib(0, "N", pt, @N);
Rotate stuff:
@P = qrotate( quaternion( {0,90,0}, 0 ), @P );

See:
http://www.tokeru.com/cgwiki/?title=HoudiniVex
https://sites.google.com/site/fujitarium/Houdini/sop/wrangle

Some animations:

Infection-style wrangle:

if (@tagged == 0) {
    float maxdist = ch('maxdist');
    int maxpoints = 8;
    int pts[] = nearpoints(0,@P, maxdist, maxpoints);
    int pt ;
    
    foreach  (pt;pts) {
        if (point(0,'tagged',pt)==1) {
            @tagged=1;
            v@Cd = {1,0,0};
            //int prim = addprim(0,'polyline');
            //addvertex(0,prim,@ptnum);
            //addvertex(0,prim,pt);
            @age = @Frame;
            return;
        }
    }
}
else{
@P.y = @P.y-0.1;
}

Crashing trees:

Each point stores a direction to the next untagged point, then vectors are interpolated

v@N2;
f@lifetime;
v@dir;

if (@tagged == 0) {
    @N2 = @N;
    float maxdist = ch('maxdist');
    int maxpoints = 3;
    int pts[] = nearpoints(0, @P, maxdist, maxpoints);
    int pt ;
    
    foreach  (pt;pts) {
        if (point(0,'tagged', pt)==1) {
            @tagged=1;
            @dir = @P - point(0, 'P', pt);
            @dir.y -= 0.0001;
            return;
        }
    }
}
else{
    @lifetime += 0.006;
    @lifetime = clamp(@lifetime, 0, 1);  
    float anim_scale = chramp('anim', @lifetime);
    @N = lerp(@N2, @dir, anim_scale);
}

random links:
http://pepefx.blogspot.de/2015/06/h14-point-wrangle-vs-creep-sop.html
https://sites.google.com/site/fujitarium/Houdini/sop/wrangle
http://www.tokeru.com/cgwiki/?title=HoudiniVex