Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 nmill99 · May 25, 2020 at 08:03 AM · meshcolortexture2dtransparencytriangle

Checking the transparency of a mesh with a piece of a texture

My program is taking in a texture and splitting the texture into randomly sized pieces that are made into 2D meshes (like a puzzle). The textures I use often contain large sections of transparency so I often end up with some puzzle pieces (meshes) where all the pixels are transparent. How do I identify if the texture mapped to the meshes UV coordinates are transparent?

I've read here: Get average color of the texture assigned to a mesh triangle

But I don't understand this part in the answer: "You'd code a likewise-not-too-difficult function to examine each pixel within the triangle based on its 3 UV coordinates". I think I just need a nudge in the right direction on how to get the pixels of a mesh under a triangle.

Here is my code:

     private void CreatePuzzlePieces(List<VoronoiCell2> cells, List<Vector2> imageBox)
     {
         for (int i = 0; i < cells.Count; i++)
         {
             VoronoiCell2 cell = cells[i];
             List<Vector2> vertices = new List<Vector2>();
 
             // Get the vertices of the mesh (puzzle piece)
             for (int j = 0; j < cell.edges.Count; j++)
             {
                 Vector3 p3 = cell.edges[j].p1.ToVector3();
                 Vector3 p2 = cell.edges[j].p2.ToVector3();
 
                 vertices.Add(p2);
                 vertices.Add(p3);
             }
 
             Vector3[] meshVertices = new Vector3[vertices.Count];
             Vector2[] uv = new Vector2[vertices.Count];
             int triangleCount = (vertices.Count - 2) * 3;
             int[] triangles = new int[triangleCount];
 
             // Scale the mesh to fit within the imagebox
             for (int j = 0; j < vertices.Count; j++)
             {
                 meshVertices[j] = new Vector3((vertices[j].x - imageBox[0].x) / (imageBox[1].x - imageBox[0].x),
                                             (vertices[j].y - imageBox[0].y) / (imageBox[1].y - imageBox[0].y));
                 uv[j] = meshVertices[j];
             }
 
             // Build triangles
             // This will only work for polygons without any concave features and it
             // uses a more efficent approach (fewer triangles) than DisplayVoronoiCells()
             // but may not work for polygons with 9 or more sides but that is unlikely to
             // occur with Voronoi algorithm
             int triPos = 0;
             int curr = 0;
             int loop = 1;
             for (int j = 0; j < triangleCount; j++)
             {
                 if (triPos == 3)
                 {
                     curr -= 1 * loop;
                     triangles[j] = curr;
                     triPos = 0;
                 }
                 else
                 {
                     if (curr >= vertices.Count)
                     {
                         curr = 0;
                         loop++;
                     }
                     triangles[j] = curr;
                 }
                 curr += 1 * loop;
                 triPos++;
             }
             Mesh mesh = new Mesh();
             mesh.vertices = meshVertices;
             mesh.uv = uv;
             mesh.triangles = triangles;
 
             GameObject goPiece = new GameObject("PuzzlePiece", typeof(MeshFilter), typeof(MeshRenderer));
             goPiece.transform.position = puzzleBox.transform.position;
             MeshRenderer rendererPiece = goPiece.GetComponent<MeshRenderer>();
             goPiece.GetComponent<MeshFilter>().mesh = mesh;
             rendererPiece.material = image;
 
             // ------------------------------------------------------------------------
             // Here is where I want to check the percent of mesh (pixels) that is fully transparent:
             if ( mesh contains > 99% transparent pixels) do something
             // ------------------------------------------------------------------------
         }
     }

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
0

Answer by nmill99 · Jun 08, 2020 at 12:41 PM

I've managed to make a solution to my particular problem. The way it works is like this:

  1. For the particular puzzle piece (mesh), I call the function "PercentTransparent()".

  2. For each triangle in the mesh, I get the UV coordinates (same as vertices for me) and translate those into pixel coordinates. For example, if the texture is 800x600, the uv coordinates (1.0f,1.0f) are translated to (800,600).

  3. I also get the vertex with the largest y value. This is our starting point. And then I get the lowest y value, which will be our end point.

  4. Then, starting from the largest y value position, I first go left looking to see if the pixel is in our triangle and once I'm not, I break and go right from the same starting point until again I'm no longer in the triangle.

The result is slow so it would not work on an Update() call but could work if pre-loaded which is my case.

