Search - User list
Full Version: Anyone has a split face VEX function?
Root » Technical Discussion » Anyone has a split face VEX function?
animatrix_
Splitting a face by inserting a point at the center of it, and connecting this new point to each edge of the face.

Has anyone written such a code?

There is a thread from 2 years ago where Jeff Lait mentioned a possible solution using add and setprimvertex but addprimvertex doesn't exist:
https://www.sidefx.com/index.php?option=com_forum&Itemid=172&page=viewtopic&t=30150&start=0&postdays=0&postorder=asc&highlight= [sidefx.com]

Is it supposed to be addvertex?

Even then it will be quite a challenge. I know the HDK must have a method for this so what's the secret?
jlait
Yes, I think I meant addvertex() in that case. That was also about splitting an edge, which is much more delicate than splitting a face.

Attached is a .hip file doing face splitting in H15.0, I've not tested in H14.0.

Turning a polygon into a fan of triangles is pretty straightforward with addpoint/addprim/addvertex/removeprim. The tricky part is attributes. Trying to loop over and interpolate all attribute types in VEX is both difficult and slow. Fortunately, we have the Attribute Interpolate SOP. This SOPs primary purpose is exactly this sort of reconstruction effort. Rather than trying to explicitly average all point/vertex/prim attributes, you instead record in attributes what the source & weightings were. The attribute interpolate will then handle the messiness of properly blending attributes.

Note in the attached I have separate sourcevtx_ and sourcept_ arrays, you could remove the point version and add * to the respective vertex attribute interpolate's point mask, because source points can be determined from source vertices. But this shows the set of possible options.

The code for the face splitter:

// Construct center point
vector center = 0;
// Get the points of our primitive
int srcpts = primpoints(0, @primnum);
int srcvtx = primvertices(0, @primnum);

float weights;
// Create our attributes to store our origin points.
// Note the last parameter determines type and defaults
// (which is irrelevant for arrays)
addpointattrib(0, ‘sourcept_num’, srcpts);
addpointattrib(0, ‘sourcept_weights’, weights);
addvertexattrib(0, ‘sourcevtx_num’, srcvtx);
addvertexattrib(0, ‘sourcevtx_weights’, weights);
addprimattrib(0, ‘sourceprim_num’, int(-1));
addprimattrib(0, ‘sourceprim_uvw’, vector(0));

foreach (int pt; srcpts)
{
center += point(0, ‘P’, pt);
append(weights, 1.0 / len(srcpts));
}
center /= len(srcpts);

int centerpt = addpoint(0, center);
setpointattrib(0, ‘sourcept_num’, centerpt, srcpts);
setpointattrib(0, ‘sourcept_weights’, centerpt, weights);

float singleweight = { 1.0 };
for (int subface = 0; subface < @numvtx; subface++)
{
// Set the point weights for single-sourced points
setpointattrib(0, ‘sourcept_num’, srcpts, srcpts);
setpointattrib(0, ‘sourcept_weights’, srcpts, singleweight);

// Create our triangle.
int tri = addprim(0, ‘poly’);
setprimattrib(0, ‘sourceprim_num’, tri, @primnum);
int vtxidx = subface;
int v1 = addvertex(0, tri, primpoint(0, @primnum, vtxidx));
setvertexattrib(0, ‘sourcevtx_num’, v1, -1, srcvtx);
setvertexattrib(0, ‘sourcevtx_weights’, v1, -1, singleweight);
vtxidx = (subface+1) % @numvtx;
int v2 = addvertex(0, tri, primpoint(0, @primnum, vtxidx));
setvertexattrib(0, ‘sourcevtx_num’, v2, -1, srcvtx);
setvertexattrib(0, ‘sourcevtx_weights’, v2, -1, singleweight);
int v3 = addvertex(0, tri, centerpt);
setvertexattrib(0, ‘sourcevtx_num’, v3, -1, srcvtx);
setvertexattrib(0, ‘sourcevtx_weights’, v3, -1, weights);
}
removeprim(0, @primnum, 0);
animatrix_
Thanks Jeff, your function works beautifully. I should have been more clear though, because I meant splitting a face where the new point connects the the center of each of the edges of the face being split, so subdividing a face.

