Jump to content

How would one get xyzdist of surface based on range of vector directions


Human_vX

Recommended Posts

I hope to get the nearest position on a surface or line that is somewhere along the inverse normal, searching in a range of angles (a cone if you will).

If this can be done in vex that'd be ideal (I've messed around sop loops and group stuff but that as expected gets very slow).

Too aid with the question there is an expertly drawn diagram.

whatdoexamplepaint.png

Link to comment
Share on other sites

Hi,

You can fire rays for each given point within a cone in the opposite direction of the point normal:

image.thumb.png.842b689e639b846abed6eb5ac4b51c65.png

Here is the VEX code:

int numrays = chi("numrays");
float maxangle = radians ( ch("maxangle") );
float maxdist = ch("maxdist");
int visualize = chi("visualize");

vector phit = 0;
vector uvhit = 0;
float nearestdist = 1e32;
vector nearestp = @P;

for ( int i = 0; i < numrays; ++i )
{
    vector2 u = rand ( i + 4523.4376 + @ptnum + ( @ptnum + 1 ) * 54.21 );
    vector dir = sample_direction_cone ( -@N, maxangle, u );
    
    if ( visualize )
    {
        int pt = addpoint ( 0, @P );
        setpointattrib ( 0, "N", pt, dir );
    }
    
    int pr = intersect ( 1, @P, dir * maxdist, phit, uvhit );
    if ( pr != -1 )
    {
        float dsq = distance2 ( phit, @P );
        if ( dsq < nearestdist )
        {
            nearestdist = dsq;
            nearestp = phit;
        }
    }
    
    if ( visualize )
    {
        int pt = addpoint ( 0, phit );
        setpointattrib ( 0, "P", pt, phit );
    }
}

@P = nearestp;

 

  • Like 5
Link to comment
Share on other sites

  • 1 month later...

Or if don't have too many points for which you need to process this, you could also make a preparation wrangle, to build primitive groups, for each point, of what they are allowed to connect to:
(I wrote this blind, but it should work.... more or less.. xD)

//running over the collision primitives:
//second input being the points you want to snap later

int nOpts = npoints(1), i;
float maxAngle = radians(chf("maxConeAngle"));
vector oP, oN;
string grp;

for(i = 0 ; i < nOpts; i++)
{
	oP = point(1, "P", i);
  	oN = point(1, "N", i);
  
  	oP = normalize(oP - v@P); // get direction vector from the current primitive to each point
  	grp = sprintf("pt%d_primSelection", i);
  	setprimgroup(0, grp, @primnum, acos(dot(oP, oN)) < maxAngle);
}

then in your actual wrangle you can just use something like:

//running over your points
//second input your collision geometry with the created groups

string grp = sprintf("pt%d_primSelection", @ptnum);
v@P = minpos(1, grp, v@P);

If your collision geometry is extremely high-res or you are testing a very large amount of points, this solution might be less scalable than ray casting.
If your collision geometry is splines, instead of polygons, you probably have to split them into individual segments, for example with a carve node.

if you want your check to be more strict, you could also choose to make a point groups instead of prim groups, and then promote them to primitive groups with the "only include when whole thing is selected something something" :P

 

Edited by acey195
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...