Jump to content

Smooth direction to surface?

Recommended Posts

Trying to replicate something form XSI in Houdini but need to get the a direction from a point to a surface (not shortest direction). To illustrate here's a circle which points are being raycasted onto the blocky shape in the middle along the desired direction.


Any easy way to calculate this?

For comparison minpos() would produce this:


The direction I'm after kind of reminded me, VDB gradient, but this is a wasteful and imprecise route, imo. 

Also reminds me of a the line between the point and a point sampled through the closest position on the surface and the corresponding location on the straight skeleton

Dunno how to both calculate the straight skeleton and sample a corresponding position from surface->skeleton.





Edited by probiner

Share this post

Link to post
Share on other sites

just turn it into a wall (extrude X amt, move up/down half X) for ray ?


(a bit unclear if you have ALREADY done this or not...but thought I'd throw it up anyway...on closer inspection of your fig 1. some of the normals ain't perpendicular ?)

Edited by Noobini
  • Like 1

Share this post

Link to post
Share on other sites

For the target polyexpand produces a straight skeleton, triangulate2d converts it to convex triangles, divide (remove shared edges) and resample (subdivision curves) turns them into a smooth outline curve.

As you suggested I used minpos() to get the directions from the circle points towards the target:

vector dir = minpos(1, @P) - v@P;

and intersect_all() would be for shooting rays from the outer circle to the original input shape:

int ray = intersect_all(2, @P, dir, pos, prim, uvw, tol, -1);

Hit play to see how it performs on different inputs.



Edited by konstantin magnus
added screenshot
  • Like 3

Share this post

Link to post
Share on other sites


Konstantins approach is already very nice. Perhaps this paper ( https://www.cc.gatech.edu/~jarek/papers/BallMorph.pdf ) may help you as well [it is about morphing between curves]. I've tried to reimplement this for myself, but my file is very raw (buggy) and no direct solution for your problem but you can take as inspiration for sure.



  • Thanks 1

Share this post

Link to post
Share on other sites

Thanks for feedback guys
While the example I gave is 2D, I was aiming to apply it in 3D. I already RFE this, but basically I'm after the third panel.


But all the things you guys posted are quite interesting :)
@Aizatulin, you went deep! :D That looks great! Sort of think it deserves attention and its own thread. Many thanks!
@konstantin magnus basically I'm after the correct direction to use in intersect() like you did, but for 3D, there's no way yet to generate the straight skeleton for 3D, the same way Polyexpand does for 2D. Thanks.
@Noobini Not the direction I'm after, but I learned from that scene, thanks!

I found an issue with xyzdist to start with: It doesn't care about incidence to the prim it returns when there's several with same dist; just returns the one with the lowest index. Also REF'ed


Edited by probiner

Share this post

Link to post
Share on other sites

It's interesting, what is being computed is unclear. Do you have access to that software and can you tell us the name of that operator.. Maybe there is some online documentation that explains what is actually computed ?

Or .. can you can post a few other test case for this operator ? Tricky ones for example (non convex curves, extreme cases.. )

I'm not sure it target curve (polygon) is resampled in order to add more points as it gets closer to the circle, or maybe it's a side effects of casting more rays on a segment that is closer to a section of the circle. Also, the normals don't seem to be involved.

The rays also don't look like they're aiming at an associated (computed from the straight skeleton or something) point, as you can see almost parallel rays in the top left quadrant. My guess is that they are minimizing the sum of several functions, which include the length of the ray, the difference of the ray angle on the target between consecutive (or some kernel function) points, smooth resampling of the target

I tried to minimize distance to target but it doesn't feel the same




Share this post

Link to post
Share on other sites

Hello @AntoineSfx

That's Softimage Closest Location: Closest Smoothed Surface in ICE. Very useful for cage deform.

I think I nailed this one, by stop focusing on trying to compute the correct direction from on xyzdist/primuv resulting normal. I'm sure there's a way and I wish I could do it for simplicity but the math it's just not coming to me...
So what I did was to loop for each point, select only the candidate prims from the reference mesh that could be the closest primitive,  "extrude" them along their point normals until they are coplanar with the point. Then check which prim is the point inside of.
If you already know the right prim, maybe the problem can be resumed by finding the ray direction from the primitive's point normals. What I did is on the right, extruded to make it coplanar, xyzdist() on the extruded prim, and applied the returned prim and uvw with primuv() on the original primitive. It's like I'm dividing the 3D space into extrusions of the reference mesh and see inside of which extrusion the point is in.


The only advantage with this is that in the process of finding the correct prim, I also right away get the corresponding uvw, hence a complete "location". On the other hand a bunch of SOPS and Loop block are required.


As for the initial shape it looks, like so:

I added all this info to the RFE. Hopefully in the future we will just need to type a function in VEX. Would be cool since what I came up with is inherently slow for heave geo :(

Scene file here: https://jmp.sh/bELWJdX

Edited by probiner
  • Like 4

Share this post

Link to post
Share on other sites

to me it looks like Closes Surface (Smoothed) is a Minpos from your geo to the subdivided (smoothed) version of the target geo, then just intersect original target geo in direction towards that position 

since at the moment xyzdist/minpos can't represent geo as subd limit surface natively, you have to use subdivide sop to create such representation, so to get really smooth results you either  subdivide a lot

or subdivide enough and apply a little post smooth/reproject step at the end

that being said I wish xyzdist, intersect and all similar function could trace against subd limit surfaces 

Share this post

Link to post
Share on other sites

@anim I threw everything and the kitchen sink at this one, from subdividing both meshes, to bluring the the direction from minpos(1,@P) - @P, from iterating (minpos + Smoothing)... Ultimately I knew this had to be made incredibly simple and fast and all of those were convoluted and didn't actually work. As for sub-diving the mesh; either I'm dealing with a NURBS surface or subdividing will only make the issues visible with minpos of a smaller resolution, not actually fix them.


I really tried to grasp what would be the math to obtain the smooth ray dir or P'' from the available data, P, P', N', Prim P and N, PrimPoints P and N. But couldn't come up with something.

The "extrusion" bit was definitely revealing. I'm sure there's a much more elegant way to go about it than actually having a primitive "extruded".

I think you're right, it would be indeed nice to be able to use such functions on a SubD surface. RFE it!


Edited by probiner

Share this post

Link to post
Share on other sites

I gave this another stab to this, last one to the right:


Here's the way I'm going about it.

- Set point normals and prim normals in the target mesh.
- For each point in the source mesh, project each polygon of the source mesh along the point normals to a plane (made of the source point and respective polygon normal).
- Check if the point is inside this projected poly. It might be inside of more than one and I'm yet to grasp the best way to weed out the correct one. I find edge cases to be problematic so I added a threshold.
- After the belonging poly is assessed, find the relative position in the projected polygon onto the original one, and there's the smooth projection of the point onto the target mesh.
At the moment I'm having issues with this last step, because I'm having to actually build the belonging projected poly and use xyzdist() on it to then use the resulting prim/uvw on the original poly with primuv(). I would save computation if I could get the barycentric coordinated of a point relative to a polygon. With tris it's easy, but the interpolation is not accurate.


This doesn't work very well with disconnected polygon islands since the space splitting these extrusions do does not work great if the target mesh has islands self intersecting and there's not way for the point normals to account for that.

Anyways let me know if someone looked into this warping before that would give some independence from xyzdist(). Seems very re-usable.



Edited by probiner

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now