Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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
0
Question by FaffyWaffles · Mar 01 at 01:06 PM · raycastmeshtrianglesduplicatetriangle

Odd Duplicate when selecting Triangle from Mesh (with Barycentric Selection.)

What I'm trying to do is select a specific triangle on any given mesh, so I'm using the Barycentric algorithm. However, as seen here, there is some strange behaviors and certain locations and always an Unwanted Triangle. Best guess, it has something to do with inaccurate float precision of the Vector3.


Here is the Script I'm Currently Using:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class SpecificTriangleIndex : MonoBehaviour
 {
     public Camera m_camera;
     public LayerMask layermask;
 
     public Vector3[] vertices;
     public Vector3[] normals;
     public int[] triangles;
 
     public List<int> triangleIndices = new List<int>(); ///Returned Triangle Indices -- What it thinks is selected.
     public List<Vector3> baryAllens = new List<Vector3>(); ///Position of Verticies of Returned Triangles
 
     private RaycastHit hit;
     private Transform objectHit;
     private Vector3 bary;
 
     void Update()
     {
         if (Input.GetMouseButton(0))
         {
             EobardThawne();
             Raycast();
         }
     }
     void Raycast()
     {
         Ray ray = m_camera.ScreenPointToRay(Input.mousePosition);
 
         if (Physics.Raycast(ray, out hit, layermask))
         {
             objectHit = hit.transform;
             MeshFilter meshFilter = hit.transform.gameObject.GetComponent<MeshFilter>();
             Mesh mesh = meshFilter.sharedMesh;
             vertices = mesh.vertices;
             normals = mesh.normals;
             triangles = mesh.triangles;
 
             Vector3 p = transform.InverseTransformPoint(hit.point);
             for (int i = 0; i < triangles.Length; i += 3)
             {
                 Vector3 a = vertices[triangles[i]];
                 Vector3 b = vertices[triangles[i + 1]];
                 Vector3 c = vertices[triangles[i + 2]];
 
                 bary = GetBarycentric(a, b, c, p);
                 if (InTriangle(bary))
                 {
                     triangleIndices.Add(i / 3);
                     baryAllens.Add(a + objectHit.position);
                     baryAllens.Add(b + objectHit.position);
                     baryAllens.Add(c + objectHit.position);
                 }
             }
             for (int i = 0; i < baryAllens.Count; i += 3)
             {
                 Vector3 v0 = baryAllens[i];
                 Vector3 v1 = baryAllens[i + 1];
                 Vector3 v2 = baryAllens[i + 2];
 
                 Debug.DrawLine(v0, v1, Color.green);
                 Debug.DrawLine(v1, v2, Color.green);
                 Debug.DrawLine(v2, v0, Color.green);
             }
         }
     }
 
     Vector3 GetBarycentric(Vector2 v1, Vector2 v2, Vector2 v3, Vector2 p)
     {
         Vector3 B = new Vector3();
         B.x = ((v2.y - v3.y) * (p.x - v3.x) + (v3.x - v2.x) * (p.y - v3.y)) /
             ((v2.y - v3.y) * (v1.x - v3.x) + (v3.x - v2.x) * (v1.y - v3.y));
         B.y = ((v3.y - v1.y) * (p.x - v3.x) + (v1.x - v3.x) * (p.y - v3.y)) /
             ((v3.y - v1.y) * (v2.x - v3.x) + (v1.x - v3.x) * (v2.y - v3.y));
         B.z = 1 - B.x - B.y;
         return B;
     }
 
     bool InTriangle(Vector3 barycentric)
     {
         return (barycentric.x >= 0.0f) && (barycentric.x <= 1.0f)
             && (barycentric.y >= 0.0f) && (barycentric.y <= 1.0f)
             && (barycentric.z >= 0.0f); //(barycentric.z <= 1.0f)
     }
 
     private void OnDrawGizmos()
     {
         Gizmos.color = Color.yellow;
         Gizmos.DrawSphere(hit.point, .01f);
 
         Gizmos.color = Color.cyan;
         foreach (int i in triangleIndices)
         {
             Gizmos.DrawSphere(FindCenter(i * 3), .01f);
             Debug.DrawLine(hit.point, FindCenter(i * 3), Color.red);
         }
     }
 
     public void EobardThawne()
     {
         //Kill Barry
         triangleIndices.Clear();
         baryAllens.Clear();
     }
 
     public Vector3 FindCenter(int i)
     {
         Vector3 v0 = transform.TransformPoint(vertices[triangles[i]]);
         Vector3 v1 = transform.TransformPoint(vertices[triangles[i + 1]]);
         Vector3 v2 = transform.TransformPoint(vertices[triangles[i + 2]]);
         Vector3 center = (v0 + v1 + v2) / 3;
         return center;
     }
 }


