Search Unity

Probuilder polyshape.SetControlPoints

Discussion in 'World Building' started by andersbomann, Oct 28, 2020.

  1. andersbomann

    andersbomann

    Joined:
    Aug 17, 2020
    Posts:
    5
    Is it possible to give two lists of control points for the polyshape?
    I would love to create a wall with openings

    Code (CSharp):
    1. PolyShape polyshape = gameObject.GetComponent<PolyShape>();
    2. polyshape.SetControlPoints(A, B);
    3. polyshape.extrude = wallThickness;
    4. polyshape.CreateShapeFromPolygon();
     
    Last edited: Oct 28, 2020
  2. andersbomann

    andersbomann

    Joined:
    Aug 17, 2020
    Posts:
    5
    Something like this
     

    Attached Files:

  3. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi Anders,
    In the class AppendElements you should find exactly the method you are looking for :


    /// <summary>
    /// Rebuild a mesh from an ordered set of points.
    /// </summary>
    /// <param name="mesh">The target mesh. The mesh values will be cleared and repopulated with the shape extruded from points.</param>
    /// <param name="points">A path of points to triangulate and extrude.</param>
    /// <param name="extrude">The distance to extrude.</param>
    /// <param name="flipNormals">If true the faces will be inverted at creation.</param>
    /// <param name="holePoints">Holes in the polygon. If null this will be ignored.</param>
    /// <returns>An ActionResult with the status of the operation.</returns>

    public static ActionResult CreateShapeFromPolygon(this ProBuilderMesh mesh, IList<Vector3> points,
    float extrude, bool flipNormals, IList<IList<Vector3>> holePoints)

    In your case A will be the list of 'points' and B a list in your 'holePoints' (you can have multiple holes in your shape, that why it's a list of list).

    Hope this helps :)
     
  4. andersbomann

    andersbomann

    Joined:
    Aug 17, 2020
    Posts:
    5
    Hi @ThomasLopez - thanks a lot for the reply!
    It seems like the perfect match for this purpose.
    Unfortunately I can't figure out to add the 'holePoints' when generating my walls.
    Can you point me in the direction of an example? Or even give some feedback on my code :)

    Code (CSharp):
    1.        
    2.  
    3. public float wallThickness = 0.2f;
    4.  
    5.         public void InitializeWall(Interface interFace) {
    6.  
    7.             wallControlPoints = new List<Vector3> {
    8.             startEndPoints[0] + normal * wallThickness/2,
    9.             dubStartEndPoints[0] + normal * wallThickness/2 + Vector3.up * 3f,
    10.             dubStartEndPoints[1] + normal * wallThickness/2 + Vector3.up * 3f,
    11.             startEndPoints[1] + normal * wallThickness/2
    12.             };
    13.  
    14.            
    15.             IList<Vector3> wallHole = new List<Vector3> {
    16.                 dubdubStartEndPoints[0] + normal * wallThickness/2 + (dubdubStartEndPoints[1]-dubdubStartEndPoints[0]) *(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]).magnitude/2 ,
    17.                 dubdubdubStartEndPoints[0] + normal * wallThickness/2 +(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]) *(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]).magnitude/2 + Vector3.up * 2f,
    18.                 dubdubdubStartEndPoints[1] + normal * wallThickness/2 +(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]) *(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]).magnitude/2+ Vector3.up * 2f,
    19.                 dubdubStartEndPoints[1] + normal * wallThickness/2+(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]) *(dubdubStartEndPoints[1]-dubdubStartEndPoints[0]).magnitude/2
    20.             };
    21.             IList<IList<Vector3>> wallHoles = new List<IList<Vector3>>();
    22.             wallHoles.Append(wallHole);
    23.             Debug.Log(wallHoles.Count);
    24.  
    25.             ProBuilderMesh mesh = ProBuilderMesh.Create();
    26.  
    27.             mesh.CreateShapeFromPolygon(wallControlPoints, wallThickness, false, wallHoles);
    28.        
    29.             mesh.GetComponent<MeshRenderer>().material = prefabWall.wallMaterial;
    30.             mesh.ToMesh();
    31.             mesh.Refresh();
    32.  
    33.         }
     
  5. andersbomann

    andersbomann

    Joined:
    Aug 17, 2020
    Posts:
    5
    Hi @ThomasLopez nvm, I solved the problem (juhu and thanks a lot for hint!) but I ran into a new one...
    It seems like the extrusion direction is rather random - but only in the cases where I'm adding the "holePoints"?
    Do you have fix for that :) ?

    Thanks in advance !
     
  6. andersbomann

    andersbomann

    Joined:
    Aug 17, 2020
    Posts:
    5
    After inspection of the code in AppendElements.cs, I think I have located the problem:
    in AppendElements.CreateShapeFromPolygon(), the extrusion directions is taken as the face normal that is closest to the up direction of the gameObject's transform (around line 350 in AppendElements.cs), while i was trying to extrude in the forward direction. Since all my face normals were perpendicular to the up direction, it would give inconsistent results. I don't think this behavior of CreateShapeFromPolygon() is documented.

    As a suggestion I would hope you could insert a further check such that the face normal would be prioritized for example as face closest to up -> face closest to forward so results can always be consistent.

    Another suggestion could be a new overload for CreateShapeFromPolygon() that could accept a direction vector and chose the face normal that is closest to the given direction vector.
     
  7. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @andersbomann, sorry for the late answer.
    So in the case of the CreateShapeFromPolygon() method, the idea is indeed to define your shape and holes in a 2D manner and then the whole shape with its holes are extruded. I have to check this in the code but in order to triangulate the polyshape you define all the vertices (shape and holes) are projected in the 2D space that best fits the alignment of shape vertices and then the resulting 2D shape is extrude.
    Then I'm not sure about the fact we can easily add a direction for hole extraction, this should already be done automatically by the code.

    Could you provide me your scripts with some real value that I could test around on my side and share my mind?
     
  8. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    I just had a quick look at your code, you should ensure that your points defined in the wallHole are in the same plane than the original shape which is not sure here regarding the way you build that it can depend on the values.

    I simplified a little your script and test is out with simple values that are in the same plane and it seems to be working :)

    upload_2020-11-18_10-24-46.png

    Here is the script I used:

    Code (CSharp):
    1.     public void InitializeWall() {
    2.  
    3.         List<Vector3> wallControlPoints = new List<Vector3> {
    4.         startEndPoints[0] + normal * wallThickness/2,
    5.         startEndPoints[0] + normal * wallThickness/2 + Vector3.up * 3f,
    6.         startEndPoints[1] + normal * wallThickness/2 + Vector3.up * 3f,
    7.         startEndPoints[1] + normal * wallThickness/2
    8.         };
    9.  
    10.      
    11.         IList<Vector3> wallHole = new List<Vector3> {
    12.             dubdubStartEndPoints[0] + normal * wallThickness/2 ,
    13.             dubdubStartEndPoints[0] + normal * wallThickness/2 + Vector3.up * 2f,
    14.             dubdubStartEndPoints[1] + normal * wallThickness/2 + Vector3.up * 2f,
    15.             dubdubStartEndPoints[1] + normal * wallThickness/2
    16.         };
    17.         IList<IList<Vector3>> wallHoles = new List<IList<Vector3>>();
    18.         wallHoles.Add(wallHole);
    19.  
    20.         ProBuilderMesh mesh = ProBuilderMesh.Create();
    21.  
    22.         mesh.CreateShapeFromPolygon(wallControlPoints, wallThickness, false, wallHoles);
    23.  
    24.         mesh.ToMesh();
    25.         mesh.Refresh();
    26.  
    27.     }
    Hope this help :)
     
  9. Alxander_Watson

    Alxander_Watson

    Joined:
    Mar 11, 2017
    Posts:
    16
    Hello

    I'm trying to understand how to use the CreateShapeFromPolygon function to create 3D objects with holes.

    I wrote this:
    Code (CSharp):
    1. List<Vector3> tempControlPoints = new List<Vector3>();
    2.                     tempControlPoints.Add(new Vector3(-0.5f, -0.5f, 0));
    3.                     tempControlPoints.Add(new Vector3(0.5f, 0.5f, 0));
    4.                     tempControlPoints.Add(new Vector3(0.5f, -0.5f, 0));
    5.                     tempControlPoints.Add(new Vector3(-0.5f, 0.5f, 0));
    6.  
    7.                     IList<IList<Vector3>> tempHolePoints = new List<IList<Vector3>>();
    8.                     tempHolePoints.Add(new List<Vector3>());
    9.                     tempHolePoints[0].Add(new Vector3(-0.25f, -0.25f, 0));
    10.                     tempHolePoints[0].Add(new Vector3(0.25f, 0.25f, 0));
    11.                     tempHolePoints[0].Add(new Vector3(0.25f, -0.25f, 0));
    12.                     tempHolePoints[0].Add(new Vector3(-0.25f, 0.25f, 0));
    13.  
    14.                     ProBuilderMesh mesh = ProBuilderMesh.Create();
    15.  
    16.                     Debug.Log(mesh.CreateShapeFromPolygon(tempControlPoints, 1, false, tempHolePoints).status);
    17.  
    18.                     mesh.ToMesh();
    19.                     mesh.Refresh();
    I was expecting a cube with a square hole. But the Action result status is always a failure.

    Where am I going wrong?