Quelqu'un at-il un algorithme pour créer une sphère procédurale avec une la
quantité de lignes de latitude, une lo
quantité de lignes de longitude et un rayon de r
? J'en ai besoin pour travailler avec Unity, donc les positions des sommets doivent être définies puis les triangles définis via les index ( plus d'infos ).
MODIFIER
J'ai réussi à faire fonctionner le code dans l'unité. Mais je pense que j'aurais pu faire quelque chose de mal. Quand je monte le detailLevel
, tout ce qu'il fait est d'ajouter plus de sommets et de polygones sans les déplacer. Ai-je oublié quelque chose?
EDIT 2
J'ai essayé de redimensionner le maillage le long de ses normales. Voilà ce que j'ai. Je pense que je manque quelque chose. Suis-je censé mettre à l'échelle uniquement certaines normales?
la source
vertices[i] = normalize(vertices[i])
. Soit dit en passant, cela vous donne également vos nouvelles normales correctes, vous devriez donc le fairenormals[i] = vertices[i]
par la suite.Réponses:
Pour obtenir quelque chose comme ça:
Créez un icosaèdre (solide régulier à 20 faces) et subdivisez les faces pour obtenir une sphère (voir le code ci-dessous).
L'idée est essentiellement:
Subdivisez chaque face en quatre faces de même taille. Chaque fois que vous faites cela, cela quadruplera le nombre de faces dans le modèle.
i0
,,i1
eti2
sont les sommets du triangle d'origine. (En fait, les index dans le tampon de vertex, mais c'est un autre sujet).m01
est le milieu du bord(i0,i1)
, m12 est le milieu du bord(i1,12)
, etm02
est, évidemment, le milieu du bord(i0,i2)
.Chaque fois que vous subdivisez une face, assurez-vous de ne pas créer de sommets en double. Chaque point médian sera partagé par une autre face source (car les bords sont partagés entre les faces). Le code ci-dessous en tient compte en conservant un dictionnaire des points médians nommés qui ont été créés et en renvoyant l'index d'un point médian créé précédemment lorsqu'il est disponible plutôt que d'en créer un nouveau.
Répétez jusqu'à ce que vous ayez atteint le nombre de faces souhaité pour votre cube.
Lorsque vous avez terminé, normalisez tous les sommets pour lisser la surface. Si vous ne le faites pas, vous obtiendrez simplement un icosaèdre de plus haute résolution au lieu d'une sphère.
Voila! Vous avez terminé. Convertissez le vecteur résultant et les tampons d'index en a
VertexBuffer
etIndexBuffer
, et dessinez avecDevice.DrawIndexedPrimitives()
.Voici ce que vous utiliseriez dans votre classe "Sphère" pour créer le modèle (types de données XNA et C #, mais cela devrait être assez clair):
Et la
GeometryProvider
classela source
int
tableau? Et que fait-.Select(i => i + vertices.Count)
il?.Select(i => i + vertices.Count)
ne fonctionne pas pour moi du tout. Est-ce une fonctionnalité XNA uniquement?Considérons la définition paramétrique d'une sphère:
où thêta et phi sont deux angles d'incrémentation, que nous désignerons par
var t
etvar u
et Rx, Ry et Rz sont les rayons (rayons) indépendants dans les trois directions cartésiennes, qui, dans le cas d'une sphère, seront définis comme un seul rayonvar rad
.Considérons maintenant le fait que le
...
symbole indique une itération qui suggère l'utilisation d'une boucle. Le concept destacks
etrows
est "combien de fois allez-vous répéter". Puisque chaque itération ajoute la valeur de t ou u, plus il y a d'itérations, plus la valeur est petite, donc plus la courbure de la sphère est précise.La condition sine qua non de la fonction « dessin de la sphère » est d'avoir les paramètres donnés suivants:
int latitudes, int longitudes, float radius
. Les conditions de post (sortie) sont de retourner ou d'appliquer les sommets calculés. Selon la façon dont vous comptez l'utiliser, la fonction peut renvoyer un tableau devector3
(vecteurs tridimensionnels) ou, si vous utilisez une sorte d'OpenGL simple, avant la version 2.0, vous souhaiterez peut-être appliquer directement les sommets au contexte.NB L'application d'un sommet en openGL appelle la fonction suivante
glVertex3f(x, y, z)
. Dans le cas où nous stockerions les sommets, nous ajouterions un nouveauvector3(x, y, z)
pour un stockage facile.De plus, la façon dont vous avez demandé le fonctionnement du système de latitude et de longitude nécessitait un ajustement de la définition de la sphère (essentiellement en changeant z et y), mais cela montre simplement que la définition est très malléable et que vous êtes libre de changer de Paramètres x, y et z pour modifier la direction dans laquelle la sphère est dessinée (où se trouvent les latitudes et les longitudes).
Voyons maintenant comment nous allons faire les latitudes et les longitudes. Les latitudes sont représentées par la variable
u
, elles itèrent de 0 à 2π radians (360 degrés). On peut donc coder son itération comme ceci:Maintenant, les longitudes sont représentées par la variable
t
et itèrent de 0 à π (180 degrés). par conséquent, le code suivant ressemble au précédent:(Notez que les boucles incluent la condition terminale, car l'intervalle d'intégration paramétrique est compris entre 0 et 2π inclus . Vous obtiendrez une sphère partielle si vos conditions ne sont pas inclusives.)
Maintenant, en suivant la définition simple de la sphère, nous pouvons dériver la définition de variable comme suit (supposons
float rad = radius;
):Encore un avertissement important! Dans la plupart des cas, vous utiliserez une forme d'OpenGL, et même si ce n'est pas le cas, vous devrez peut-être le faire. Un objet en trois dimensions a besoin de plusieurs sommets pour être défini. Ceci est généralement réalisé en fournissant le sommet suivant qui est calculable.
À quel point dans la figure ci-dessus les différentes coordonnées sont
x+∂
ety+∂
, nous pouvons facilement générer trois autres sommets pour toute utilisation souhaitée. Les autres sommets sont (supposonsfloat rad = radius;
):Enfin, voici une fonction complète qui retournerait tous les sommets d'une sphère, et la seconde montre une implémentation OpenGL fonctionnelle du code (c'est la syntaxe de style C et non JavaScript, cela devrait fonctionner avec tous les langages de style C, y compris C # lors de l'utilisation de Unity).
Code OpenGL:
PS Vous avez peut-être remarqué cette déclaration
rad = radius;
. Cela permet de modifier le rayon dans la boucle, en fonction de l'emplacement ou de l'angle. Cela signifie que vous pouvez appliquer du bruit à la sphère pour la rendre rugueuse, la rendant plus naturelle si l'effet souhaité est de type planète. Par exemplefloat rad = radius * noise[x][y][z];
Claude-Henry.
la source
rad
. Maintenant, vous faites cette jambe d'un triangle, et sous-entend que l'hypoténuse dudit triangle l'est égalementrad
. Cela vous donne effectivement un rayon derad * sqrt(2)
.J'ai créé quelque chose comme ça il y a quelque temps pour créer une sphère de cubes, pour le plaisir et la science. Ce n'est pas trop dur. Fondamentalement, vous prenez une fonction qui crée un cercle de sommets, puis parcourez les incréments de hauteur que vous souhaitez créer des cercles à chaque hauteur au rayon requis pour créer une sphère. Ici, j'ai modifié le code pour ne pas être pour les cubes:
Maintenant, ce code ne ferait que créer des points pour la latitude. Cependant, vous pouvez presque utiliser le même code pour créer les lignes de longitude. Sauf que vous devrez tourner entre chaque itération et faire un cercle complet à chaque
degreeStep
.Désolé, ce n'est pas une réponse complète ou spécifique à Unity, mais j'espère que cela vous aidera à démarrer.
la source
Ne pourriez-vous pas simplement commencer avec une forme simple, pourrait être une boîte avec une distance r du centre au coin. Pour créer une sphère plus détaillée, subdivisez tous les polygones, puis déplacez les sommets à une distance r du centre, le vecteur passant par sa position actuelle.
Continuez à répéter jusqu'à ce que suffisamment sphérique pour vos goûts.
la source
Avez-vous réellement besoin de la géométrie 3D ou simplement de la forme?
Vous pouvez créer une "fausse" sphère en utilisant un seul quad. Il suffit de mettre un cercle dessus et de l'ombrer correctement. Cela a l'avantage d'avoir exactement la résolution requise quelle que soit la distance à la caméra ou la résolution.
Il y a un tutoriel ici .
la source
voici un code pour n'importe quel nombre de sommets également espacés d'une sphère, c'est comme une peau d'orange qui enroule une ligne de points autour d'une sphère en spirale. ensuite, la façon dont vous joignez les sommets dépend de vous. vous pouvez utiliser des points voisins dans la boucle en tant que 2 de chaque triangle, puis trouver le troisième serait une torsion proportionnelle autour de la sphère plus haut ou plus bas ... vous pouvez également faire des triangles par boucle et le plus proche voisin, fait quelqu'un connaissez une meilleure façon?
};
la source
Bien que David ait tout à fait raison dans sa réponse, je veux offrir une perspective différente.
Pour ma mission de génération de contenu procédural, j'ai examiné (entre autres choses) l'icosaèdre par rapport à des sphères subdivisées plus traditionnelles. Regardez ces sphères générées de manière procédurale:
Les deux ressemblent à des sphères parfaitement valides, non? Eh bien, regardons leurs wireframes:
Wow, que s'est-il passé là-bas? La version filaire de la deuxième sphère est si dense qu'elle a l'air texturée! Je vais vous dévoiler un secret: la deuxième version est un icosaèdre. C'est une sphère presque parfaite, mais elle a un prix élevé.
La sphère 1 utilise 31 subdivisions sur l'axe des x et 31 subdivisions sur l'axe des z, pour un total de 3 844 faces.
Sphère 2 utilise 5 subdivisions récursives, pour un total de 109 220 faces.
Mais d'accord, ce n'est pas vraiment juste. Réduisons considérablement la qualité:
La sphère 1 utilise 5 subdivisions sur l'axe des x et 5 subdivisions sur l'axe des z, pour un total de 100 faces.
Sphère 2 utilise 0 subdivisions récursives, pour un total de 100 faces.
Ils utilisent la même quantité de visages, mais à mon avis, la sphère de gauche semble meilleure. Il semble moins bosselé et beaucoup plus rond. Jetons un coup d'œil au nombre de visages que nous générons avec les deux méthodes.
Icosaèdre:
Sphère subdivisée:
Comme vous pouvez le voir, l'icosaèdre augmente de visages à un rythme exponentiel, à une troisième puissance! En effet, pour chaque triangle, nous devons les subdiviser en trois nouveaux triangles.
La vérité est: vous n'avez pas besoin de la précision qu'un icosaèdre vous donnera. Parce qu'ils cachent tous les deux un problème beaucoup plus difficile: texturer un plan 2D sur une sphère 3D. Voici à quoi ressemble le haut:
En haut à gauche, vous pouvez voir la texture utilisée. Par coïncidence, il est également généré de manière procédurale. (Hé, c'était un cours sur la génération procédurale, non?)
Ça a l'air terrible, non? Eh bien, c'est aussi bon que ça va arriver. J'ai obtenu les meilleures notes pour mon mappage de texture, car la plupart des gens ne comprennent même pas cela correctement.
Alors s'il vous plaît, pensez à utiliser le cosinus et le sinus pour générer une sphère. Il génère beaucoup moins de visages pour la même quantité de détails.
la source
N
pièces vous donnera deN*N
nouveaux triangles, qui sont quadratiques, exactement comme ce que vous faites avec la sphère UV.Le script ci-dessous créera un Icosaèdre avec n Polygones ... base 12. Il subdivisera également les polygones en maillages séparés et calculera le total des verts-doublons et des polygones.
Je n'ai rien trouvé de similaire alors j'ai créé ça. Attachez simplement le script à un GameObject et définissez les subdivisions dans l'éditeur. Travail sur la modification du bruit ensuite.
la source