Как мне превратить сплющенный 3D-массив вершин в массив треугольников?

#c# #unity3d #geometry #mesh

#c# #unity3d #геометрия #сетка

Вопрос:

Привет, я использую Unity и C # вместе с средством визуализации сетки и фильтром для имитации фрагмента 16*16*256 (фрагмента Minecraft). Следуя следующему видео в качестве руководства.

У меня есть 3 константы :

Globals.CHUNK_X (сокращено до W)

Globals.CHUNK_Y (H)

Globals.CHUNK_Z (D)

У меня также есть функция Globals.c3to1(x, y, z) , которая преобразует 3d-индекс в 1d-индекс в (W 1)*(H 1)*(D 1) массиве вершин, возвращая следующее (H 1) * (W 1) * z (W 1) * y x .

Я расположил свои вершины в 1d массиве измерений (W 1)*(H 1)*(D 1) , называемых vertices такими, что vertices[c3to1(x, y, z)] = (x, y, z) . Теперь, когда у меня есть свои вершины, как мне собрать все треугольники в массив. Я создал цикл for, с которым можно согласиться.

 /*How the array of vertices were created.*/
        vertices = new Vector3[(Globals.CHUNK_X   1) * (Globals.CHUNK_Y   1) * (Globals.CHUNK_Z   1)];
        for (int z = 0; z <= Globals.CHUNK_Z; z  ) {
            for (int y = 0; y <= Globals.CHUNK_Y; y  ) {
                for (int x = 0; x <= Globals.CHUNK_X; x  ) {
                    int index = Globals.c3to1(x, y, z);
                    vertices[index] = new Vector3(x, y, z);
                }
            }
        }
  
 /*How do I go about doing this triangles array*/
        triangles = new int[36 * (Globals.CHUNK_X   1) * (Globals.CHUNK_Y   1) * (Globals.CHUNK_Z   1)];
        for (int z = 0; z < Globals.CHUNK_Z; z  ) { //For each aisle
            for (int y = 0; y < Globals.CHUNK_Y; y  ) { //For each row
                for (int x = 0; x < Globals.CHUNK_X; x  ) { //For each column
                    for (int i = 0, index = 0; i < 6; i  ) { //For each 6 faces
                        for (int j = 0; j < 6; j  , index  ) { //For each 6 points of each face
                            //triangles[36 * Globals.c3to1(x, y, z)   index] = ?;
                        }
                    }
                }
            }
        }
  

Для тех, кто задается вопросом, почему вершины 17*17*257 вместо 16*16*256 этого являются bc, в каждой строке, столбце и проходе есть дополнительная вершина (2 смежных куба имеют 3 вершины на соединенном ребре, 3 имеют 4, 4 имеют 5 и так далее).

Комментарии:

1. Вы уверены, что хотите это сделать? Это около 2 миллионов треугольников, где большинство из них все равно не видны. Чего вы пытаетесь достичь? Можно ли отображать только треугольники на поверхности?

2. @NicoSchertler Я думаю, что в Unity есть какая-то выбраковка, потому что я пытался делать это раньше, но в итоге 14*16*256 вместо того , чтобы 16*16*256 , но все же удалось получить более 2000 кадров в секунду. Я думаю, что Unity не заботится о невидимых треугольниках, но это только я.

Ответ №1:

Во многих случаях люди просто задают кубические треугольники вручную. Добавление циклов не очень выгодно, потому что они будут очень короткими, а логика становится довольно запутанной:

 int nextIndex = 0;
// index offsets that are equivalent to increasing x/y/z by 1
int stepX = Globals.c3to1(1, 0, 0);
int stepY = Globals.c3to1(0, 1, 0);
int stepZ = Globals.c3to1(0, 0, 1);
for (int z = 0; z < Globals.CHUNK_Z; z  ) { //For each aisle
    for (int y = 0; y < Globals.CHUNK_Y; y  ) { //For each row
        for (int x = 0; x < Globals.CHUNK_X; x  ) { //For each column
            int baseVertex = Globals.c3to1(x, y, z);

            // front face
            triangles[nextIndex  ] = baseVertex;
            triangles[nextIndex  ] = baseVertex   stepY;
            triangles[nextIndex  ] = baseVertex   stepX;

            triangles[nextIndex  ] = baseVertex   stepX;
            triangles[nextIndex  ] = baseVertex   stepY;
            triangles[nextIndex  ] = baseVertex   stepX   stepY;

            // repeat equivalently for other faces
        }
    }
}
  

Комментарии:

1. Хорошо, я понял, каков ваш ответ, спасибо за это, однако я получаю дополнительный ряд удлиненных треугольников на обратной стороне одной из граней. Я прикреплю изображения здесь 1 мин.

2. Вот изображения проблемы. Вперед: imgur.com/a/2A5SJ4z В обратном направлении: imgur.com/a/OjxUYey