I want to implement catmull clark subd in VEX, so the face split proves to be the hardest part by far

I also thought about splitting edges a little and it seemed like it would take a lot of code to do so.

So my problem is harder to implement than a mere edge split

If I am not wrong, I have to think of open poly curves, closed polygons where the edges to split doesn't have any other face sharing it, and the case where there are other faces sharing it. Maybe there are more issues to think about?
jlait
The problem is a simple For-All-Primitives won't work properly. You want to ensure points created on shared edges are shared.

You could re-create them for all faces but mark them with their creation points. Then do a fuse using the creation point attribute as the distance metric.

Or you could do it is several passes. In possibly four attribute wrangles:
* Create all face points
* Create all edge points
* Update the vertex points
* Stitch together the new polygons

The first is a for-all-primitives. The second a for-all-points that then loops over neighbours and creates to a higher point number. The third is loop over all original points. And the final is again a loop over all primitives.

A complicated part is to include a tracking attribute in the face/edge points to make sure you can find them again in the successive steps.
animatrix_
Thanks Jeff, I will leave this to SESI then as it seems like a major undertaking .
animatrix_
Finally bit the bullet and did it



https://www.sidefx.com/forum/topic/74486/ [www.sidefx.com]
wangguo
use halfedge can do it
vinyvince
Impressive implementation Animatrix!
Everytime i see your custom python sexy interface and come back to the defaut houdini, i feel like driving an old car


Im confused by a couple of 2 things actually.

-The first one is the tittle of your video. I know VEx is multithread for sure, but does that mean the Houdini subdivide node in its current state is not? If it's the case, such an important node should really be, Sidefx if i could say…

- Did you implementation differ for *all* the current ones present in the subdivide node. I see you comparing to one or two

- At some point you do a local subdivision on a group of poly , but it look like it broke the surface tangent continuity.
Which should not be the case in the pixar renderman implementation i believe. But be you just have to recomput nomal but is it expected?
animatrix_
vinyvince
Impressive implementation Animatrix!
Everytime i see your custom python sexy interface and come back to the defaut houdini, i feel like driving an old car
Thanks! SESI is welcome to add this customization as an option to default Houdini

vinyvince
Im confused by a couple of 2 things actually.

-The first one is the tittle of your video. I know VEx is multithread for sure, but does that mean the Houdini subdivide node in its current state is not? If it's the case, such an important node should really be, Sidefx if i could say…

Yes the default Subdivide is not multi-threaded. You can verify this using the performance monitor. My implementation is VEX based but there are still other nodes in the network that are not fully threaded, so I loop over each connected piece in a compiled network to fully maximize performance. This is a low hanging fruit that should be added to the default Subdivide. RFE submitted.

vinyvince
- Did you implementation differ for *all* the current ones present in the subdivide node. I see you comparing to one or two

My implementation is based on OpenSubdiv but some cases are handled differently by design.

vinyvince
- At some point you do a local subdivision on a group of poly , but it look like it broke the surface tangent continuity.
Which should not be the case in the pixar renderman implementation i believe. But be you just have to recomput nomal but is it expected?

There might be some shading differences in the viewport but this is due to the point ordering of the polygons that affects the viewport triangulation (1). The topology is exactly the same in most cases, but in cases like below, there are clear issues in the default Subdivide algorithms (2).

There was a bug with OpenSubdiv to crash Houdini immediately when using a sub-geometry like below, but that's now fixed. So I just tried it, it works now, except it deletes the included open polygons completely (3). But this is another existing issue with OpenSubdiv.

vinyvince
Thanks this is perfectly clear now.
Im sure Sidefx is listening and will take note

Cheers

________________________________________________________________
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
 http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
(Available in few days, please contact me if interested)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB