Search Unity

Trying extrude a 2d polygon to create a mesh

Discussion in 'Scripting' started by markt1964, Aug 30, 2011.

  1. markt1964

    markt1964

    Joined:
    Aug 30, 2011
    Posts:
    83
    I am trying to figure out how to go from a 2d polygon (stored as an array of Vector2) to an extruded mesh, but I am not sure if I am doing things correctly, because I do not see my object in the scene editor when I attempt to add it using test methods. I am unsure if the problem is how I am creating the mesh, or if it is related to my creating the corresponding gameobject. I am, at the moment, only interested in seeing a wireframe of the mesh in the editor... nothing more.

    I am using csharp for scripting... if anyone can help me figure out what I am doing wrong, it would be greatly appreciated. The source code for the Triangulator class that I am using can be found here.

    Thanks in advance.
    Code (csharp):
    1.  
    2. ....
    3.     static Mesh CreateMesh(Vector2 [] poly)
    4.     {
    5.         // convert polygon to triangles
    6.         Triangulator triangulator = new Triangulator(poly);
    7.         int[] triangles = triangulator.Triangulate();
    8.         Mesh m = new Mesh();
    9.         m.vertices = new Vector3[poly.Length*2];
    10.         for(int i=0;i<poly.Length;i++)
    11.         {
    12.             m.vertices[i].x = poly[i].x;
    13.             m.vertices[i].y = poly[i].y;
    14.             m.vertices[i].z = -10; // front vertex
    15.             m.vertices[i+poly.Length].x = poly[i].x;
    16.             m.vertices[i+poly.Length].y = poly[i].y;
    17.             m.vertices[i+poly.Length].z = 10;    // back vertex    
    18.         }
    19.         m.triangles = new int[triangles.Length*2+poly.Length*6];
    20.         int count_tris = 0;
    21.         for(int i=0;i<triangles.Length;i+=3)
    22.         {
    23.             m.triangles[i] = triangles[i];
    24.             m.triangles[i+1] = triangles[i+1];
    25.             m.triangles[i+2] = triangles[i+2];
    26.         } // front vertices
    27.         co/unt_tris+=triangles.Length;
    28.         for(int i=0;i<triangles.Length;i+=3)
    29.         {
    30.             m.triangles[count_tris+i] = triangles[i+2]+poly.Length;
    31.             m.triangles[count_tris+i+1] = triangles[i+1]+poly.Length;
    32.             m.triangles[count_tris+i+2] = triangles[i]+poly.Length;
    33.         } // back vertices
    34.         count_tris+=triangles.Length;
    35.         for(int i=0;i<poly.Length;i++)
    36.         {
    37.                        // triangles around the perimeter of the object
    38.             int n = (i+1)%poly.Length;
    39.             m.triangles[count_tris] = i;
    40.             m.triangles[count_tris+1] = i + poly.Length;
    41.             m.triangles[count_tris+2] = n;
    42.             m.triangles[count_tris+3] = n;
    43.             m.triangles[count_tris+4] = n + poly.Length;
    44.             m.triangles[count_tris+5] = i + poly.Length;
    45.             count_tris += 6;
    46.         }
    47.         m.RecalculateNormals();
    48.         m.RecalculateBounds();
    49.         m.Optimize();
    50.         return m;
    51.     }
    52.  
    53.         static void test()
    54.         {
    55.             Mesh m = CreateMesh(polygon);
    56.         GameObject gameObject = new GameObject();
    57.             gameObject.AddComponent(typeof(MeshRenderer));
    58.             MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
    59.             filter.mesh = m;
    60.         }
    61. ...
    62.  
     
    AlekseyKhomenko likes this.
  2. ivkoni

    ivkoni

    Joined:
    Jan 26, 2009
    Posts:
    978
    looks correct to me.
    Does a new gameobject appear in the editor?
    you can also try GameObject gameObject = new GameObject("test");
    You can also try creating a prefab that already has the mesh renderer and the mesh filter. Then use Instantiate() to create the prefab and assign the mesh with GetComponent<MeshFilter>().mesh = m.
     
  3. markt1964

    markt1964

    Joined:
    Aug 30, 2011
    Posts:
    83
    Thank you for your response. When I run my test function, although a new game object appears in the Hierarchy window, I cannot actually see it anything in the Scene window (which is currently set to Wireframe mode). It is evidently really there, because clicking on the object in the hierarchy window shows a tiny square and 3 axes in the Scene window, presumably where the object is situated, and which I can manipulate graphically, but I cannot actually see any of the object itself. The original polygon has units in the range of about +-100 in both the x and y axes.

    Thanks again... any further assistance would be greatly appreciated.
     
  4. ivkoni

    ivkoni

    Joined:
    Jan 26, 2009
    Posts:
    978
    try

    Code (csharp):
    1.  
    2. static Mesh CreateMesh(Vector2 [] poly)
    3.     {
    4.         // convert polygon to triangles
    5.         Triangulator triangulator = new Triangulator(poly);
    6.         int[] tris = triangulator.Triangulate();
    7.         Mesh m = new Mesh();
    8.         Vector3[] vertices = new Vector3[poly.Length*2];
    9.        
    10.         for(int i=0;i<poly.Length;i++)
    11.         {
    12.             vertices[i].x = poly[i].x;
    13.             vertices[i].y = poly[i].y;
    14.             vertices[i].z = -10; // front vertex
    15.             vertices[i+poly.Length].x = poly[i].x;
    16.             vertices[i+poly.Length].y = poly[i].y;
    17.             vertices[i+poly.Length].z = 10;  // back vertex    
    18.         }
    19.         int[] triangles = new int[tris.Length*2+poly.Length*6];
    20.         int count_tris = 0;
    21.         for(int i=0;i<tris.Length;i+=3)
    22.         {
    23.             triangles[i] = tris[i];
    24.             triangles[i+1] = tris[i+1];
    25.             triangles[i+2] = tris[i+2];
    26.         } // front vertices
    27.         count_tris+=tris.Length;
    28.         for(int i=0;i<tris.Length;i+=3)
    29.         {
    30.             triangles[count_tris+i] = tris[i+2]+poly.Length;
    31.             triangles[count_tris+i+1] = tris[i+1]+poly.Length;
    32.             triangles[count_tris+i+2] = tris[i]+poly.Length;
    33.         } // back vertices
    34.         count_tris+=tris.Length;
    35.         for(int i=0;i<poly.Length;i++)
    36.         {
    37.           // triangles around the perimeter of the object
    38.             int n = (i+1)%poly.Length;
    39.             triangles[count_tris] = i;
    40.             triangles[count_tris+1] = i + poly.Length;
    41.             triangles[count_tris+2] = n;
    42.             triangles[count_tris+3] = n;
    43.             triangles[count_tris+4] = n + poly.Length;
    44.             triangles[count_tris+5] = i + poly.Length;
    45.             count_tris += 6;
    46.         }
    47.         m.vertices = vertices;
    48.         m.triangles = triangles;
    49.         m.RecalculateNormals();
    50.         m.RecalculateBounds();
    51.         m.Optimize();
    52.         return m;
    53.     }
    54.  
     
    AlekseyKhomenko likes this.
  5. markt1964

    markt1964

    Joined:
    Aug 30, 2011
    Posts:
    83
    Thank you! That worked perfectly!
     
  6. CoalCzar

    CoalCzar

    Joined:
    Nov 25, 2012
    Posts:
    22
    For anyone else who happens to stumble upon this code, there is an error that will give you only every other triangle around the perimeter. Just replace

    Code (CSharp):
    1.           // triangles around the perimeter of the object
    2.             int n = (i+1)%poly.Length;
    3.             triangles[count_tris] = i;
    4.             triangles[count_tris+1] = i + poly.Length;
    5.             triangles[count_tris+2] = n;
    6.             triangles[count_tris+3] = n;
    7.             triangles[count_tris+4] = n + poly.Length;
    8.             triangles[count_tris+5] = i + poly.Length;
    9.             count_tris += 6;
    with

    Code (CSharp):
    1.             // triangles around the perimeter of the object
    2.             int n = (i+1)%poly.Length;
    3.             triangles[count_tris] = i;
    4.             triangles[count_tris+1] = n;
    5.             triangles[count_tris+2] = i + poly.Length;
    6.             triangles[count_tris+3] = n;
    7.             triangles[count_tris+4] = n + poly.Length;
    8.             triangles[count_tris+5] = i + poly.Length;
    9.             count_tris += 6;
     
    konistehrad2 and AlekseyKhomenko like this.
  7. alexander11

    alexander11

    Joined:
    Aug 11, 2014
    Posts:
    94
    What is polygon in line 55?
     
  8. jaxx0rr

    jaxx0rr

    Joined:
    Aug 25, 2013
    Posts:
    23
    for me the normals were flipped on the sides but this worked

    Code (CSharp):
    1.             // triangles around the perimeter of the object
    2.             int n = (i+1)%poly.Length;
    3.             triangles[count_tris] = i;
    4.             triangles[count_tris+1] = n;
    5.             triangles[count_tris+2] = i + poly.Length;
    6.             triangles[count_tris+3] = n;
    7.             triangles[count_tris+4] = i + poly.Length;
    8.             triangles[count_tris+5] = n + poly.Length;
    9.             count_tris += 6;
    ...

    EDIT: ok now the other code works for this new shape.. no clue whats going on...
     
    Last edited: May 17, 2017
  9. Thibault-Potier

    Thibault-Potier

    Joined:
    Apr 10, 2015
    Posts:
    206
    "EDIT: ok now the other code works for this new shape.. no clue whats going on..."

    Guys, the reason that makes you all have "different" behaviour with the same code (and thus, make you all have a different version of the code to work for your mesh) is simple:

    It is dependant of the way you defined your points. If the points in your Vector2 array are listed clockwise (or anti-clockwise) the sides of the mesh will have a normal pointing inside (or outside) of the mesh.

    To find out if a list of polygon points are listed clockwise or not, you need to sum the angle between each point.
    There is a simple geometric rule that says: The sum of all the N interior angle of any polygon is equal to (n-2) × 180°
    Thus, you can deduce if the list is in clockwise order or anti-clockwise.
     
  10. JPhilipp

    JPhilipp

    Joined:
    Oct 7, 2014
    Posts:
    56
    Thanks for the code, it works great -- but how do I flip the bridging triangle normals, as seemingly every second is wrong for me? (Also asked at StackOverflow.)

    Edit: The answer is now provided in above-mentioned StackOverflow, and works great.

     
    Last edited: Nov 18, 2019
  11. elfasito

    elfasito

    Joined:
    Jul 4, 2017
    Posts:
    51
    Hello, newbie question.
    Is there a way of modify this to use as sprite mask?
    my basic idea is use the 2d polygon to generate a sprite mask.
    I need to create a lot of shapes for use as mask, but the "photoshop" way is really slower because of the quantity.
     
    Last edited: Apr 29, 2021