EDITED ANSWER: FIND 3D POSITION OF A GIVEN UV POINT
Ok, so you want to find the 3D position of a given texture element in the mesh. You’re lucky: I answered recently a question about triangle interpolation, and found all the geometry needed in your case.
The basic idea is: given the UV coordinates of some texture point, iterate through the triangles until you find the one that contains it, then interpolate the triangle vertices to find the 3D point in the mesh; since mesh coordinates are in local space, you must also convert it to world space with transform.TransformPoint.
In order to check whether the point lies inside a given triangle, you can calculate the [barycentric coordinates][2] of the UV point: if any of them is negative, the point is outside the triangle. If the point is inside the triangle, the interpolation is incredibly easy to do because all it needs is the barycentric coordinates we’ve just calculated: just sum the triangle vertices multiplied by the respective barycentric coordinates, then apply TransformPoint to convert the resulting position to world space.
The function UvTo3D below does this: it must be attached to the mesh, and you must pass to it the UV coordinates of the desired point. The function gets the triangles, vertices and uvs of the mesh and looks for the point in the UV map. If the point lies inside one or more triangles, the 3D position in the first triangle found is returned; if not, the function returns Vector3.zero:
function UvTo3D(uv: Vector2): Vector3 {
var mesh: Mesh = GetComponent(MeshFilter).mesh;
var tris: int[] = mesh.triangles;
var uvs: Vector2[] = mesh.uv;
var verts: Vector3[] = mesh.vertices;
for (var i: int = 0; i < tris.length; i += 3){
var u1: Vector2 = uvs[tris*]; // get the triangle UVs*
var u2: Vector2 = uvs[tris[i+1]];
var u3: Vector2 = uvs[tris[i+2]];
// calculate triangle area - if zero, skip it
var a: float = Area(u1, u2, u3); if (a == 0) continue;
// calculate barycentric coordinates of u1, u2 and u3
// if anyone is negative, point is outside the triangle: skip it
var a1: float = Area(u2, u3, uv)/a; if (a1 < 0) continue;
var a2: float = Area(u3, u1, uv)/a; if (a2 < 0) continue;
var a3: float = Area(u1, u2, uv)/a; if (a3 < 0) continue;
// point inside the triangle - find mesh position by interpolation…
var p3D: Vector3 = a1verts[tris_]+a2verts[tris[i+1]]+a3verts[tris[i+2]];_
_// and return it in world coordinates:_
return transform.TransformPoint(p3D);
_}_
_// point outside any uv triangle: return Vector3.zero*_
return Vector3.zero;
}
// calculate signed triangle area using a kind of “2D cross product”:
function Area(p1: Vector2, p2: Vector2, p3: Vector2): float {
var v1: Vector2 = p1 - p3;
var v2: Vector2 = p2 - p3;
return (v1.x * v2.y - v1.y * v2.x)/2;
}
If you want to know more details about triangle interpolation, take a look at the [question mentioned above][2].
ORIGINAL ANSWER: COLOR PICKER, NOT WHAT THE OP ACTUALLY WANTED
If you’re looking for a kind of “color picker” that gets the original texture color of the point under the cursor, this can be done - but with several restrictions:
1- The clicked object must have a mesh collider to return a valid UV pair in the RaycastHit structure;
2- The texture must have Read/Write enabled in the Import Settings (click the texture in the Project view to show its Import Settings, then select Texture Type = Advanced and mark Read/Write enabled);
3- A single pixel in the screen may correspond to lots of texture elements, thus the UV pair returned by RaycastHit may not be precise enough to detect small areas in the object.
The script below gets the texture color of the object point under the mouse, and you can compare it to whatever you want. It’s based on the [RaycastHit.textureCoord][1] example, and only works for mesh colliders and textures marked as read/write. Attach it to the camera:
function Update () {
var ray = camera.ScreenPointToRay(Input.mousePosition);
var hit: RaycastHit;
if (Physics.Raycast(ray, hit)){
var meshCollider = hit.collider as MeshCollider;
if (!meshCollider) return; // only works for mesh colliders
var renderer: Renderer = hit.collider.renderer;
if (renderer && renderer.material && renderer.material.mainTexture){
var tex : Texture2D = renderer.material.mainTexture;
var pixelUV = hit.textureCoord;
pixelUV.x *= tex.width;
pixelUV.y *= tex.height;
var color: Color = tex.GetPixel(pixelUV.x, pixelUV.y);
// now you’ve got the color of the original texture
// at the hit point - compare it to what you want
}
}
}
_[1]: http://docs.unity3d.com/Documentation/ScriptReference/RaycastHit-textureCoord.html*_
_[2]: http://answers.unity3d.com/questions/383804/calculate-uv-coordinates-of-3d-point-on-plane-of-m.html*_