Friday, 29 September 2017

connecting points again..


Here're two expanded ways of connecting groups of points together!




The first method relies on you creating an attribute in a preceding point wrangle called "id". This is the value you'll search for, when making connections. The "destination" points go into the first input, the origin points go into the second.

int count = findattribvalcount(1,"point","id",i@id);

for (int i = 0; i < count; i++) {
    int find = findattribval(1,"point","id",i@id,i);
    
    int prim = addprim(0,"polyline");
    
    vector p2 = point(1,"P",find);
    
    int pt = addpoint(0,@ptnum);
    setpointattrib(0,"P",pt,p2);
    
    addvertex(0,prim,@ptnum);
    addvertex(0,prim,pt);
}


LINE BY LINE

int count = findattribvalcount(1,"point","id",i@id);
//count number of points that have the "id" value
for (int i = 0; i < count; i++) {
//start for loop, for the number of points it has found
    int find = findattribval(1,"point","id",i@id,i);
    //get point number for point that has the id value. The last i is the index of the for loop.
    int prim = addprim(0,"polyline");
    //add primitive, of polyline type
    vector p2 = point(1,"P",find);
   //create position vector based on point number found 
    int pt = addpoint(0,@ptnum);
//create point at the position of current point
    setpointattrib(0,"P",pt,p2);
    //set position of just created point to the vector created
    addvertex(0,prim,@ptnum);
//add vertex to the primitive at current point position
    addvertex(0,prim,pt);
//add vertex to the primitive at found point position
}





This method doesn't need the "id" value, but just grabs the closest point to it. Again the many destinations go into the first input and the few "origins" go to the second.

int nearpt = nearpoint(1,@P);
int prim = addprim(0,"polyline");
vector p2 = point(1,"P",nearpt);
int pt = addpoint(0,@ptnum);
setpointattrib(0,"P",pt,p2);
addvertex(0,prim,@ptnum);
addvertex(0,prim,pt);


LINE BY LINE

int nearpt = nearpoint(1,@P);
//get id number of point from second input to currently processed point's position
int prim = addprim(0,"polyline");
//create primitive of polyline type
vector p2 = point(1,"P",nearpt);
//set vector to nearpt's position
int pt = addpoint(0,@ptnum);
//add point at currently processed point's position
setpointattrib(0,"P",pt,p2);
//set position of new point to position of nearpt.
addvertex(0,prim,@ptnum);
//add vertex at currently processed point's position
addvertex(0,prim,pt);
//add vertex at nearpt's position

Wednesday, 27 September 2017

writing alembics for maya - path attribute

