Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Orient procedural cylinder mesh ring center to spline point

Discussion in 'Scripting' started by badr_douah, Jan 19, 2018.

  1. badr_douah

    badr_douah

    Joined:
    Jun 22, 2017
    Posts:
    22
    i'm having issues figuring out how i can orient a procedural cylinder mesh ring center "Vector3" with a spline point "Vector3" in order to make the generated procedural mesh follows a spline properly , what i have is a normal and tangent and position of each point on the spline

    here is the code i'm using to create the mesh and allign it with the spline

    Code (CSharp):
    1.    void CreateVertices()
    2. {
    3.     Vertices.Clear();
    4.     Normals.Clear();
    5.     Tangents.Clear();
    6.     Triangles.Clear();
    7.     Uvs.Clear();
    8.  
    9.     step = (360.0f * Mathf.Deg2Rad) / Segments;
    10.     for (int n = 0; n < SplineVertices.Count; n++)
    11.     {
    12.  
    13.  
    14.         var p =   SplineVertices[n];// spline vertex position
    15. // i have normals and tangents of each vertex as well
    16.  
    17.         float dynamicAngle = 0.0f;
    18.         for (int i = 0; i < Segments; i++) //+1 to close circle
    19.         {
    20.         Vector3 point =new Vector3();
    21.  
    22.             if (i ==0 && n==0   ) //first cap
    23.             {
    24.                 point= p;
    25.             //    point = point * Quaternion.LookRotation(point, Vector3.forward);
    26.                 AddVertex(i, n, point);
    27.                 point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z) ;
    28.  
    29.                 AddVertex(i, n, point);
    30.  
    31.             }
    32.             else if (i == Segments - 1 && n == SplineVertices.Count - 1) //last cap
    33.             {
    34.  
    35.                 point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z)  ;
    36.  
    37.                 AddVertex(i, n, point);
    38.                 point = p;
    39.  
    40.                 AddVertex(i, n, point);
    41.             }
    42.             else //regular vertices
    43.             {
    44.                 point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z);
    45.  
    46.                 AddVertex( i, n, point);
    47.             }
    48.                 dynamicAngle = dynamicAngle + step;
    49.  
    50.         }
    51.     }
    52.  
    53.     CapSeparation(1); //first cap
    54.     CapSeparation(Vertices.Count - Segments - 1);//second cap
    55.     MeshDataCalculation();
    56.     CreateMesh();
    57. }
    58.  
    59. public float  Remap( float value, float from1, float to1, float from2, float to2)
    60. {
    61.     return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
    62. }
    63. void AddVertex(int i, int n, Vector3 point)
    64. {
    65.  
    66.     //point.z = transform.position.z+ Remap(n, 0, Rings-1, 0, Height);//height settings
    67.     // point.z = SplineVertices[n].z;
    68.     point = transform.InverseTransformPoint(point);//convert points from world space to local space
    69.  
    70.  
    71.     Vertices.Add(point);
    72.  
    73. }
    here is a gif that illustrates my issue
     
    Last edited: Jan 19, 2018
  2. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    What you have is all the cylinder rings contain the same orientation (rotation). For each spline vertex "p", you're only looking at its position, not rotation, when generating the points, so you end up with that flattened section of the tube.

    Are the spline vertices rotated along where the tube should go? If not, you'll probably have to figure out the rotation based on the vector between the current and previous vertices...
     
    badr_douah likes this.
  3. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    There you go. You can use both to rotate your verticies. Your code sets position with a constant orientation. You can rotate it by multiplying with a quaternion (I just learned myself :) )
    You could also use normal direction for another transformation to prevent possible wrinkles around the Z axis of your spline.

    Maybe that should work. Rewrite all your point assignments like that.
    Code (CSharp):
    1. var p =   SplineVertices[n];// spline vertex position
    2. // i have normals and tangents of each vertex as well
    3. var t = SplineTangents[n];// spline vertex tangent
    4.  
    5. var orientation = Quaternion.Euler(t);
    6.  
    7. //Inside for loop
    8.  
    9. point = p + orientation * new Vector3( Radius * Mathf.Cos(dynamicAngle),  Radius * Mathf.Sin(dynamicAngle), 0) ;
     
    Last edited: Jan 19, 2018
    asdzxcv777 and badr_douah like this.
  4. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    badr_douah likes this.
  5. badr_douah

    badr_douah

    Joined:
    Jun 22, 2017
    Posts:
    22
    thank you very much guys for all your answers ,
    @McDev02 your answer helped me the most,i knew that i have to add a rotation , but what i was doing in a wrong way, i was multilying by "point" instead of adding to "point", also Quaternion.Euler(t); didn't work but Quaternion.LookRotation did
    here is the code that worked for me

    Code (CSharp):
    1.  for (int n = 0; n < SplineVertices.Count; n++)
    2.         {
    3.  
    4.             var p =   SplineVertices[n];
    5.             var t =   SplineTangents[n];// spline vertex tangent
    6.  
    7.            var orientation = Quaternion.LookRotation(SplineTangents[n], SplineNormals[n]);
    8.  
    9.             for (int i = 0; i < Segments; i++) //+1 to close circle
    10.             {
    11.             Vector3 point =new Vector3();
    12.            
    13.                     point =p+ orientation* new Vector3( Radius * Mathf.Cos(dynamicAngle), Radius * Mathf.Sin(dynamicAngle),0) ;
    14.        
     
    McDev02 likes this.
  6. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    Quaternion.LookRotation(SplineTangents[n], SplineNormals[n]);
    That might be the best solution as it solves banking issues right away.
    Also my solution was wrong as I testet it only with a rotation vector and not with a directional vector :)
     
    badr_douah likes this.
  7. homer_3

    homer_3

    Joined:
    Jun 19, 2011
    Posts:
    111
    @badr_douah I'm trying to do something similar but am still struggling on just getting a segmented cylinder drawn before I even begin to look at rotating each segment. Any chance you're able to share your code for this?