Jump to content

Custom smooth deformer


Pancho

Recommended Posts

In SI it's pretty simple to do this kind of thing. Even use the "Keep" node in conjunction with the "self.vertexIsBorder" one to make the borders stick at their position (Keep node in front of the set point position one).

 

How would I do this in an Attribute Vop? The Smooth operator give really funky results and is hardly usable.

post-13587-0-34249300-1437998598_thumb.p

Edited by Pancho
Link to comment
Share on other sites

That same set up with VOPs is definitely a little trickier, as far as I know you can't return an array of neighbor points, so you would have to create a loop, which again can be kinda tricky.

 

I actually did this once with VOPs, mostly to see if I could, it wasn't fun and making it iterate was nearly impossible.  You could achieve the same functionality using a point cloud but it will smooth non connected vertices as well.

 

However using a point wrangle node, this is very easy.  My Vex is pretty rusty but this still only took me about five minutes :)

int neigbors = neighbourcount(0, @ptnum);
vector totalPos = {0,0,0};
for (int x = 0; x < neigbors; x++)
{
    int neighPtnum = neighbour(0, @ptnum, x);
    
    totalPos += point(0, "P", neighPtnum);
    
}

@P = totalPos/neigbors;

If you want to pin borders I would try something like testing if a point only has two connected vertices and not smoothing the point.

 

Houdini's smooth node uses a frequency based smoothing approach, if i remember correctly.   http://graphics.stanford.edu/courses/cs468-12-spring/LectureSlides/06_smoothing.pdf  I had a better link at one point, but that covers most every smoothing technique.  Your node set up, and this Vex code uses Laplacian smoothing.

Edited by captain
  • Like 1
Link to comment
Share on other sites

Thanks! Almost there. : )

Just two things.

a) How do I add the point position of the actuall point to total Pos? totalPos += point (P) is obviously not the correct syntax.

B) Tried to set an outer loop around your code, but the code only iterates once. Is that because P can only get set once in a point wrangle node? How would I loop it?

Link to comment
Share on other sites

How do you mean?  Add the position of the the current point your smoothing? 

 

totalPos +=@P

@P = totalPos/(neigbors+1);

 

 

You can't really make a loop around it the proper way as in, smooth all points then do it again, I think you would need to use a foreach sop to iterate properly.  

Edited by captain
Link to comment
Share on other sites

Hi!

 

Yeah, that's what I've meant!

 

Pitty that this can't be done in the point wrangle node.

 

But could it be done if I'd transfer P to a custom attribute and loop over this and apply this to P after the loops? Just an idea ....

Link to comment
Share on other sites

Man! Thanks!

 

Looking forward to the day when H will get some "proper" SI nodes. There's so much stuff in SI which is simple to achieve with a few nodes and very weired or difficult in H. Hopefully they'll implement the best pieces of SI in order to makes things more comfortable in H.

Link to comment
Share on other sites

self.Neighbours will return the connected vertices of the current point. If you want to get the nearest neighbours in a particle way, you'd choose "get closest points". You are able to changed the maximum amount of points returned in the array and change the maximum search distance.

It's a bit frustrating to feel so handicapped when making the switch from SI to H.

Link to comment
Share on other sites

Houdini has the same functionality, using a point cloud you can return an array of the closest points based on range and other parameters.  

 

Houdini exposes things at a lower level(or i should probably say in a different way, as VEX is really a shader language) then SoftImage seems too, so in many instances it can be more difficult to do equivalent operations, however because of this Houdini in many instances can be faster, while being just as flexible.  It can be a steep learning curve but once you figure out how to port over your bag of tricks, things get way easier.

 

 

I added a bit more to show what Houdini is really about, this allows you control the weighting and the iterations, without the need to jump into the geometry object.  

Edited by captain
Link to comment
Share on other sites

Point clouds in Houdini already sort the found points by distance. If you search for 9 points you know you end up with a 3x3 grid of points where the diagonals will always be the last 4 points in the list.

You can use this information to get a weighted average by assigning the last 4 points a lower weight. 

Link to comment
Share on other sites

I had a few minutes, so I added the functionality to pin the borders(works as long as your mesh is all quads), and the ability to blend the pinned border points.  Figured I'd stick it up here real quick. 

 

Should do everything that you could do with it in SI (and a bit more), you can turn this into an asset and drop it down whenever you need.  Never have to think about it again.

Edited by captain
Link to comment
Share on other sites

