Orient procedural cylinder mesh ring center to spline point

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

   void CreateVertices()
{
    Vertices.Clear();
    Normals.Clear();
    Tangents.Clear();
    Triangles.Clear();
    Uvs.Clear();

    step = (360.0f * Mathf.Deg2Rad) / Segments;
    for (int n = 0; n < SplineVertices.Count; n++)
    {


        var p =   SplineVertices[n];// spline vertex position
// i have normals and tangents of each vertex as well

        float dynamicAngle = 0.0f;
        for (int i = 0; i < Segments; i++) //+1 to close circle
        {
        Vector3 point =new Vector3();

            if (i ==0 && n==0   ) //first cap
            {
                point= p;
            //    point = point * Quaternion.LookRotation(point, Vector3.forward);
                AddVertex(i, n, point);
                point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z) ;

                AddVertex(i, n, point);

            }
            else if (i == Segments - 1 && n == SplineVertices.Count - 1) //last cap
            {

                point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z)  ;

                AddVertex(i, n, point);
                point = p;

                AddVertex(i, n, point);
            }
            else //regular vertices
            {
                point = new Vector3(p.x + Radius * Mathf.Cos(dynamicAngle), p.y + Radius * Mathf.Sin(dynamicAngle), p.z);

                AddVertex( i, n, point);
            }
                dynamicAngle = dynamicAngle + step;

        }
    }

    CapSeparation(1); //first cap
    CapSeparation(Vertices.Count - Segments - 1);//second cap
    MeshDataCalculation();
    CreateMesh();
}

public float  Remap( float value, float from1, float to1, float from2, float to2)
{
    return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
void AddVertex(int i, int n, Vector3 point)
{

    //point.z = transform.position.z+ Remap(n, 0, Rings-1, 0, Height);//height settings
    // point.z = SplineVertices[n].z;
    point = transform.InverseTransformPoint(point);//convert points from world space to local space


    Vertices.Add(point);

}

here is a gif that illustrates my issue

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…

1 Like

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 :slight_smile: )
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.

var p =   SplineVertices[n];// spline vertex position
// i have normals and tangents of each vertex as well
var t = SplineTangents[n];// spline vertex tangent

var orientation = Quaternion.Euler(t);

//Inside for loop

point = p + orientation * new Vector3( Radius * Mathf.Cos(dynamicAngle),  Radius * Mathf.Sin(dynamicAngle), 0) ;
2 Likes

I’m on my phone so i can’t say much. But i do remember answering this question before. Check this thread.

1 Like

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

 for (int n = 0; n < SplineVertices.Count; n++)
        {

            var p =   SplineVertices[n];
            var t =   SplineTangents[n];// spline vertex tangent

           var orientation = Quaternion.LookRotation(SplineTangents[n], SplineNormals[n]);
 
            for (int i = 0; i < Segments; i++) //+1 to close circle
            {
            Vector3 point =new Vector3();
            
                    point =p+ orientation* new Vector3( Radius * Mathf.Cos(dynamicAngle), Radius * Mathf.Sin(dynamicAngle),0) ;

1 Like

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 :slight_smile:

1 Like

@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?