Any Help or Insight would be Appreciated.

Also, RaycastHit.triangleIndex doesn't work in all cases, so thats why I am pursuing this.

Comment
Add comment
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

1 Reply

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

Answer by Bunny83 · Mar 01 at 09:06 PM

You seem to use the methods I had posted over here or in the other linked post. However those methods takes "Vector2" values since they were meant to be used to look up uv coordinates, not spatial position data which is of course 3d and not 2d. You pass in your 3d coordinates into the method where the z component is essentially dropped.


Later in the comments below my answer I've also created the Barycentric struct which I posted to the unity wiki. Unfortunately the wiki does no longer exist. However we have the wayback machine ^^. This struct has 5 different constructors. So you can use Vector2, 3, 4 values as well as a version that takes Color values. So you should be able to create baricentric coordinates from any vertex attribute, given you do have the interpolated value (i.e. the uv coordinate or the local position).

Likewise the struct has several "Interpolate" methods in order to interpolate any other vertex attribute across the triangle based on the barycentric coordinate.

Comment
Add comment · Show 2 · 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 FaffyWaffles · Mar 03 at 12:17 AM 0
Share

While your wiki and past answers have been an enormous help, I'm still a bit confused on how your "Interpolate" method does, and how to use it

avatar image Bunny83 FaffyWaffles · Mar 09 at 10:18 AM 1
Share

Sorry, I wasn't home for the last couple of days ^^. Barycentric coordinates can be seen as interpolation factors in 2d space based on the triangle they belong to. They work similar to how the interpolation factors t and (1-t) work for a normal 1d lerp interpolation. You can simply interpolate any vertex attribute across the triangle. Vertex attributes are any attributes that are associated with vertices. This includes the position in 3d space, the uv coordinates in 2d space, the associated vertex color and even the vertex normal. Each vertex has one distinct value of those. Our barycentric coordinate represents a point in between those vertices. So by providing the 3 values of a certain vertex attribute we can calculate the interpolated value between the vertices according to the barycentric coordinate.


So you can use the different constructores of the Barycentric struct to calculate the barycentric coordinates based on a known value (like the position of a point inside a triangle and the 3 vertex positions) and then use the resulting struct to calculate any other interpolated vertex attribute at that point.


The original question I've linked asked about calculating the barycentric coordinate of a known 2d UV coordinate and compare that to the 3 UV coordinates of a triangle. If the requested point is inside a triangle we can then use the 3 vertex positions and the barycentric coordinates to calculate the position in 3d space. However you have a position (the hit.point value) so you have to use the vertex positions to calculate the barycentric coordinate of the hit point in relation to a certain triangle.


An important property of a barycentric coordinate is that the sum of the 3 factors will always add up to 1.0. A barycentric point is inside the triangle when all 3 factors are within a range of 0 <= v <=1. Though for exampe (-5, 9, -3) would be a valid barycentric coordinate (it sums to 1.0), but it would lay outside the triangle but in the same plane as the triangle.


Keep in mind that when calculating the barycentric coordinate from a point in 3d space and the vertex positions, the point has to be on the surface / plane of the triangle. passing in a point that is above / below the triangle would give you a wrong coordinate. You also have to be careful with degenerate triangles (triangles with no area, so at least two of the vertices have the same position) as it's not possible to calculate a meaningful coordinate for such triangles.

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

196 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 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 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 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 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 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 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 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 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 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 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 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 avatar image avatar image avatar image avatar image

Related Questions

How to Detect All Mesh Triangles Within a Given Area 2 Answers

How to find connected mesh triangles? 2 Answers

shooting raycast from each triangle on mesh and change its texture 0 Answers

Calculating triangles of a vertex array 0 Answers

instanced mesh won't collide with raycast anymore 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