Covered this in an older post, but this is for more straightforward cases when you want to define a group and shape node name for Maya purposes. We do this to avoid multiple shape names in Maya (eg. lots of pSphereShape1's or multiple Houdini Merge listings ; Alembic will take whatever the penultimate node to your ROP-alembic is called!)

In a primitive wrangle, this bit of code will create two text entry boxes, so you can input a group name and a shape name. If you were to call the group "squareGrp" and the name "square", then the resultant hierarchy would be "squareGrp/square/squareShape" in Maya.


string group = chs("MayaGroup");
string name = chs("Name");

group += chs("groupSuffix");
name += chs("geoSuffix");

s@path = group + '/' + name + '/' + name + 'Shape';


Remember to tick the "build hierarchy" box in the ROP-Alembic node & also to tick "use path".

Saturday, 16 September 2017

Entagma snippet : drawing lines between a set of two points

This is useful when you want to connect two bunches of points together.. You'd think it'd be easy right?

Scatter, say 50, points on a grid. Then another 50 on another grid (or any shape..it doesn't really matter). Move them about a bit, then plug them both into a point wrangle (first two inputs).
This code will draw a single primitive edge between the points, paired by @ptnum (so you could do some sort of sorting beforehand, I guess):


int npnt=addpoint(0, @opinput1_P);

int nprim=addprim(0,"polyline");

addvertex(0,nprim,@ptnum);

addvertex(0,nprim,npnt);

Lets tackle each line.

int npnt=addpoint(0,@opinput1_P);
First we make a new point. Point wrangles only ever consider the first input's points. So we need to add the other input's points into the mix. I think the 0 corresponds to the @ptnum attribute.. So it looks up the relevant point in input1 and then puts it at the position specified by "@opinput1_P". That's a handy bit of VEX shortcutting there.

int nprim=addprim(0,"polyline");
Here we are creating a new primitive, of polyline type. Nothing is there yet...

addvertex(0,nprim,@ptnum);
Now we add a vertex to the primitive we just created. Firstly, we add the point we're currently processing.

addvertex(0,nprim,npnt); 
Next we add the vertex we added at the beginning (our currently processed point's counterpart in the other group).

That's it!

set colour according to bounding box.

now that the old Point node is more or less dead and buried, we have to rely on wrangles or vops to set our colours in fancy ways.

To give an object a gradient of colour based on it's bounding box (eg. black-to-red, from -ve to +ve on the x axis) we can use the relbbox function.
In a wrangle, we can type

@Cd=set(relbbox(@P.x),0,0);

tadah!

Tuesday, 15 August 2017

Shattering an animated object. Eg. flying saucer smashing into something

Say you want to make a moving object smash into bits. Eg. A flying saucer that's been hand animated, which then needs to break apart dynamically.
As usual this isn't going to be straightforward :)

Shatter and pack geometry as usual, only what we need to do is ensure the points are not active. You can be double sure by laying down a point wrangle and setting i@active=0;

In your DOP network, make sure the RBD is not an active rbd as initial state. Set it to deforming static object. This should be done in the drop down menu. Now if you hit play, the object should not simulate at all & only follow it's given animation. "Overwrite Attributes" is NOT ticked.

We will use a sop solver & a point wrangle within to set the active value to 1. I've found using an activating shape like a box to set points into a group (using the bounding option) works best for this. eg. the saucer rbd points don't become active until they pass through said box. The attribute "deforming" (an integer) must be set to 0 once the "active" value switches to 1. This is so it no longer animates, or as Houdini refers to it, "deforms".
We use a sop solver so that the active value stays at 1 and doesn't reset to 0 once it passes through the activating shape. What we also need to do is use this sop solver in conjunction with the Bullet solver. This is done with a multi-solver.

Things I've found that are a bit problematic are glue constraints... Will look into this.
Update on glue - 

Houdini 16.0.504.2 has a weird thing... The Constraint Network's "Overwrite with SOP" attribute's default value is supposed to only import the SOP on the first frame...but it seems to behave as if it's always importing it. As a result, set it to 0 (zero), so that the animation of the object is ignored. This seems to make the glue constraints work properly.

https://drive.google.com/file/d/0B2eKYZ42BvalZnFaY0NZMkhwb3M/view?usp=sharing

Monday, 17 July 2017

pyro - "custom wind volumes"

Sometimes you want to have pyro behave a certain way in a certain area. Eg.  the smoke should go from left to right, then suddenly shoot upwards after a few seconds.

Instead of fiddling with the advection or velocity updates, it's a bit simpler to create a separate pyro source that only emits velocity.
Simply create a source as you normally do, but remove it's density & temperature. Remember to scale these to zero in the DOP area too!

Friday, 23 June 2017

latticing VDBs/volumes

Bring in your VDB however you need to.
Plug it into a VolumeVOP and create an addpoint node. Plug P into the ptvalue input.
Next create a setattrib node and plug your addpoint's ptnum output into the setattrib's i1. Plug your density into the value node and name the parameter "density". Jump back out of the VOP.

This will have made a volume grid of points that represent your VDB, each containing the corresponding density value. The number of points created is dependent on the resolution of your VDB, although I guess you could duplicate points and hope that they interpolate nicely?

Next, add a Timeshift node after the VOP and freeze your volume at the point you think it occupies the most space. Eg. if it's a trail of cigarette smoke, it's last frame. Create a Bound node for this.
This is now the lattice you can transform and deform.
Then make a Lattice node and plug your Volume VOP into the first input, the output of the Bound into the 2nd and then finally whatever your transform/deforms are into the 3rd.

So far, we've transformed a bunch of points, that hold our density values.. Now we have to recreate our volume..


Connect a Bound node to your deformed points. We're making an empty volume that encompasses the limits of your deformed sequence. Add an Iso Offset to this, set the Output Type to Fog Volume, Mode to Ray Intersect and name it Density. You control the effective resolution with the sampling. Next let's copy the density back into your empty volume.

Make a volume VOP, plug the Iso Offset into the first input & the lattice into the second. Jump in and make a Point Cloud Open node. Connect the P to the P and the OpInput2 into the File input.
Create a Point Cloud Filter and set it's signature to Float Channel and label the Channel "density". Plug the Point Cloud Open's handle into the Point Cloud Filter's handle input. Finally plug the value into the volumevopoutput's Density..

Your blank volume now has a deformed version of the original's density!
Sit back, relax and pretend you're resimming now.