Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by sparkzbarca · Mar 26, 2013 at 08:40 AM · mathtrigonometry

nearest point on mesh?

So this could be a long one.

Basically my issue is this

alt text

Now what i'm doing is rotating an object so the 2 nearest faces of an object are parallel.

the issue is when you have a sphere basically against a non sphere. Imagine if you rotated this object on the left, the hexagon, so that the face of it THE SOLID LINE goes though, was parallel. You would get a parallel face. However if you casted from the object to the center of the black line object. you'd find that the rotation had basically made it so a new face had rotated around.

Basically everytime you rotate the object you get a new face to rotate.

The reason is because your not casting directly out your casting slightly up to the center of the object.

really if you casted to the nearest point of the object it'd work.

But i've no idea how to do that.

pretty much if the face of an object is long enough (the angle between each face is big enoguh)

it's not an issue.

it find the right face even casting at an angle.

but for shallow angles it finds a new face everytime.

I'd like to cast from the center of object hexagon

to the nearest point on another ojbect.

but not the nearest vertex. cause thats the point at the top of the line or maybe at the bottom.

the nearest point in space.

can it even be done?

the line of course is actually a triangle (viewed side on, its actually a 3d triangle)

i can find the nearest triangle i'm confident but can i use some averaging of the 3 points of the trinagle to find the nearest point.

like in this case really for this 2d view what i want is to cast direciton (x,y)

where x = object x - other object x y = object y

i want to keep the same height I'm not sure how to translate this into 3 dimensions however.

example.png (6.8 kB)
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image sparkzbarca · Mar 26, 2013 at 08:44 AM 0
Share

is it perhaps the x and z of the second objects position but the height of the first objects that will go in the direction of the closest point?

3 Replies

· Add your reply
  • Sort: 
avatar image
6
Best Answer

Answer by whydoidoit · Mar 26, 2013 at 09:23 AM

Ok so here's the description of how to do that.

  1. Iterate through each triangle in the mesh

  2. Get the normal of the plane on which the triangle lies

  3. Calculate the nearest point on that plane (using the normal above)

  4. Work out the barycentric coordinates of the point within the triangle (see the third post here)

  5. Clamp each barycentric coordinate between 0 and 1 which forces the point to be just within the triangle if in fact it originally lay outside. alt text

  6. Convert the barycentric coordinates to world coordinates

  7. Store the point if the sqrMagnitude of the distance to the start point is less than the current best

  8. Loop until all triangles have been considered

  9. You have the closest point

This is some code I wrote a while ago to do it, can't remember if this is the final version though!

You'd use it like this:

 var closestPointCalculator = new BaryCentricDistance(someMeshFilter);

  var result = closestPointCalculator.GetClosestTriangleAndPoint(someVector3);
  var closest = result.closestPoint;

