5 votes

Mesh de cercle procédural avec des faces uniformes

Je cherche à créer un cercle 2D de manière procédurale avec des faces uniformes comme ceci.

description de l'image ici

Normalement, je le créerais avec une structure de ventilateur triangulaire, mais j'ai besoin que les faces soient approximativement identiques. J'ai cherché des exemples, mais je n'ai pu trouver que des exemples de "cube en sphère". Un compromis pourrait être quelque chose de similaire à ceci :

description de l'image ici

Pouvez-vous m'aider à trouver un moyen de dessiner cette structure? J'aimerais le faire en C# mais du js ou même du pseudo-code feraient l'affaire!

Merci beaucoup

7voto

Yuri Nudelman Points 2178

Vous m'avez intéressé avec votre question, et je pense avoir la solution que vous recherchiez. Voici comment nous pouvons créer la topologie que vous désiriez :

1) Nous commençons par un hexagone. Pourquoi un hexagone et pas une autre forme ? Parce que l'hexagone est la seule forme magique avec son rayon égal à la longueur de son côté. Nous appellerons ce rayon R. Nous allons maintenant essayer de créer une forme qui ressemble à un cercle et qui est constituée de triangles avec une longueur de côté approximativement R.

2) Maintenant, imaginez des cercles concentriques, avec des rayons R, 2R, 3R et ainsi de suite - plus il y en a, plus la résolution est élevée.

3) Le cercle numéro 1 a un rayon R. Nous allons maintenant remplacer ce cercle par un hexagone avec un rayon R.

Exemple 1

4) Nous allons maintenant ajouter plus de nœuds sur le deuxième cercle pour étendre notre hexagone. Quelle est la circonférence du cercle numéro N ? C'est 2PiRN. Maintenant, nous voulons le diviser en X arêtes d'une longueur d'environ R. Ainsi, X=2PiN, ce qui est approximativement 6N. Nous allons donc diviser le premier cercle en 6 arêtes (hexagone), le deuxième en 12, puis 18, 24, et ainsi de suite.

5) Maintenant, nous avons beaucoup de cercles divisés en arêtes. Nous devons maintenant connecter les arêtes en triangles. Comment construire des triangles entre le cercle N (extérieur) et N-1 (intérieur) ? Le cercle extérieur a 6 arêtes de plus que le cercle intérieur. S'ils avaient un nombre identique de sommets, nous pourrions les connecter avec des quadrilatères. Mais ce n'est pas le cas. Ainsi, nous essaierons quand même de construire des quadrilatères, mais pour chaque quadrilatère que nous construisons pour N, nous devrons ajouter 1 triangle. Chaque quadrilatère utilise 2 sommets du cercle intérieur et 2 sommets du cercle extérieur. Chaque triangle utilise 2 sommets du cercle extérieur et seulement 1 du cercle intérieur, compensant ainsi l'excès de sommets.

Exemple 2

6) Et enfin, voici un code d'exemple testé qui fait ce dont vous avez besoin. Il générera un cercle avec une topologie uniforme, avec un point central à l'origine et un rayon de 1, divisé en *cercles secondaires de résolution. Il pourrait bénéficier d'une légère optimisation des performances (ce qui est hors de propos pour le moment), mais dans l'ensemble, cela devrait faire l'affaire.

using System.Collections.Generic;
using UnityEngine;

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

    public int resolution = 4;

    // Use this for initialization
    void Start() {
        GetComponent().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; // En cas de point central
        x = x % ((c + 1) * 6); // Créer un index circulaire
                               // Explication : index = nombre de points dans les cercles précédents + point central + x
                               // donc : (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();
        vtc.Add(Vector3.zero); // Commencer avec seulement le point central
        var tris = new List();

        // Première passe => construire les sommets
        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));
            }
        }

        // Deuxième passe => connecter les sommets en triangles
        for (int circ = 0; circ < res; ++circ) {
            for (int point = 0, other = 0; point < (circ + 1) * 6; ++point) {
                if (point % (circ + 1) != 0) {
                    // Créer 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 {
                    // Créer 1 triangle inverse
                    tris.Add(GetPointIndex(circ, point));
                    tris.Add(GetPointIndex(circ, point + 1));
                    tris.Add(GetPointIndex(circ - 1, other));
                    // Ne pas passer au point suivant dans le cercle plus petit
                }
            }
        }

        // Créer le maillage
        var m = new Mesh();
        m.SetVertices(vtc);
        m.SetTriangles(tris, 0);
        m.RecalculateNormals();
        m.UploadMeshData(true);

        return m;

    }
}

Résultat Final :

entrez la description de l'image ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X