Jump to content

Replicate ForEachSOP in vex/wrangle


Annon

Recommended Posts

Pardon my total lack of understanding of vex so far ;)

 

I've created a relative matrix building thingy in vex/attribWrangle(points) that's working well, but now I want to do it on a per attribute basis. So each object will have a class or name etc and for each attribute I want to return a handle of that geo and run my code on each object separately. I could shove it in a forEachSOP, but I'd like to know if this is possible in vex alone?

 

There's ways around this simply I know. My example I started building I could see people would respond with an alternative way of doing it, but that's not what I'm after, I need to know if there's a general way of looping over different sets of geo. 

 

So if I have 100 points in 10 objects, I would loop over the geo where it would always return point numbers 0-9 in the equivalent of geoself(), not doing soming like "for each point in all, does attribute == "blah"" etc...

 

Is this the domain of HDK? Not wrangles?

 

Thanks

Christian

Link to comment
Share on other sites

There are a lot of scenarios where you can emulate the behaviour of ForEach SOP in Wrangles.

The downside is that you have to be in Details Mode, so I'm not sure if SIMD acceleration works, but it is still faster than ForEach.

 

There are 4 VEX functions that will help you to do that :

nuniqueval

uniqueval

findattribvalcount

findattribval

 

So first you have to find how many unique values you have. This will give you the number of pieces. Then create a loop with the same number of iterations.

Inside this loop you can operate on each piece individually.

Next get how many of this values are there and create another loop.

Now you can traverse over each individual component of that piece.

 

I always use this instead of ForEach if I can and find it much better alternative.

 

 

Actually that's exactly what I'm doing while controlling bullet pieces with SOP animation.

Edited by rayman
  • Like 3
Link to comment
Share on other sites

Thanks guys, I looked at that example, I understood it but I'm unsure how I go about doing what I want to do.

 

So I have a matrix creation thing that just looks at @ptnum 0, 1, 2 on input 1 and input 2, builds the matrix etc...

Was going to randomize the numbers to be somewhere between 0 and npoints etc.

 

SO.. Is it possible to wrap this example (attached) into a per primitive attribute thing? I think I just have to shift my thinking a bit...

 

Cheers

Christian

multiMatrix.hip

Link to comment
Share on other sites

Generally I wouldn't do it that way:

string nameAttr = "name";
string matrixAttr = "trMatrix";
int currIn = 0;
int restIn = 1;

//create attribute
matrix offMx = ident();
addattrib(currIn,"point",matrixAttr,offMx);

//itarate through pieces
//get unique piece count
int piecesCount = nuniqueval(currIn,"point",nameAttr);
for(int i=0; i<piecesCount; i++){
    //get current piece name
    int pieceName = uniqueval(currIn,"point",nameAttr,i);//this works for strings too
    //get piece points count
    int piecePointCount = findattribvalcount(currIn,"point",nameAttr,pieceName);
    //if there are at least 3 points compose matrix
    if(piecePointCount>=3){
        //get point ids
        int currPt1 = findattribval(currIn,"point",nameAttr,pieceName,0);//get current point 1 id
        int currPt2 = findattribval(currIn,"point",nameAttr,pieceName,1);//get current point 2 id
        int currPt3 = findattribval(currIn,"point",nameAttr,pieceName,2);//get current point 3 id
        
        int restPt1 = findattribval(restIn,"point",nameAttr,pieceName,0);//get rest point 1 id
        int restPt2 = findattribval(restIn,"point",nameAttr,pieceName,1);//get rest point 2 id
        int restPt3 = findattribval(restIn,"point",nameAttr,pieceName,2);//get rest point 3 id
        
        //get point positions
        vector currPos1 = point(currIn,"P",currPt1);
        vector currPos2 = point(currIn,"P",currPt2);
        vector currPos3 = point(currIn,"P",currPt3);
        
        vector restPos1 = point(restIn,"P",restPt1);
        vector restPos2 = point(restIn,"P",restPt2);
        vector restPos3 = point(restIn,"P",restPt3);
        
        //create vectors
        vector currVecX = normalize(currPos2-currPos1);
        vector currVecY = normalize(currPos3-currPos1);
        vector currVecZ = cross(currVecX,currVecY);
        
        vector restVecX = normalize(restPos2-restPos1);
        vector restVecY = normalize(restPos3-restPos1);
        vector restVecZ = cross(restVecX,restVecY);
        
        //compose matrices
        matrix currMx = maketransform(currVecZ,currVecY,currPos1);
        
        matrix restMx = maketransform(restVecZ,restVecY,restPos1);
        offMx = invert(restMx)*currMx;
        //go through each point and set its value
        for(int p=0; p<piecePointCount; p++){
            int currPt = findattribval(currIn,"point",nameAttr,pieceName,p);
            setattrib(currIn,"point",matrixAttr,currPt,0,offMx,"set");
        }
    }
}

multiMatrix_PerAttrib.hiplc

  • Like 3
Link to comment
Share on other sites

Wow, you have been so much help! Thank you!!!

Also good to update to H14 and am glad you can now have multiple outputs from subnets...

 

I'll play with this more on monday, but it's a great example, thank you very much.

Christian

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...