Search Unity

Help Wanted Reading a texture - how to find uv coordinate of texel using GetPixel?

Discussion in 'General Graphics' started by MMeyers23, Feb 9, 2021.

  1. MMeyers23

    MMeyers23

    Joined:
    Dec 29, 2019
    Posts:
    73
    I need to find the uv coordinates of a white pixel on a texture. I succeeded in making a script, thanks to this forum:

    https://answers.unity.com/questions...ure2d.html?childToView=1812988#answer-1812988)

    which returns the world position of a texture's uv. In other words, an object that has a texture applied to it exists in the scene, and if I feed a UV coordinate (say 0.5,0.5) into the script, another object will move to the world position at which that UV coordinate exists on the first object (in this case the center of the texture).

    https://giphy.com/gifs/AJagUnwaVy9g6qqYtd

    here you can see me using the script - I adjust the value for u and v and the cube moves correspondingly to that uv position on the plane object.

    The intended purpose is to move the cube to the location in world space where a WHITE PIXEL exists on the plane. The only thing I need is to look up where the white pixel exists in UV space. I thought I found a solution here: https://answers.unity.com/questions/1246324/get-color-coordinate-from-the-texture-and-convert.html

    namely, the line: var point = new Vector2(index % w, index / w) - new Vector2(0.5f/w, 0.5f/h);

    this should give me the coordinates (u,v) where the GetPixel color array included a pixel that was the designated color. However, when I incorporated this equation into the previous script it did not work. The gameobject always moves the world position Vector3.zero. What is wrong with my script?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class pixelworldposition : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     public GameObject cube;
    9.  
    10.     [SerializeField]
    11.     Color testcolor;
    12.     [SerializeField]
    13.     Texture2D Texture;
    14.  
    15.     Vector3 ColorToUvTo3D(Color Targetcolor)
    16.     {
    17.         Mesh mesh = GetComponent<MeshFilter>().mesh;
    18.         int[] tris = mesh.triangles;
    19.         Vector2[] uvs = mesh.uv;
    20.         Vector3[] verts = mesh.vertices;
    21.  
    22.  
    23.        
    24.         int w = Texture.width;
    25.         int h = Texture.height;
    26.  
    27.  
    28.         Color[] colors = Texture.GetPixels();
    29.         int index = -1;
    30.         for (int i = 0; i < colors.Length; i++)
    31.         {
    32.             if (colors[i] == Targetcolor)
    33.             {
    34.                 index = i;
    35.                 break;
    36.             }
    37.         }
    38.         if (index == -1)
    39.             return Vector3.zero;
    40.  
    41.  
    42.  
    43.         Vector2 uv = new Vector2(index % w, index / w) - new Vector2(0.5f / w, 0.5f / h);
    44.  
    45.         for (int i = 0; i < tris.Length; i += 3)
    46.         {
    47.             Vector2 u1 = uvs[tris[i]]; // get the triangle UVs
    48.             Vector2 u2 = uvs[tris[i + 1]];
    49.             Vector2 u3 = uvs[tris[i + 2]];
    50.             // calculate triangle area - if zero, skip it
    51.             float a = Area(u1, u2, u3); if (a == 0) continue;
    52.             // calculate barycentric coordinates of u1, u2 and u3
    53.             // if anyone is negative, point is outside the triangle: skip it
    54.             float a1 = Area(u2, u3, uv) / a; if (a1 < 0) continue;
    55.             float a2 = Area(u3, u1, uv) / a; if (a2 < 0) continue;
    56.             float a3 = Area(u1, u2, uv) / a; if (a3 < 0) continue;
    57.             // point inside the triangle - find mesh position by interpolation...
    58.             Vector3 p3D = a1 * verts[tris[i]] + a2 * verts[tris[i + 1]] + a3 * verts[tris[i + 2]];
    59.             // and return it in world coordinates:
    60.             return transform.TransformPoint(p3D);
    61.         }
    62.         // point outside any uv triangle: return Vector3.zero
    63.         return Vector3.zero;
    64.     }
    65.  
    66.     // calculate signed triangle area using a kind of "2D cross product":
    67.     float Area(Vector2 p1, Vector2 p2, Vector2 p3)
    68.     {
    69.         Vector2 v1 = p1 - p3;
    70.         Vector2 v2 = p2 - p3;
    71.         return (v1.x * v2.y - v1.y * v2.x) / 2;
    72.     }
    73.  
    74.     void Update()
    75.     {
    76.    
    77.         cube.transform.position = ColorToUvTo3D(testcolor);
    78.     }
    79. }
     
unityunity