Процедурная круговая сетка с однородными гранями - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь создать 2-й круг процедурно с одинаковыми лицами, вот так.

enter image description here

Обычно я создавал бы его с треугольной структурой вееров , но мне нужно, чтобы грани были примерно одинаковыми.Я искал примеры, но я мог только найти примеры "куб в сферу".Компромисс может быть чем-то похожим на это:

enter image description here

Не могли бы вы помочь мне найти способ нарисовать эту структуру?Я хотел бы сделать это в C #, но js или даже псевдокод подойдет!

Большое спасибо

1 Ответ

0 голосов
/ 22 ноября 2018

Вы заинтересовали меня своим вопросом, и я думаю, что у меня есть решение, которое вы искали.Вот как мы можем создать желаемую топологию:

1) Начнем с шестиугольника.Почему шестиугольник, а не другая форма?Потому что шестиугольник - единственная магическая форма с радиусом, равным длине его стороны.Мы назовем этот радиус R .Теперь мы попытаемся создать форму, которая напоминает круг и состоит из треугольников с длиной стороны приблизительно R .

2) Теперь представим несколько концентрических кругов с радиусом R, 2R, 3R и т. Д. - чем больше, тем выше разрешение.

3) Круг с номером 1 имеет радиус R .Теперь мы заменим этот круг шестиугольником с радиусом R .

Example 1

4) Теперь мы добавим больше узлов на секундукруг, чтобы расширить наш шестиугольник.Какова окружность круга с номером N ?Это 2PiRN .Теперь мы хотим разделить его на X ребер длиной примерно R .Следовательно, X = 2PiN , что приблизительно равно 6N .Итак, мы разделим первый круг на 6 ребер (шестиугольник), второй на 12, затем 18, 24 и т. Д.

5) Теперь у нас есть много кругов, разделенных на ребра.Теперь нам нужно соединить ребра в треугольники.Как мы строим треугольники между кругом N (внешний) и N-1 (внутренний)?Внешний круг имеет на 6 ребер больше, чем внутренний.Если бы у них было одинаковое количество вершин, мы могли бы связать их с квадратами.Но они этого не делают.Итак, мы все же попытаемся построить квады, но для каждого N построенных нами квадратов нам нужно будет добавить 1 треугольник.Каждый квад использует 2 вершины из внутренней и 2 вершины из внешней окружности.Каждый треугольник использует 2 вершины из внешнего круга и только 1 из внутреннего, таким образом компенсируя избыток вершин.

Example 2

6) И теперь, наконец,есть несколько проверенных примеров кода, который делает то, что вам нужноОн сгенерирует окружность с однородной топологией, с центральной точкой в ​​начале координат и радиусом 1, разделенной на подкруги * разрешения.Он может использовать некоторую незначительную оптимизацию производительности (пока это выходит за рамки), но в целом он должен делать свою работу.

using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
public class UniformCirclePlane : MonoBehaviour {

    public int resolution = 4;

    // Use this for initialization
    void Start() {
        GetComponent<MeshFilter>().mesh = GenerateCircle(resolution);
    }

    // Update is called once per frame
    void Update() {

    }

    // Get the index of point number 'x' in circle number 'c'
    static int GetPointIndex(int c, int x) {
        if (c < 0) return 0; // In case of center point
        x = x % ((c + 1) * 6); // Make the point index circular
                               // Explanation: index = number of points in previous circles + central point + x
                               // hence: (0+1+2+...+c)*6+x+1 = ((c/2)*(c+1))*6+x+1 = 3*c*(c+1)+x+1

        return (3 * c * (c + 1) + x + 1);
    }

    public static Mesh GenerateCircle(int res) {

        float d = 1f / res;

        var vtc = new List<Vector3>();
        vtc.Add(Vector3.zero); // Start with only center point
        var tris = new List<int>();

        // First pass => build vertices
        for (int circ = 0; circ < res; ++circ) {
            float angleStep = (Mathf.PI * 2f) / ((circ + 1) * 6);
            for (int point = 0; point < (circ + 1) * 6; ++point) {
                vtc.Add(new Vector2(
                    Mathf.Cos(angleStep * point),
                    Mathf.Sin(angleStep * point)) * d * (circ + 1));
            }
        }

        // Second pass => connect vertices into triangles
        for (int circ = 0; circ < res; ++circ) {
            for (int point = 0, other = 0; point < (circ + 1) * 6; ++point) {
                if (point % (circ + 1) != 0) {
                    // Create 2 triangles
                    tris.Add(GetPointIndex(circ - 1, other + 1));
                    tris.Add(GetPointIndex(circ - 1, other));
                    tris.Add(GetPointIndex(circ, point));
                    tris.Add(GetPointIndex(circ, point));
                    tris.Add(GetPointIndex(circ, point + 1));
                    tris.Add(GetPointIndex(circ - 1, other + 1));
                    ++other;
                } else {
                    // Create 1 inverse triange
                    tris.Add(GetPointIndex(circ, point));
                    tris.Add(GetPointIndex(circ, point + 1));
                    tris.Add(GetPointIndex(circ - 1, other));
                    // Do not move to the next point in the smaller circle
                }
            }
        }

        // Create the mesh
        var m = new Mesh();
        m.SetVertices(vtc);
        m.SetTriangles(tris, 0);
        m.RecalculateNormals();
        m.UploadMeshData(true);

        return m;

    }
}

Окончательный результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...