I got this algorithm idea from paper A Parallel Algorithm for Polygon Rasterization by Juan Pineda 1988 and in particular this diagram: alt text

 public class PuzzlePiece
 {
     public Mesh Mesh { get; }
     public Material Image { get; }

     private float PercentTransparent()
     {
         float percent = 0f;
 
         string output = "Checking transparency on piece " + Index + "...\n";
 
         output += "Texture dimensions = " + Image.mainTexture.width + ", " + Image.mainTexture.height + "\n";
 
         output += " - Number of triangles = " + Mesh.triangles.Length + "\n";
         output += " - Number of vertices = " + Mesh.vertices.Length + "\n";
         output += " - Number of uvs = " + Mesh.uv.Length + "\n";
 
         // Iterate through each triangle
         long totalPixelCount = 0;
         long transparentPixelCount = 0;
         var triangles = Mesh.triangles;
         var uv = Mesh.uv;
         for (int i = 0; i < triangles.Length; i += 3)
         {
             // For each triangle (3 vertices), establish new UV coordiantes based on pixel position
             List<Vector2> uvPixelVertices = new List<Vector2>();
             int startYPos = 0;
             int startXPos = 0;
             int endYPos = 0;
 
             output += " Triangle" + i + ":\n";
             for (int j=0; j<3; j++)
             {
                 output += "   Normalized UV " + j + ": " + uv[triangles[i + j]] + "\n";
                 Vector2 vertices = new Vector2(uv[triangles[i + j]].x * Image.mainTexture.width,
                                                uv[triangles[i + j]].y * Image.mainTexture.height);
 
                 uvPixelVertices.Add(vertices);
 
                 if (Mathf.FloorToInt(vertices.y) > startYPos)
                 {
                     startYPos = Mathf.FloorToInt(vertices.y);
                     startXPos = Mathf.FloorToInt(vertices.x); ;
                 }
                 if (j == 0 || Mathf.FloorToInt(vertices.y) < endYPos)
                 {
                     endYPos = Mathf.FloorToInt(vertices.y);
                 }
                 output += "   - Pixel UV: " + vertices + "\n";
             }
             
 
             // Starting from the top, we go down one row at a time
             // and identify all the pixels inside our triangle
             // if they are inside, we track the pixel transparency
             // (Assuming : a<1.0 = transparent)
 
             for (int y = startYPos; y >= endYPos; y--)
             {
                 bool foundPixelOnLeft = false;
                 bool foundPixelOnRight = false;
                 int x = startXPos;
 
                 // First look left
                 while (true)
                 {
                     if (x < 0)
                         break;
                     if (PuzzleUtilities.IsPointInPolygon(new Vector2(x, y), uvPixelVertices))
                     {
                         if (!foundPixelOnLeft)
                             foundPixelOnLeft = true;
                         totalPixelCount++;
                         if ((Image.mainTexture as Texture2D).GetPixel(x, y).a < 1.0)
                             transparentPixelCount++;
                     }
                     else if (foundPixelOnLeft)
                     {
                         break;
                     }
                     x--;
                 }
 
                 // Now look right
                 x = startXPos + 1;
                 while(true)
                 {
                     if (x > Image.mainTexture.width)
                         break;
                     if (PuzzleUtilities.IsPointInPolygon(new Vector2(x, y), uvPixelVertices))
                     {
                         if (!foundPixelOnRight)
                             foundPixelOnRight = true;
                         totalPixelCount++;
                         if ((Image.mainTexture as Texture2D).GetPixel(x, y).a < 1.0)
                             transparentPixelCount++;
                     }
                     else if (foundPixelOnLeft)
                     {
                         break;
                     }
                     else if (foundPixelOnRight)
                     {
                         break;
                     }
                     x++;
                 }
             }
         }
 
         output += "FINISHED!  Total pixels = " + totalPixelCount + " Transparent Pixels = " + transparentPixelCount + "\n";
         Debug.Log(output);
 
         return (float) transparentPixelCount / totalPixelCount;
     }
 }
 
 
 public static class PuzzleUtilities
 {
     public static bool IsPointInPolygon(Vector2 point, List<Vector2> polygon)
     {
         // Even-odd rule
         // https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
         bool res = false;
         int j = polygon.Count - 1;
 
         for (int i = 0; i < polygon.Count; i++)
         {
             if (((polygon[i].y > point.y) != (polygon[j].y > point.y)) &&
                 (point.x < polygon[i].x + (polygon[j].x - polygon[i].x) * (point.y - polygon[i].y) / (polygon[j].y - polygon[i].y)))
             {
                 res = !res;
             }
             j = i;
         }
         return res;
     }
 }



rasterizer.png (45.6 kB)
Comment
Add comment · 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

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

146 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

Related Questions

Changing the color and transparency of a 3D model at runtime 1 Answer

Change color of mesh triangle based on Y position in world space 1 Answer

Render mesh by specifying color of triangle 1 Answer

Get average color of the texture assigned to a mesh triangle 2 Answers

Vertex Color to Texture2D?? 0 Answers


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