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.
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.
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 :