3. Вероятно, один из ваших индексов отключен. Если вы не нашли, какой именно, закомментируйте по одному треугольнику за раз и посмотрите, когда проблема исчезнет.

Ответ №2:

Этот код не ваш, но он иллюстрирует то, что вы хотите знать. Итак, если вы пройдетесь по этому коду, вы найдете свой ответ.

Об этом коде: Это скрипт на C # для создания цилиндрической сетки во время выполнения

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cylinder : MonoBehaviour
{

    [SerializeField]
    private float radius = 2.0f;
    [SerializeField]
    private float height = 4.0f;

    [SerializeField]
    private int VerticalSubdivisions = 10;
    [SerializeField]
    private int HorizontalSubdivisions = 4;


    private void Start()
    {
        CreateCylinder();
    }

    void CreateCylinder()
    {
        Vector3[] vertices = new Vector3[VerticalSubdivisions * (HorizontalSubdivisions   2)   2];

        float delta_angle = Mathf.PI * 2 / VerticalSubdivisions;
        float delta_height = height / (HorizontalSubdivisions   1);
        for (int j = 0; j < (HorizontalSubdivisions   2); j  )
            for (int i = 0; i < VerticalSubdivisions; i  )
            {
                vertices[1   i   j * VerticalSubdivisions] = new Vector3(Mathf.Cos(delta_angle * i) * radius, delta_height * j - height * 0.5f, Mathf.Sin(delta_angle * i) * radius); 
            }
        vertices[0] = new Vector3(0, -height * 0.5f, 0);
        vertices[vertices.Length - 1] = new Vector3(0, height * 0.5f, 0);

        int[] triangles = new int[6 * VerticalSubdivisions * (HorizontalSubdivisions   1)   VerticalSubdivisions * 2 * 3];

        for (int i = 0; i < (VerticalSubdivisions - 1); i  )
        {
            triangles[i * 3   0] = 0;
            triangles[i * 3   1] = i   1;
            triangles[i * 3   2] = i   2;
        }
        triangles[(VerticalSubdivisions - 1) * 3   0] = 0;
        triangles[(VerticalSubdivisions - 1) * 3   1] = 1   VerticalSubdivisions - 1;
        triangles[(VerticalSubdivisions - 1) * 3   2] = 1;

        int lower_cap_tris_offset = 3 * VerticalSubdivisions;
        for (int j = 0; j < (HorizontalSubdivisions   1); j  )
        {
            for (int i = 0; i < VerticalSubdivisions; i  )
            {
                int index = lower_cap_tris_offset   j * VerticalSubdivisions * 6   6 * i;
                triangles[index   0] = 1   i   VerticalSubdivisions * j;
                triangles[index   1] = 1   VerticalSubdivisions * (j   1)   i;
                triangles[index   2] = 1   VerticalSubdivisions * (j   1)   i   1;

                triangles[index   3] = triangles[index   2];
                triangles[index   4] = 1   i   VerticalSubdivisions * j   1;
                triangles[index   5] = 1   i   VerticalSubdivisions * j; 
            }
            int __index = lower_cap_tris_offset   j * VerticalSubdivisions * 6   6 * (VerticalSubdivisions - 1);
            triangles[__index   0] = 1   VerticalSubdivisions - 1   VerticalSubdivisions * j;
            triangles[__index   1] = 1   VerticalSubdivisions * (j   1)   VerticalSubdivisions - 1;
            triangles[__index   2] = 1   VerticalSubdivisions * (j   1); 
            triangles[__index   3] = triangles[__index   2];
            triangles[__index   4] = 1   VerticalSubdivisions * j;
            triangles[__index   5] = 1   VerticalSubdivisions - 1   VerticalSubdivisions * j; 
        }

        for (int i = 0; i < VerticalSubdivisions - 1; i  )
        {
            int index = 3 * VerticalSubdivisions   VerticalSubdivisions * 6 * (HorizontalSubdivisions   1); 
            triangles[index   i * 3   0] = 1   VerticalSubdivisions * (HorizontalSubdivisions   1)   i;
            triangles[index   i * 3   1] = vertices.Length - 1;
            triangles[index   i * 3   2] = 1   VerticalSubdivisions * (HorizontalSubdivisions   1)   i   1;
        }
        int _index = 3 * VerticalSubdivisions   VerticalSubdivisions * 6 * (HorizontalSubdivisions   1)   (VerticalSubdivisions - 1) * 3;
        triangles[_index   0] = 1   VerticalSubdivisions * (HorizontalSubdivisions   1)   VerticalSubdivisions - 1;
        triangles[_index   1] = vertices.Length - 1;
        triangles[_index   2] = 1   VerticalSubdivisions * (HorizontalSubdivisions   1); 


        Mesh mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh; 
        mesh.Clear();

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }

}
  

Надеюсь, это поможет вам!