Find world position of a Texture2D

How to find the position of a texture2D in world space?

My case is … a texture’s colour alpha is compared to an objects A texture colour alpha when this object is hit. I want to position of where this happened (from pixels)

What I have is a RaycastHit.textCoord of object A which I think may be used to find the position. But the texture coordination is then changed a bit, this is why I cannot use the hitpoint mentioned earlier.

What I need is somewhat a way to change pixels back to RaycastHit.textCoord which in turn it is changed to a position. But I guess this way is not possible, I don’t know.

Below is a piece of code relevant

function CheckAlpha (texture:Texture2D, pixelUV:Vector2, directionCheck:boolean, other:Collider):boolean {

//pixelUV is the RaycastHit.textCoord
    	var uvX:int = pixelUV.x * texture.width;
    	var uvY:int = pixelUV.y * texture.height;
    	
    	if (directionCheck) {

//This loop will pick up the pixel (a new uvY) from the
texture which is not transparent, starting from the bottom
till the uvY. If a pixel is picked up, another texture is
placed around the uvX and the new uvY. How can I get world
coordinates of this other texture?
    		for(var i = texture.height; i >= uvY; i--){
    		
    			if(texture.GetPixel(uvX, i).a != 0.0)
    				return ApplyTexture(texture, uvX, i, shipDamageTexture, shipHoleTextureArray);
    		}
    }

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*_

Converted to C#

       /// <summary>
        /// Convert UV coordinate to World Coordinate
        /// </summary>
        /// <param name="uv">UV Coordinate</param>
        /// <param name="mesh">Mesh</param>
        /// <param name="transform">Transform of gameobject where mesh resides</param>
        /// <returns>World Coordinate</returns>
        public Vector3 UvTo3D(Vector2 uv, Mesh mesh, Transform transform)
        {
            int[] tris = mesh.triangles;
            Vector2[] uvs = mesh.uv;
            Vector3[] verts = mesh.vertices;
            
            for (int i = 0; i < tris.Length; i += 3)
            {
                Vector2 u1 = uvs[tris*];      // get the triangle UVs*

Vector2 u2 = uvs[tris[i + 1]];
Vector2 u3 = uvs[tris[i + 2]];

// Calculate triangle area - if zero, skip it
float a = 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

float a1 = Area(u2, u3, uv)/a;
if (a1 < 0)
continue;

float a2 = Area(u3, u1, uv)/a;
if (a2 < 0)
continue;

float a3 = Area(u1, u2, uv)/a;
if (a3 < 0)
continue;

// Point inside the triangle - find mesh position by interpolation…
Vector3 p3D = a1* verts[tris_] + a2 * verts[tris[i + 1]] + a3 * verts[tris[i + 2]];_

// return it in world coordinates:
return transform.TransformPoint(p3D);
}

// Point outside any uv triangle
return Vector3.zero;
}

///


/// Calculate signed triangle area using a kind of “2D cross product”:
///

///
///
///
/// Area
private float Area(Vector2 p1, Vector2 p2, Vector2 p3)
{
Vector2 v1 = p1 - p3;
Vector2 v2 = p2 - p3;
return (v1.x * v2.y - v1.y * v2.x) / 2;
}