Unity3D Method for Creating Cylinders

Time:2019-6-12

Looking at this article, you may wonder why Unity has its own cylindrical component that can be generated directly, and why we need to use code to generate it. In fact, recently, the leader of the project has a requirement, that is, we have to operate the cylinder in the self-written editor, that is, the cylinder. The function is similar to the drawing line in 3D Max. When I first saw this request, I refused it in my heart. I am a unit programmer, not an image programmer. It looks a bit low-level. But I think this is also an opportunity for self-learning and promotion, so I will give the leadership face to realize it. We know that if we want to operate a pipeline like in 3D max, we have to create a cylinder with code and control its vertex position with code to meet our needs. So the first step is to use code to create the cylinders we need. The results are as follows:

In fact, before I tried to understand the code to create a cube, it looked very simple, but in fact it was not simple, mainly for the vertex, and corresponding to the vertex order of the triangle. I found a self-written cylindrical code on the Internet. It looked good and copied it directly, but it provided two sides less. So we need to make up for this by ourselves. And then the important thing isThe intersection of the two faces can not be shared. It must be added again, because it involves the problem of the normal line.

// A cylinder is composed of two circles and a rectangle. The vertex of the rectangle is input first and then the vertex of the circle is input.
 private void UpdateMesh(Mesh mesh,int edg_x, int edg_y, float rad, float len)
 {
  Edg_x = Mathf. Max (2, edg_x); // Guarantee a minimum of 2 edges
  edg_y = Mathf.Max(2, edg_y);
  Int_deglen= (edg_x+1)*edg_y;//cuboid
  Int total count = deglen + (1 + edg_x + 1) * 2; // plus two circles
 
 
  Vector3[] normals = new Vector3[totalcount];
  Vector3[] verts = new Vector3[totalcount];
  Vector2[] uvs = new Vector2[totalcount];
  int[] trians = new int[edg_x * edg_y*6]; 
  float reg = 6.28318f / edg_x;
  float _len = len / (edg_y - 1);
 
  
 
  for (int y = 0; y < edg_y; y++)
   For (int x = 0; x < edg_x + 1; x +) // more than one side to save the UV value
   {
    int i = x + y * (edg_x + 1);
    Verts [i] = new Vector 3 (Mathf.Sin ((reg* (x%) edg_x)% 6.28318f) * rad, Mathf.Cos ((reg* (x%) edg_x)% 6.28318f) * rad, rigPos + y* _len); //Compute vertex coordinates
    Norals [i] = new Vector 3 (verts [i], x, verts [i], y, 0); //Calculate the normal direction
    int id = x % (edg_x + 1) * 6 + y * edg_x * 6;
    If (x < edg_x + 1 & & Y < edg_y - 1 & & (id + 5) < trians. Length) // Compute vertex array
    {
     if(length>0)
     {
      trians[id] = i;
      trians[id + 1] = trians[id + 4] = i + edg_x + 1;
      trians[id + 2] = trians[id + 3] = i + 1;
      trians[id + 5] = i + edg_x + 2;
     }
     else
     {
      trians[id] = i;
      trians[id + 1] = trians[id + 3] = i + 1;
      trians[id + 2]= trians[id + 5]=i + edg_x + 1;
      trians[id + 4] = i + edg_x + 2;
     }
     
    }
    // If (edg_x!= 2)// Compute UV, taking into account the case of two edges
    // uvs[i] = new Vector2(x == edg_x ? 1f : quaduvStep.x * x, y == edg_y - 1 ? (2*rad+len)/totalLen : quaduvStep.y * y);
    //else
    // uvs[i] = new Vector2(x % edg_x, y == edg_y - 1 ? (2 * rad + len) / totalLen : quaduvStep.y * y);
   }
  
  int maxId = edg_x * (edg_y - 1) * 6;
  verts[_deglen] = new Vector3(0,0,rightPos);
  
  normals[_deglen] = -Vector3.forward;
 
  //uvs[_deglen] = new Vector2(0.5f, (rad) / totalLen);
  // Origin side
  for (int x = 0; x < edg_x+1 ; x++)
  {
   verts[_deglen + 1 + x] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, rightPos);
   normals[_deglen + 1 + x] = -Vector3.forward;
   if (x == edg_x) continue;
 
   if(length>0)
   {
    trians[3 * x + maxId] = _deglen;
    trians[3 * x + 1 + maxId] = _deglen + 1 + x;
    trians[3 * x + 2 + maxId] = _deglen + 2 + x;
   }
   else
   {
    trians[3 * x + maxId] = _deglen;
    trians[3 * x + 1 + maxId] = _deglen + 2 + x;
    trians[3 * x + 2 + maxId] = _deglen + 1 + x;
   }
  }
 
 
  // Far side
  maxId += 3 * edg_x;
  verts[_deglen + 2 + edg_x] = new Vector3(0, 0, leftPos);
  normals[_deglen + 2 + edg_x] = Vector3.forward;
  //uvs[_deglen + 1] = new Vector2(0.5f, (3 * rad + len) / totalLen);
  
  for (int x = 0; x < edg_x+1; x++)
  {
   verts[1 + x+edg_x+2+ _deglen] =new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad,leftPos);
   normals[1 + x + edg_x + 2 + _deglen] = Vector3.forward;
   if (x == edg_x) continue;
   if (length > 0)
   {
    trians[3 * x + maxId] = _deglen + 2 + edg_x;
    trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 2;
    trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 1;
   }
   else
   {
    trians[3 * x + maxId] = _deglen + 2 + edg_x;
    trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 1;
    trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 2;
   }
  }
  mesh.Clear();
  mesh.vertices = verts;
  mesh.triangles = trians;
  //mesh.uv = uvs;
  mesh.normals = normals;
  mesh.RecalculateBounds();
 }

In fact, looking at the code, you will find that the length len of the cylinder is obtained by the variable leftPos-rightPos that we declared ourselves. That is length = len = leftPos-rightPos. We can manipulate variables leftPos and rightPos to control the position and length of one end of the cylinder. When our length is less than 0, his triangular vertex drawing order is just the opposite, so we need to judge in the code block. The above is the realization of drawing cylinders for code. I hope it will help you.