AIR RESIST
//in **popdrag** check "use VEXexpression" then type in
airresist = fit01(rand(@ptnum),0,1);
Masking MeshDeoform
1vector Cd = point(1, "Cd", @ptnum);
2vector animPos = point(1, "P", @ptnum);
3float weight = Cd.x;
4
5@P = @P*1(1-weight) + (animPos*weight);
ptnum/numpt
f@mask = @ptnum/(@numpt-1.0);
用材質分Group
string group = split(s@shop_materialpath, "/")[-1];
setprimgroup(0, group, @primnum, 1);
Get input1
@Cd = v@opinput1_Cd;
Setup Maya Hierarchical path
s@path = sprintf('%s/%s_%02d/%s_%02dShape', chs('groupname'), chs('packedname'), @primnum, chs('packedname'), @primnum);
用Group出Attribute
Groups To Attribute With VEX
Today at work I was loading some really heavy geometry into Houdini that needed FX added to it. Its came in from Maya with thousands of primitive groups for different numbered parts of the geometry. If you tried it before you will know that unpacking heavy geometry with a lot of groups is any easy way to fill up your ram. In this cache filling 64GB and the cracking Houdini after filling the swap as well.
I really wanted to keep the incoming part numbers because so parted where linked to other parts with different names and not all part where connected with connectivity so I quick Connectivity SOP trick wouldn’t do the job. Luckily I could access the groups while the geometry was still packed primitives so the solution was to convert the groups to a single numbered attribute and get rid of the groups before unpacking or converting to full Houdini geometry. So that is the back story and here is my solution.
string groups[] = detailintrinsic(0, "primitivegroups");
In vex you can use the Detail Intrinsic function to write all the primitive groups to a string array, you can do the same point edge and vertex groups. So that’s step one, pretty easy right? The is were it get a little more tricky. The groups are named something like:
asset_foo_0001_bar
asset_foo_0002bar
asset_bar_002_blabla
asset_bar_0003_blabla
Combining all the foo and bar groups is easy using a group combine SOP.
But what takes a bit more thinking is extracting the numbers so you have an attribute that reads like this:
The bad naming above with different padding and some numbers not having underscores was deliberate as that is what I was dealing with. VEX has a couple of functions to handle string manipulation and the really interesting ones for this problem are the re functions, there are a couple re_find(), re_match() and a few other ones. If you have never seen these before or have and wondered what they are for, well they are what is called regular expressions or regex. Regex is a sequence of characters that define a search patterns. These are usually use by string searching algorithms like in this case in VEX in Houdini.
To demonstrate I will how it works lets apply a re_find() to the first group string “asset_foo_0001_bar”. The pattern \\\\d finds all the digits in a string while \\\\D finds all the non digit characters.
s@num = re_find(r"\\\\d","asset_foo_0001_bar")
returns = 0
s@numAll = re_findall(r"\\\\d","asset_foo_0001_bar");
returns = [0,0,0,1]
If the above code makes sense lets look at searching for 4 numbers in a row. To find that the pattern is \\\\d{4}.
s@num = re_find(r"\\\\d{4}","asset_foo_0001_bar")
returns = 0001
You can get a lot more advanced with these patterns but all I will add is \\\\d{3,6} which means find strings of numbers between 3 or 6 which compensated for one of my groups having less padding than the others. The lack of an underscore in string two doesn’t even matter with this method so that is taken cares of as well.
With step two sorted step 3 will be easy, all we need to do is use a foreach loop to go through the group array and find the group numbers for primitives that belong to that group and write that to an attribute. The code for that run over primitives with a list of primitive groups looks like this.
//convert numbered groups to a numbered attribute
string groups[] = detailintrinsic(0, "primitivegroups");
int prim = @primnum;
string elemnum;
foreach(string i; groups)
{
//if the current primitive is in group i
if(inprimgroup(0,i,prim) == 1)
{
elemnum = re_find(r"\\\\d{3,6}",i);
}
}
s@number = elemnum;
This is just scratching the surface of what you can do with regular expressions, its a great way of seaching for values in a sting when you are not 100% sure the string pattern is all was the same. There are many more patterns you can make and online help like regex101.com makes it super easy to test and debug.
Enjoy!
RS Instancing
s@instance = "/obj/tree2";
VEX spining particle
VEX: Spinning Particles
The titles should really be how to rotate the orient attribute but spinning particles is more catchy. Rotation can be a tricky beast and when it comes to particles there are a bunch of ways to control their direction, and when you are stacking multiple rotations things can become a little hairy! I suggest using quaternions to control direction because the qmultiply function makes it very simple to modify the current orient.
Randomly oriented points
The above points have random orientation driven by a random @orient attribute. To rotate it around the z axis with the qmultiply we need to build the quaternion to multiply with. To do that we use the quaternion fuction building it with a vector axis and a float angle. The axis is z so (0,0,1) and the angle is set to @Time * $PI * 2 so that it make a full rotation each second. Finally the new vector4 we created gets multiplied with the orient and this is the result:
Here is was I described in code:
// make spin vector4
vector axis = set(0,0,1);
float angle = @Time * $PI;
vector4 spin = quaternion(angle, axis);
// apply to orient attribute
@orient = qmultiply(@orient, spin);
The cool thing about this is that the new vector4 does not have to know anything about the incoming orient attribute and it can be applied in unil directions. To illustrate that here is the spin vector4 applied as the orient:
@orient = spin;
For there if you want to change the behaviour like pick a random axis or spin a different rates all you need to control is a unit vector direction and and a float angle. Here is one last example with a random axis and angle.
//axis
vector axis = set(0,0,0);
int randaxis = floor(rand(@ptnum+237.23*293)*3);
setcomp(axis,1,randaxis);
//angle
float spinseed = rand(@ptnum+38.43*8723.74);
float rate = fit01(spinseed, 0.1, 1);
float angle = (@Time * $PI * 2) * rate;
//spin quaternion
vector4 spin = quaternion(angle, axis);
@orient = qmultiply(@orient, spin);
Here is the HIP File enjoy!