Here's the script

 using UnityEngine;
 using System.Collections;
 using System.Linq;
 
 public class BaryCentricDistance {
     
     public BaryCentricDistance(MeshFilter meshfilter)
     {
         _meshfilter = meshfilter;
         _mesh = _meshfilter.sharedMesh;
         _triangles = _mesh.triangles;
         _vertices = _mesh.vertices;
         _transform = meshfilter.transform;
     }
     
     public struct Result
     {
         public float distanceSquared;
         public float distance
         {
             get
             {
                 return Mathf.Sqrt(distanceSquared);
             }
         }
         
         public int triangle;
         public Vector3 normal;
         public Vector3 centre;
         public Vector3 closestPoint;
     }
     
     int[] _triangles;
     Vector3[] _vertices;
     Mesh _mesh;
     MeshFilter _meshfilter;
     Transform _transform;
     
     public Result GetClosestTriangleAndPoint(Vector3 point)
     {
         
         point = _transform.InverseTransformPoint(point);
         var minDistance = float.PositiveInfinity;
         var finalResult = new Result();
         var length = (int)(_triangles.Length/3);
         for(var t = 0; t < length; t++)
         {
             var result = GetTriangleInfoForPoint(point, t);
             if(minDistance > result.distanceSquared)
             {
                 minDistance = result.distanceSquared;
                 finalResult = result;
             }
         }
         finalResult.centre = _transform.TransformPoint(finalResult.centre);
         finalResult.closestPoint = _transform.TransformPoint(finalResult.closestPoint);
         finalResult.normal = _transform.TransformDirection(finalResult.normal);
         finalResult.distanceSquared = (finalResult.closestPoint - point).sqrMagnitude;
         return finalResult;
     }
     
     Result GetTriangleInfoForPoint(Vector3 point, int triangle)
     {
         Result result = new Result();
         
         result.triangle = triangle;
         result.distanceSquared = float.PositiveInfinity;
         
         if(triangle >= _triangles.Length/3)
             return result;
         
         
         //Get the vertices of the triangle
         var p1 = _vertices[ _triangles[0 + triangle*3] ];
         var p2 = _vertices[ _triangles[1 + triangle*3] ];
         var p3 = _vertices[ _triangles[2 + triangle*3] ];
         
         result.normal = Vector3.Cross((p2-p1).normalized, (p3-p1).normalized);
         
         //Project our point onto the plane
         var projected = point + Vector3.Dot((p1 - point), result.normal) * result.normal;
         
         //Calculate the barycentric coordinates
         var u = ((projected.x * p2.y) - (projected.x * p3.y) - (p2.x * projected.y) + (p2.x * p3.y) + (p3.x * projected.y) - (p3.x  * p2.y)) /
                 ((p1.x * p2.y)  - (p1.x * p3.y)  - (p2.x * p1.y) + (p2.x * p3.y) + (p3.x * p1.y)  - (p3.x * p2.y));
         var v = ((p1.x * projected.y) - (p1.x * p3.y) - (projected.x * p1.y) + (projected.x * p3.y) + (p3.x * p1.y) - (p3.x * projected.y))/
                 ((p1.x * p2.y)  - (p1.x * p3.y)  - (p2.x * p1.y) + (p2.x * p3.y) + (p3.x * p1.y)  - (p3.x * p2.y));
         var w = ((p1.x * p2.y) - (p1.x * projected.y) - (p2.x * p1.y) + (p2.x * projected.y) + (projected.x * p1.y) - (projected.x * p2.y))/
                 ((p1.x * p2.y)  - (p1.x * p3.y)  - (p2.x * p1.y) + (p2.x * p3.y) + (p3.x * p1.y)  - (p3.x * p2.y));
         
         result.centre = p1 * 0.3333f + p2 * 0.3333f + p3 * 0.3333f;
         
         //Find the nearest point
          var vector = (new Vector3(u,v,w)).normalized;
            
 
         //work out where that point is
         var nearest = p1 * vector.x + p2 * vector.y + p3 * vector.z;    
         result.closestPoint = nearest;
         result.distanceSquared = (nearest - point).sqrMagnitude;
         
         if(float.IsNaN(result.distanceSquared))
         {
             result.distanceSquared = float.PositiveInfinity;
         }
         return result;
     }
     
 }



point.png (10.4 kB)
Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image sparkzbarca · Mar 26, 2013 at 12:14 PM 0
Share

im going to mark this correct.

I'm going to try first to see if it's close enough to the truth casting to the center but then whatever face i hit on the second object, casting again but this time to the inverse normal direction of the face.

Basically if i find the nearest face and cast in the inverse normal direction i think it'll work.

avatar image sparkzbarca · Mar 26, 2013 at 12:17 PM 0
Share

but i will remember this, mostly i don't wnat to use barycentric co-ordinate cause i dont' understand it except that it is the center of mass, and i get that but when i did a debug.drawray and drew from the hit objects barycenter to the hit planes normal direction the barycenter was moving around which i don't understand cause i would have though the center of mass stayed constant and basically if i use that i'm going to have to spend an hour at least wrapping my head around what it means REALLY and what the result is "roughly" in my head of a barycenter calculation.

avatar image whydoidoit · Mar 26, 2013 at 12:33 PM 0
Share

Ok you aren't using the barycentre you are using barycentric coordinates because clamping between 0 and 1 on each axis gives you a point inside the triangle - it's what barycentric coordinates are good for.

alt text

point.png (10.4 kB)
avatar image whydoidoit · Mar 26, 2013 at 12:51 PM 0
Share

I've updated the answer with example code

avatar image Gottn · Apr 29, 2013 at 08:35 AM 0
Share

What are you using "public float distance" for?

Show more comments
avatar image
0

Answer by matfrem · Sep 10, 2013 at 09:41 PM

There's an error. You need to replace "`w = Mathf.Clamp01(w);`" by "`w = 1.0f - u - v;`" to keep the barycentric coordinates normalized.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Bloxard · Apr 18, 2014 at 06:21 PM

I know this is an old post, but I just want to correct this. You cannot find the nearest point on the triangle in barycentric coordinates like this.

//Find the nearest point

var vector = (new Vector3(u,v,w)).normalized;

If is true that if u>0 and v>0 and u+v<1.0 then the point is inside the triangle, but this doesn't mean that the clamped point is the closest point on the triangle.

This code above will give you a rough estimate at best.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

16 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Define circle using 3 points 0 Answers

How can I launch a ball given an angle in degrees and a magnitude? 2 Answers

clamp rotation by mouse direction 0 Answers

Math question, angles and magnitude stuff 2 Answers

Calculate mid angle position based on three points 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges