Como você gera programaticamente uma esfera?

25

Alguém poderia explicar como seria possível criar vértices, índices e coordenadas de textura de uma esfera? Há uma surpreendente falta de documentação sobre como fazer isso e é algo que estou interessado em aprender.

Eu tentei o óbvio, pesquisando no google, procurando no gamedev.net, etc. No entanto, nada cobre as gerações de pontos esféricos, indexando-os e texturizando.

judeclarke
fonte
6
Não vou votar ou votar para encerrar isso, mas você está realmente me dizendo que nem um único resultado do google.com/search?q=how+to+generate+a+sphere+vertices foi útil? Nesse caso, você precisará explicar qual é o seu problema com mais detalhes.
Pesquisar por icosfera Muito mais esperta que a "esfera polar" burra, que produz rostos inúteis.
Notabene
3
Vale ressaltar que, para alguns propósitos simples, uma "esfera" perfeitamente fina é um quad com uma textura circular voltada para a câmera.
aaaaaaaaaaaa 30/08
Aqui está como eu o implementei para o skydome no meu jogo.
danijar

Respostas:

36

Existem duas abordagens gerais:

insira a descrição da imagem aqui

O extremo esquerdo é denominado esfera uv e o extremo direito, icosfera.

GLUT tende a usar a abordagem uv: observe a função glutSolidSphere()no código-fonte freeglut .

Aqui está um excelente artigo sobre a produção de uma icosfera: http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html

A esfera uv parece um globo. Para muitos propósitos, é perfeitamente adequado, mas para alguns casos de uso, por exemplo, se você deseja deformar a esfera, é desvantajoso que a densidade dos vértices seja maior ao redor dos polos. Aqui a icosfera é melhor, seus vértices são distribuídos uniformemente.

Você também pode achar isso interessante: http://kiwi.atmos.colostate.edu/BUGS/geodesic/text.html descreve uma abordagem para organizar as faces em zonas.

http://vterrain.org/Textures/spherical.html fornece uma excelente descrição de como você pode optar por texturizá-las.

Vai
fonte
2
Embora a idéia geral seja boa, subdividir um politopo Schläfli {3,5} não é a única maneira de fazê-lo. Geralmente, prefiro trabalhar com a família Schläfli {4, *} ({4,3} no caso de uma esfera) para fins de mapeamento UV.
Martin Sojka
Esferas icosaédricas finamente em mosaico são um pouco mais caras para gerar devido à necessidade de subdividir recursivamente as faces.
bobobobo
9

Existem 2 maneiras de fazer isso:

  1. Ande theta e phi em coordenadas esféricas, gere faces e tris

  2. Crie um icosaedro e subdividir recursivamente as faces até atingir o mosaico desejado.

Esfera usando coordenadas esféricas andar

Pela primeira vez, basta usar um aninhado duplo para caminhar theta e phi. Ao andar com theta e phi, você gira triângulos para criar sua esfera.

insira a descrição da imagem aqui

O código que faz isso será mais ou menos assim:

for( int t = 0 ; t < stacks ; t++ ) // stacks are ELEVATION so they count theta
{
  real theta1 = ( (real)(t)/stacks )*PI ;
  real theta2 = ( (real)(t+1)/stacks )*PI ;

  for( int p = 0 ; p < slices ; p++ ) // slices are ORANGE SLICES so the count azimuth
  {
    real phi1 = ( (real)(p)/slices )*2*PI ; // azimuth goes around 0 .. 2*PI
    real phi2 = ( (real)(p+1)/slices )*2*PI ;

    //phi2   phi1
    // |      |
    // 2------1 -- theta1
    // |\ _   |
    // |    \ |
    // 3------4 -- theta2
    //

    //vertex1 = vertex on a sphere of radius r at spherical coords theta1, phi1
    //vertex2 = vertex on a sphere of radius r at spherical coords theta1, phi2
    //vertex3 = vertex on a sphere of radius r at spherical coords theta2, phi2
    //vertex4 = vertex on a sphere of radius r at spherical coords theta2, phi1

    // facing out
    if( t == 0 ) // top cap
      mesh->addTri( vertex1, vertex3, vertex4 ) ; //t1p1, t2p2, t2p1
    else if( t + 1 == stacks ) //end cap
      mesh->addTri( vertex3, vertex1, vertex2 ) ; //t2p2, t1p1, t1p2
    else
    {
      // body, facing OUT:
      mesh->addTri( vertex1, vertex2, vertex4 ) ;
      mesh->addTri( vertex2, vertex3, vertex4 ) ;
    }
  }
}

Observe acima, é importante enrolar a tampa superior e inferior usando apenas tris, não quads.

Esfera icosaédrica

Para usar um icosaedro, você apenas gera os pontos do icosaedro e termina triângulos a partir dele. Os vértices de um icosaedro sentado na origem são:

(0, ±1, ±φ)
1, ±φ, 0)
(±φ, 0, ±1)
where φ = (1 + 5) / 2 

Você então precisa apenas olhar o diagrama de um icosaedro e as faces do vento a partir desses verts. Eu já tenho um código que faz isso aqui .

bobobobo
fonte
alguma idéia de como obter o meio corpo, como de theta = pi / 4 a theta = 3pi * 4? Como esta imagem: i.stack.imgur.com/Jjx2c.jpg Passei dias com isso não consegui resolver.
Tina J
3

Se os pontos não precisam ser localmente uniformes, mas devem ser globalmente uniformes e não precisam seguir nenhum padrão definido, você pode usar uma variante do algoritmo de arremesso de dardos para distribuir n pontos em uma esfera com raio r , em média dist pontos distantes. Esses valores são aproximadamente:

  1. Se você deseja ter uma quantidade específica de vértices:
    • n = (quantidade desejada de vértices)
    • dist = 2 × r × √ ( π / n )
  2. Se você deseja ter uma distância média específica entre os vértices:
    • n = 4 × π × ( r / dist ) 2
    • dist = (distância média desejada)

No caso mais simples, você pode escolher uniformemente pontos aleatoriamente, escolhendo duas variáveis ​​uniformemente distribuídas u e v de (0, 1) e calculando as coordenadas polares a partir delas de acordo com as fórmulas θ = 2 × π × u e ϕ = arco cos (2 x v - 1); descartando pontos que estejam muito próximos dos pontos já escolhidos. Para um algoritmo um pouco mais complexo e com desempenho significativamente melhor, consulte " Dart Throwing on Surfaces " de Cline, Jeschke, White, Razdan e Wonka.

Depois de escolher seus quatro primeiros pontos (supondo que nenhum deles seja degenerado , ou seja - eles não estão no mesmo grande círculo, mas isso é altamente improvável), você pode criar quatro faces entre eles e cada vez que adicionar um novo ponto, você pode dividir a face à qual pertence de acordo com três sub-faces.

Para fins de texturização, você pode mapear os pontos para um mapa de cubo.

Martin Sojka
fonte