- Home /
Finding the polygon/face your'e currently looking at?
So Im trying to find the face of the object instance im looking at but I cant work out how to go about doing it
ive got a script attached to my object so OnMouseEnter get the transform of it and make it the selected object then OnMouseExit reset the the selected object to null
say if i my mouse cursor was over the top face/polygon how would i find that out?
raycasting? (not educated on raycasting but i did a little search and im guessing its this)
would someone be able to explain the logic or maybe give me a quick example or a link to a tutorial
all help appreciated
thanks!
Answer by Flynn · Jan 18, 2011 at 05:56 AM
Hi there. :)
An explanation of raycasts: Raycasts are systems that when called are given a number of variables. One of these variables is actually a reference, and what handles the data returned by the hit. Physics.Raycast returns a bool statiing if it hit, but it is also fed a variable of type RaycastHit, which after the raycast, is fed with data.
Raycasts can come in two forms.
Form one is calling Physics.Raycast, and passing the directional values there. Form two is pre-creating the raycast, and then calling Physics.Raycast, replacing all of the inputs with parameters from the Ray object.
You want the latter. Why?
There exists a function called ScreenPointToRay, which creates an object of type Ray that can be used in Physics.Raycast. When this ray gets fired, it will hit exactly whatever the camera is looking at (Or what your mouse is over, if you feed it the mouse's position).
RaycastHit contains a variable, which is the index of the tri on the mesh you hit. I believe that is what you are looking for.
Putting this all together [Based on examples in the doc]:
c#
using UnityEngine; using System.Collections;
public class DoMyRay : MonoBehaviour { void Update() { //This generates our ray. We input the positions x, and y, as screen height and width divided by two to send a ray towards whatever the //screen center is viewing. //Camera.main is a static var, capable of being accessed from any code without references. Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2, Screen.height/2, 0));
//This defines a RaycastHit object. Its information is filled out if Physics.Raycasthit actually hits.
RaycastHit hit = new RaycastHit();
//This uses the ray's parameters to call physics.raycast. Mathf.Infinity is the distance the raycast will go before giving up. [Don't worry, distances of this size cause no lag].
//We specify 'out' as that is just how c# rolls. [It goes into variable references, ETC. All of this is automagic in JS]
if (Physics.Raycast(ray.origin, ray.direction, out hit, Mathf.Infinity))
{
//This is not necissarry. All it does is visualize in 3D what the camera is looking at. hit.Distance is how far the raycast got before
//Hittign soemthing. It functions as how far away we will draw the ray.
Debug.DrawRay(ray.origin, ray.direction * hit.distance, Color.red);
//This is the index of the tri the camera is looking at:
int ind = hit.triangleIndex;
Debug.Log("Hit tri index is " + ind*3);
}
}
}
JS:
function Update() { //This generates our ray. We input the positions x, and y, as screen height and width divided by two to send a ray towards whatever the //screen center is viewing. //Camera.main is a static var, capable of being accessed from any code without references. var ray : Ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2, Screen.height/2, 0));
//This defines a RaycastHit object. Its information is filled out if Physics.Raycasthit actually hits.
var hit : RaycastHit = new RaycastHit();
//This uses the ray's parameters to call physics.raycast. Mathf.Infinity is the distance the raycast will go before giving up. [Don't worry, distances of this size cause no lag].
if (Physics.Raycast(ray.origin, ray.direction, hit, Mathf.Infinity))
{
//This is not necissarry. All it does is visualize in 3D what the camera is looking at. hit.Distance is how far the raycast got before
//Hittign soemthing. It functions as how far away we will draw the ray.
Debug.DrawRay(ray.origin, ray.direction * hit.distance, Color.red);
//This is the index of the tri the camera is looking at:
var ind : int = hit.triangleIndex;
Debug.Log("Hit tri index is " + ind * 3);
}
}
An explanation to meshes:
Meshes in Unity are defined by a number of data arrays. These arrays are:
UV1 -- Used for texture mapping. Very confusing, I won't bother explaining.
UV2 -- Works the same way, used for lightmappy
Vertices -- Used to define geometry "waypoints" which faces snap to
Triangles -- Defines tries and which vertices they snap to.
Vertices -- Vertices are 3D points in space which cannot be seen. They define the waypoints that faces -- AKA tris -- CAN cover. Most 3D modeling applications allow faces to be quads (four-side faces) but in Unity they all have to be three sided (tris).
mesh.triangles is a power of three array. That means that the number of elements in this array will always be devisable by three. Why is it this way?
Every three elements in the tris array belong to the same tri. To visualize it:
In a cube:
Vertices: Index :Value 0 :Vector3(0,0,0)
1 :Vector3(1,0,0)
2 :Vector3(0,1,0)
3 :Vector3(1,1,0)
4 :Vector3(0,0,1)
5 :Vector3(1,0,1)
6 :Vector3(0,1,1)
7 :Vector3(1,1,1)
These are points in 3D space relative to the object using the mesh.
Tris (This is a shortened version, does not visuallize WHOLE cube):
This specifies a face that spans the gap between the vertex positions at indexes 0, 1, and 2:
Index: Value
0: 0
1: 1
2: 2
IF a mesh were to have two tris making a quad, it would look like this:
0: 0
1: 1
2: 2
3: 3
4: 1
5: 2
Assuming the verts were layed out properly. Each of those values in the triangles array points to a vertice in the vertices array. It it's self points to a place in 3d space. Every three elements in the tris array represents the pointers to the three vertices in each tri.
I was wrong in thinking that hit.triangleIndex directly pointed to one of these indexes. Instead, it points to the tris as a whole. So, if the index were 0, it would point to triangle indexes 0, 1, 2. If it is 1, it woudl point to 3, 4, and 5. If it were 2, it would point to 6, 7, and 8.
Likewise, multiplying the hit index by 3 allows you to gather the precise index of the first element in the tri ti points to. For instance, because the returned value 2 points to 6, 7, and 8, multiplying 2x3 returns 6, which is the first index it points to.
Explanation to meshes in general:
3D geometry works similarly. When you model something, you create vertices [which in the modeler you can see.] You then select various vertices and tell the mesh a face exists between them. When you do that, you are basically making a triangle, and the three corners on that triangle touch the three vertices you chose.. Just in 3D.
Unity's arrays are just optimized ways of expressing those decisions in 3D modeling. A square face is just two triangles working together to define a square.
Ok so I semi-understand that, how would i go about applying it say if top face of a cube is what centerscreen is looking at do this Im looking into raycasting now, thanks for you help so far flynn!
THe top face of a cube is two different tris. You could compare the indexes of the two top-face tris with ind to see if what you are hitting is the top of the cube. Unfortunately deter$$anonymous$$ing these indexes is simply a matter of trial and error. However, I can enlighten you to how tris work:
Each tri has three elements in an array called "triangles" [Accessed via mesh.triangles]. Unfortunately, I slipped up and used mesh.tris (which doesn't exist) ins$$anonymous$$d of mesh.triangles.
hit.triangleIndex returns the first of the three indexes of each try in mesh.triangles.
[Continuation] To figure out if a certain tri on a mesh is what is being hit, you need only check if hit.triangleIndex = firstIndexOfTri.
FirstIndexOfTri is very hard to find as it uses trial and error. However the best way to find it is to try 0, then 3, then 6, then 9, and so on. 1, 2, 4, 5, 7 and 8 are obsolete because they are not the first indexes of any tris. They are all second and third indexes.
To clarify further, each index is a reference to one of the vertices in the mesh.vertices array.
[Continuation 2] Each tri covers the space between three vertices, which is why each tri needs three elements on the array. Each one, as stated, points to a vertice in the array.
ok after applying that there were a few errors but i managed to clean it up (in ray var width is lower case, same for distance in the debug)
im guessing in the if statement "out hit" and $$anonymous$$athf.Infinity are the wrong way around, that was throwing up an error
then i debugged the tricorners and ind but ind stayed at 0, tricorners were always 1,0,3
(also changing mesh.tris to mesh.triangles just remembered)
im just using a standard unity cube, but i cant seem to get it working!
although it may have had some errors it helped me understand it more from working out a fix
Answer by Le_Revenant · Mar 31 at 09:54 AM
You can get the direction the face of an object is facing using Unity's Raycast class, example:
RaycastHit Hit;
Hit.normal; // it is a Vector3 quantity
//for X - axis :
Hit.normal.x;
//for Y - axis :
Hit.normal.y;
//for Z - axis :
Hit.normal.z;
This will only give you the direction the face in facing in world space. for example if it is facing in the positive Z direction, it will return a Vector3, (0, 0, 1) where the z value is positive.
This question is more than 10 years old and was already answered. Your answer does not even address the question asked. What's the point of posting this? The question was
Finding the polygon/face you're currently looking at?