2015-04-02 6 views
0

Я работаю над созданием процедурной цилиндрической сетки с Unity C#. У меня все работает, но есть одна вещь, которую я хотел бы реализовать в моем существующем коде, чтобы определить vector3 halfAxis, который определяет высоту и направление цилиндра. Поэтому, если половина Ахз (0,1,0), центр цилиндра совпадает с осью у, если цилиндр находится в начале координат в мировом пространстве, а длина равна 2 с его половинной осью.Создание процедурной сетки с ориентацией

В настоящее время весь мой код генерирует цилиндр на основе коэффициента высоты только в направлении y. Существует capResolution, который определяет гладкость цилиндра и радиус для определения радиуса цилиндра

Ниже мой код. Как бы я изменить его, чтобы добавить вектор и определить полуоси его ориентация

public Vector3 halfAxis = Vector3.up; 
public float radius = 3f; 
public int capResolution = 3; 
public int height = 2; 
private const int MAX_CAP_RES = 3; 
private const int MAX_RADIUS = 1; 

void ComputeCylinder(out Vector3[] vertices, out Vector2[] uvs, out Vector3[] normals, out int[] faces) 
    { 

     if (capResolution < MAX_CAP_RES) capResolution = MAX_CAP_RES; 
     if (radius < MAX_RADIUS) radius = MAX_RADIUS; 

     //define total columns and rows 
     int noOfColumns = capResolution + 1; 
     int noOfRows = height + 1; 

     //total number of vertices that make up the cylinder 
     int noOfVertices = noOfColumns * noOfRows; 

     //no of normals for each vertex 
     int noOfNormals = noOfVertices; 

     //uvs are always equal to no of vertices in a mesh 
     int noOfUvs = noOfVertices; 

     //side faces (tris) without the top and bottom caps 
     int noOfSideFaces = capResolution * height * 2; 

     //cap faces (2 caps bottom and top) 
     int noOfCapFaces = capResolution - 2; 

     //initialize all the arrays 
     vertices = new Vector3[noOfVertices]; 
     normals = new Vector3[noOfNormals]; 
     uvs = new Vector2[noOfUvs]; 
     faces = new int[(noOfSideFaces + noOfCapFaces * 2) * 3]; 

     //angle step for each column for side tris 
     float step = Mathf.PI * 2/capResolution; 

     /* 
      first for loop computes all the side faces of the cylinder 
      second loop computes tris for top and bottom caps 
     */ 
     for (int i = 0; i < noOfRows; i++) 
     { 
      for (int j = 0; j < noOfColumns; j++) 
      { 
       float angle = j * step; 

       //folding from the first and last vertex 
       if (j == noOfColumns - 1) angle = 0; 

       //compute vertices, uvs and normals for each row and column offsets 
       vertices[i * noOfColumns + j] = new Vector3(radius * Mathf.Cos(angle),i * height,radius * Mathf.Sin(angle)); //build a cylinder with an upwards orientation 
       uvs[i * noOfColumns + j] = new Vector2(j * 1/radius, i * 1/halfAxis.y); 
       normals[i * noOfColumns + j] = new Vector3(0, 0, -1.0f); 

       /* 
        To create faces, we ignore the first row and the last column 
        for every other vertex we create two triangle faces at the same time in one loop 
       */ 
       if (i != 0 && j < noOfColumns - 1) 
       { 
        //offset the initial space for storing tris for bottom cap 
        int index = noOfCapFaces * 3 + (i - 1) * capResolution * 6 + j * 6; 

        //create the first face 
        faces[index + 0] = i * noOfColumns + j; 
        faces[index + 1] = i * noOfColumns + j + 1; 
        faces[index + 2] = (i - 1) * noOfColumns + j; 

        //create the second face 
        faces[index + 3] = (i - 1) * noOfColumns + j; 
        faces[index + 4] = i * noOfColumns + j + 1; 
        faces[index + 5] = (i - 1) * noOfColumns + j + 1; 
       } 
      } 
     } 

      /*drawing top and bottom caps 
      we need the firstIndex, midIndex and lastIndex as vertices for cap tris and store it in the faces array*/ 

     int firstIndex = 0; 
     int midIndex = 0; 
     int lastIndex = 0; 
     int topCapOffset = noOfVertices - noOfColumns; 

     for (int i = 0; i < noOfCapFaces; i++) 
     { 
      //we get the bottom index to populate faces for bottom cap 
      int bottomIndex = i * 3; 

      //top cap tris will be stored in the empty end location of faces array 
      int topIndex = (noOfCapFaces + noOfSideFaces) * 3 + i * 3; 

      //get the three index for each vertex to make a cap tri 
      if (i == 0) 
      { 
       firstIndex = 1; 
       midIndex = 0; 
       lastIndex = noOfColumns - 2; 
      } 
      else 
      { 
       midIndex = lastIndex; 
       lastIndex = lastIndex - 1; 
      } 

      //populate triangle vertices for bottom cap 
      faces[bottomIndex + 0] = lastIndex; 
      faces[bottomIndex + 1] = midIndex; 
      faces[bottomIndex + 2] = firstIndex; 

      //populate triangle vertices for top cap 
      faces[topIndex + 0] = topCapOffset + firstIndex; 
      faces[topIndex + 1] = topCapOffset + midIndex; 
      faces[topIndex + 2] = topCapOffset + lastIndex; 
     } 
    } 

ответ

1

Вы действительно должны повернуть данные сетки или это также приемлемо для вращения GameObject, который прилагается эта сетка? Late легко реализовать и более удобен в использовании, так как гораздо проще видеть степени вращения в инспекторе Transform.

Если вам нужно создать вращающуюся сетку, вы можете использовать Quaternion.LookAt для создания кватерниона, указывающего на halfAxis. Затем вы умножаете кватернион с каждой вершиной. Вы также должны умножать вращение с нормалями.

Бонус:

Это, как я бы вычислить нормаль для боковых стенок:

var vertexLocal = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), i * height); 
vertices[i * noOfColumns + j] = vertexLocal; //build a cylinder with an upwards orientation 
uvs[i * noOfColumns + j] = new Vector2(j * 1/radius, i * 1/halfAxis.y); 
vertexLocal.y = 0f; 
normals[i * noOfColumns + j] = vertexLocal.normalized; 
+0

К сожалению, это проблема дано мне, и это требует от меня, чтобы повернуть только данные сетки, а не окончательное геймобжекты. Я попробую решение Quaternion, предложенное вами. – Htlcs

+0

Я не совсем уверен, как будет работать подход кватерниона. Я попробовал что-то вроде Quaternion targetRot = Quaternion.LookRotation (halfAxis) и умножил каждый вектор вершин с этим вращением. Это не работает, или я могу сделать это неправильно. – Htlcs

+0

Продолжайте пытаться. Вероятно, вам нужно переключить vertex.y и vertex.z, потому что ваш объект будет обращен к оси Z после LookAt. И попробуйте изменить значения halfAxis и посмотреть, меняется ли ориентация ориентации. –