Okay, so I got really distracted this with today, and really wanted to find a way to find border points in all cases.  In most cases one would just see which edges are shared, however I don't believe this is possible in VEX.  So what I did was get the neighborCount of all the neighbor points and use a algorithm that tries to figure out if this point is a border point using that information.  I actually needed something like this, but I would just remesh first, the quad stuff was a bit of masochistic fun.

vector doSmooth(int neigbors, myPtnum; vector myPos)
{
    vector totalPos = {0,0,0};
    for (int x = 0; x < neigbors; x++)
    {
    
        int neighPtnum = neighbour(0, myPtnum, x);
    
        totalPos += point(0, "P", neighPtnum);
    
    }
    vector neighPos  = totalPos/neigbors;

    return (myPos*(1-chf("weight"))) + (neighPos*chf("weight"));
}

int isEdge(int neigbors, myPtnum)
{
//do we have only two edges connected to us then we return 1, as in yes we are an edge point
    if (neigbors == 2)
    {
        return 1;
    }
    //count the number of edges of each of our neighbors
    int hasTwo = 0, hasThree = 0, hasFour = 0, hasFive = 0, hasSix = 0;
    for (int x = 0; x < neigbors; x++)
    {
        int nnCnt = neighbourcount(0,neighbour(0, myPtnum, x));
        //printf("%g \n", nnCnt);
        if (nnCnt == 2)
        {
            hasTwo += 1;
        }
        else if (nnCnt == 3)
        {
            hasThree += 1;
        }
        else if (nnCnt == 4)
        {
            hasFour += 1;
        }
        else if (nnCnt == 5)
        {
            hasFive += 1;
        }
        else if (nnCnt >= 6)
        {
            hasSix += 1;
        }
        
    }
    //tri meshes
    if (chi("triMesh") == 1)
    {
   	 if (neigbors > 3 && (hasFive + hasSix) > 3)
  	 {
   	    return 0;
   	 }
  	 else if (neigbors > 5)
  	 {
  	    return 0;
  	 }
    return 1;
    }
    
    //quads
    else if (neigbors == 3 && hasThree == 1 && hasFour == 1 && hasFive == 1)
    {
        return 0;
    }
    else if (neigbors == 3 && hasFour < 2)
    {
        return 1;
    }
    // this case can go either way
    else if (neigbors == 3 && hasFour == 2 && chi("notWorking")==0)
    {
       return 0;
    }
    else if (neigbors == 3 && hasFour == 2 && hasFive == 0) 
    {
        return 1;
    }
    else if (neigbors == 3 && hasFive == 1) 
    {
        return 0;
    }
   //do we have four edges and one of those has only two edges
   else if (hasTwo >= 1 && (neigbors == 4 || neigbors == 3))
   {
        return 1;
   }
   
   else if (neigbors == 5 && hasTwo >= 1)
   {
       return 1;
   }
    return 0;
}

int neigbors = neighbourcount(0, @ptnum);


if (isEdge(neigbors, @ptnum) == 0)
{
    @P = doSmooth(neigbors, @ptnum,  @P);
}
else 
{
    @P = (doSmooth(neigbors, @ptnum,  @P)*chf("pinBlendWeight")) + (@P*(1-chf("pinBlendWeight")));
}

It works in 4 out of 5 cases and seems to always work if you remesh first, so it could be useful, although there's probably some SOP node I can't think of, that just marks border edges :)

Edited by captain
Link to comment
Share on other sites

with all this VEX/Wrangle epidemy don't forget that you can use:

Group SOP in Point mode

uncheck Enable in Number tab

check Enable and Unshared edges in Edges tab

that will give you group of border points

which you can either use in wrangle as if (!i@group_border) ...

or directly run your Wrangle only on !border group (e.g. not border points)

 

 

however for pure VEX solution to detect border points you can do:

int isBorderPoint(int geo, ptnum)
{
    int hedge = pointhedge(geo, ptnum);
    int starthedge = hedge;
    do
    {
        if (hedge_equivcount(geo, hedge) == 1) return 1;
        hedge = pointhedgenext(geo, hedge);
    } while (starthedge != hedge && hedge != -1);
    return 0;
}
  • Like 3
Link to comment
Share on other sites

Great that you put all the effort into this. Thanks! I like that you can dig really deep into H, but sometimes the ease and very efficient low level qualities of SI are lacking. Hope the team creates more simple ways to achieve all this. : )

Link to comment
Share on other sites

Thank you Anim,

 

That's a way better solution.  :)   I've spent this entire year in the HDK working with tool states, apparently it's melted my brain.  

 

Half edges in Vex is awesome though, I hadn't seen that before now.  

 

 

Pancho- I wouldn't say much of this is "digging deep", the group sop solution is really a vital tool in Houdini.

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...