Unity3D: можно ли динамически изменять вершину в me sh без пересчета треугольников, uv и нормалей? - PullRequest
0 голосов
/ 06 августа 2020

Я успешно создал куб по этому коду: http://wiki.unity3d.com/index.php/ProceduralPrimitives и с текстурой получил следующее:

enter image description here

But if I try to change one vertex's position, half of the triangles get inverted such as shown in the following screen.
I also tried to change all of the vertices at once by giving them the exact same values ( I copy / pasted the code used to create the vertices ) and reassign the vertices with mesh.vertices = vertices but I get the exact same triangle problem

введите описание изображения здесь

Все треугольники есть, но половина из них в конечном итоге отражается внутри меня sh, и форма куба теряется.

Когда я также пересчитываю треугольники текстура находится не на своем месте, и мне нужно пересчитать нормали и UV, если я хочу, чтобы куб выглядел нормально.

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

Есть ли способ изменить форму моего куба, не пересчитывая все? Я не добавляю / удаляю вершины, и куб не скручивается / не деформируется (верхняя левая вершина остается верхней левой вершиной и так далее)

Примечание : Я sh, чтобы изменить положение вершин во время выполнения

Изменить : это код, который вызывает ошибку:

    float width = 10f;
    float height = 10f;
    float length = 10f;
    Vector3 p0 = new Vector3(-width * .5f, -height * .5f, length * .5f);
    Vector3 p1 = new Vector3(width * .5f, -height * .5f, length * .5f);
    Vector3 p2 = new Vector3(width * .5f, -height * .5f, -length * .5f);
    Vector3 p3 = new Vector3(-width * .5f, -height * .5f, -length * .5f);
    Vector3 p4 = new Vector3(-width * .5f, height * .5f, length * .5f);
    Vector3 p5 = new Vector3(width * .5f, height * .5f, length * .5f);
    Vector3 p6 = new Vector3(width * .5f, height * .5f, -length * .5f);
    Vector3 p7 = new Vector3(-width * .5f, height * .5f, -length * .5f);

    Vector3[] vertices = new Vector3[] {
        // Bottom
        p0, p1, p2, p3,
        // Left
        p7, p4, p0, p3,
        // Front
        p4, p5, p1, p0,
        // Back
        p6, p7, p3, p2,
        // Right
        p5, p6, p2, p1,
        // Top
        p7, p6, p5, p4
    };
    _selectionBoxMeshFilter.mesh.vertices = vertices;

Это тот же код, что и использовался для создания me sh в первую очередь. Me sh делает странные вещи, когда он вызывается после того, как me sh был создан.

1 Ответ

2 голосов
/ 06 августа 2020

mesh.Optimize переупорядочивает vertices и переупорядочивает triangles, чтобы сделать рендеринг более эффективным.

Вы не заменяете текущие значения vertices теми же значений, потому что в этом случае порядок оказывается другим.

Чтобы решить эту проблему, не предполагайте, что вершины будут находиться в том же месте, что и при назначении mech.vertices .

Одним из решений может быть отображение индексов для каждой вершины после вызова mesh.Optimize и назначение / редактирование вершин на основе этого:

private List<int> indicesOfP0;

// ...

_selectionBoxMeshFilter.mesh.Optimize();

indicesOfP0 = new List<int>();
for (int i = 0 ; i < _selectionBoxMeshFilter.mesh.vertices.Length ; i++)
{
    if (_selectionBoxMeshFilter.mesh.vertices[i] == p0)
    { 
        indicesOfP0.Add(i);
    } 
}

// ...

Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
foreach (int i in indicesOfP0)
{
    vertices[i] += Vector3.up * Time.deltaTime;
}
_selectionBoxMeshFilter.mesh.vertices = vertices;

Лучшим вариантом, вероятно, было бы просто вычислить, что делать с каждой вершиной на основе ее положения:

Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
for (int i = 0; i < vertices.Length; i++)
{
    if (vertices[i].y>0) 
    {
        vertices[i] += Vector3.up * Time.deltaTime;
    }
}
_selectionBoxMeshFilter.mesh.vertices = vertices;

Но если вы должны назначить массив позиций, подумайте о том, чтобы основывать его на позициях после mesh.Optimize называется:

private Vector3[] startPos;

// ...

_selectionBoxMeshFilter.mesh.Optimize();

startPos = _selectionBoxMeshFilter.mesh.vertices;

// ...

_selectionBoxMeshFilter.mesh.vertices = startPos;
...