Alguém tem um algoritmo para criar uma esfera processualmente com la
quantidade de linhas de latitude, lo
quantidade de linhas de longitude e raio de r
? Eu preciso que ele trabalhe com o Unity, para que as posições dos vértices precisem ser definidas e, em seguida, os triângulos definidos por meio de índices ( mais informações ).
EDITAR
Consegui fazer o código funcionar em unidade. Mas acho que posso ter feito algo errado. Quando eu ligo o detailLevel
, Tudo o que faz é adicionar mais vértices e polígonos sem movê-los. Eu esqueci alguma coisa?
EDIT 2
Tentei escalar a malha ao longo de suas normais. Isto é o que eu tenho. Eu acho que estou perdendo alguma coisa. Devo escalar apenas certos normais?
unity
procedural-generation
3d-meshes
Daniel Pendergast
fonte
fonte
vertices[i] = normalize(vertices[i])
. Aliás, isso também fornece suas novas e corretas normais, então você deve fazernormals[i] = vertices[i]
depois.Respostas:
Para obter algo assim:
Crie um icosaedro (sólido regular de 20 lados) e subdividir as faces para obter uma esfera (consulte o código abaixo).
A ideia é basicamente:
Subdividir cada face em quatro faces do mesmo tamanho. Cada vez que você fizer isso, ele quadruplicará o número de faces no modelo.
i0
,i1
Ei2
são os vértices do triângulo original. (Na verdade, índices no buffer de vértice, mas esse é outro tópico).m01
é o ponto médio da aresta(i0,i1)
, m12 é o ponto médio da aresta(i1,12)
em02
é, obviamente, o ponto médio da aresta(i0,i2)
.Sempre que você subdividir uma face, não crie vértices duplicados. Cada ponto médio será compartilhado por uma outra face de origem (já que as arestas são compartilhadas entre as faces). O código abaixo explica isso mantendo um dicionário de pontos médios nomeados que foram criados e retornando o índice de um ponto médio criado anteriormente quando estiver disponível, em vez de criar um novo.
Repita até atingir o número desejado de faces para o seu cubo.
Quando terminar, normalize todos os vértices para suavizar a superfície. Se você não fizer isso, obterá um icosaedro de maior resolução em vez de uma esfera.
Voila! Você está feito. Converta o vetor resultante e os buffers de índice em
VertexBuffer
eIndexBuffer
, e desenhe comDevice.DrawIndexedPrimitives()
.Aqui está o que você usaria na classe "Sphere" para criar o modelo (tipos de dados XNA e C #, mas deve ficar bem claro):
E a
GeometryProvider
classefonte
int
matriz? E o que.Select(i => i + vertices.Count)
faz?.Select(i => i + vertices.Count)
não funciona para mim. É um recurso exclusivo do XNA?Vamos considerar a definição paramétrica de uma esfera:
onde theta e phi são dois ângulos incrementais, aos quais iremos nos referir como
var t
evar u
e Rx, Ry e Rz são os raios independentes (raios) nas três direções cartesianas, que, no caso de uma esfera, serão definidos como um único raiovar rad
.Vamos agora considerar o fato de que o
...
símbolo indica uma iteração que sugere o uso de um loop. O conceito destacks
erows
é "quantas vezes você iterará". Como cada iteração adiciona o valor de t ou u, quanto mais iterações, menor o valor, portanto, mais precisa é a curvatura da esfera.A pré-condição da função 'desenho da esfera' é ter os seguintes parâmetros fornecidos:
int latitudes, int longitudes, float radius
. As condições de postagem (saída) são para retornar ou aplicar os vértices calculados. Dependendo de como você pretende usar isso, a função pode retornar uma matriz devector3
(vetores tridimensionais) ou, se você estiver usando algum tipo de OpenGL simples, anterior à versão 2.0, poderá aplicar os vértices ao contexto diretamente.NB A aplicação de um vértice no openGL está chamando a seguinte função
glVertex3f(x, y, z)
. No caso em que armazenaríamos os vértices, adicionaríamos um novovector3(x, y, z)
para facilitar o armazenamento.Além disso, a maneira como você solicitou o funcionamento do sistema de latitude e longitude precisava de um ajuste na definição da esfera (basicamente alternando z e y), mas isso apenas mostra que a definição é muito maleável e que você é livre para alternar entre as esferas. parâmetros x, ye z para alterar a direção em que a esfera é desenhada (onde estão as latitudes e longitudes).
Agora vamos ver como vamos fazer as latitudes e longitudes. As latitudes são representadas pela variável
u
, elas iteram de 0 a 2π radianos (360 graus). Portanto, podemos codificar sua iteração da seguinte maneira:Agora as longitudes são representadas pela variável
t
e iteram de 0 a π (180 graus). portanto, o código a seguir é semelhante ao anterior:(Note-se que loops são Inclusive de lá condição terminal, porque o intervalo para a integração paramétrico é de 0 a 2p Inclusive . Você terá uma esfera parcial se suas condições são não-inclusive.)
Agora, seguindo a definição simples da esfera, podemos derivar a definição da variável da seguinte forma (suponha
float rad = radius;
):Mais um aviso importante! Na maioria dos casos, você usará algum tipo de OpenGL, e mesmo se não estiver, talvez ainda precise fazer isso. Um objeto tridimensional precisa de vários vértices para serem definidos. Isso geralmente é conseguido fornecendo o próximo vértice que é computável.
Exatamente como na figura acima estão as diferentes coordenadas
x+∂
ey+∂
, podemos facilmente gerar três outros vértices para qualquer uso desejado. Os outros vértices são (assumafloat rad = radius;
):Finalmente, aqui está uma função completa que retornaria todos os vértices de uma esfera, e a segunda mostra uma implementação de código OpenGL funcional (essa é a sintaxe no estilo C e não o JavaScript, isso deve funcionar com todas as linguagens no estilo C, incluindo C # ao usar o Unity).
Código OpenGL:
PS Você pode ter notado esta afirmação
rad = radius;
. Isso permite que o raio seja modificado no loop, com base na localização ou no ângulo. Isso significa que você pode aplicar ruído à esfera para torná-la áspera, tornando-a mais natural se o efeito desejado for semelhante ao de um planeta. Por exemplofloat rad = radius * noise[x][y][z];
Claude-Henry.
fonte
rad
. Agora você está criando essa perna de um triângulo e implicando que a hipotenusa do referido triângulo também érad
. Isso efetivamente fornece um raio derad * sqrt(2)
.Eu criei algo assim um tempo atrás para fazer uma esfera de cubos, por diversão e ciência. Não é muito difícil. Basicamente, você utiliza uma função que cria um círculo de vértices e, em seguida, percorre os incrementos de altura que deseja, criando círculos a cada altura no raio necessário para formar uma esfera. Aqui eu modifiquei o código para não ser para cubos:
Agora, esse código criaria apenas pontos para a latitude. No entanto, você quase pode usar o mesmo código para criar as linhas de longitude. Exceto que você precisará alternar entre cada iteração e fazer um círculo completo a cada
degreeStep
.Lamentamos, mas esta não é uma resposta completa ou específica do Unity, mas espero que o ajude a começar.
fonte
Você não poderia simplesmente começar com uma forma simples, poderia ser uma caixa com uma distância r do centro aos cantos. Para criar uma esfera mais detalhada, subdivide todos os polígonos e mova os vértices para a distância r do centro, fazendo com que o vetor passe pela posição atual.
Continue repetindo até esférico o suficiente para o seu gosto.
fonte
Você realmente precisa da geometria 3D ou apenas da forma?
Você pode fazer uma esfera 'falsa' usando um único quad. Basta colocar um círculo e sombrear corretamente. Isso tem a vantagem de ter exatamente a resolução necessária, independentemente da distância da câmera ou da resolução.
Há um tutorial aqui .
fonte
aqui está um código para qualquer número de vértices igualmente espaçados, como uma casca de laranja, que enrola uma linha de pontos ao redor de uma esfera em espiral. depois, como você une os vértices é com você. você pode usar pontos vizinhos no loop como 2 de cada triângulo e, em seguida, descobrir que o terceiro seria uma torção proporcional ao redor da esfera, mais acima ou mais abaixo ... você também pode fazer triângulos por loop e o vizinho mais próximo, alguém conhece uma maneira melhor?
};
fonte
Embora David esteja absolutamente correto em sua resposta, quero oferecer uma perspectiva diferente.
Para minha tarefa de geração de conteúdo processual, observei (entre outras coisas) o icosaedro versus as esferas subdivididas mais tradicionais. Veja estas esferas geradas processualmente:
Ambos parecem esferas perfeitamente válidas, certo? Bem, vejamos seus wireframes:
Uau, o que aconteceu lá? A versão em estrutura de arame da segunda esfera é tão densa que parece texturizada! Vou contar um segredo: a segunda versão é um icosaedro. É uma esfera quase perfeita, mas tem um preço alto.
A esfera 1 usa 31 subdivisões no eixo xe 31 subdivisões no eixo z, para um total de 3.844 faces.
A esfera 2 usa 5 subdivisões recursivas, para um total de 109.220 faces.
Mas tudo bem, isso não é realmente justo. Vamos reduzir a qualidade consideravelmente:
A esfera 1 usa 5 subdivisões no eixo xe 5 subdivisões no eixo z, para um total de 100 faces.
A esfera 2 usa 0 subdivisões recursivas, para um total de 100 faces.
Eles usam a mesma quantidade de rostos, mas na minha opinião, a esfera da esquerda parece melhor. Parece menos irregular e muito mais redondo. Vamos dar uma olhada em quantas faces geramos com os dois métodos.
Icosaedro:
Esfera subdividida:
Como você pode ver, o icosaedro aumenta em rostos a uma taxa exponencial, para uma terceira potência! Isso porque para cada triângulo, devemos subdividi-los em três novos triângulos.
A verdade é: você não precisa da precisão que um icosaedro lhe dará. Porque ambos escondem um problema muito mais difícil: texturizar um plano 2D em uma esfera 3D. Aqui está a aparência do topo:
No canto superior esquerdo, você pode ver a textura sendo usada. Coincidentemente, também está sendo gerado procedimentalmente. (Ei, foi um curso sobre geração processual, certo?)
Parece terrível, certo? Bem, isso é tão bom quanto será possível. Eu consegui as melhores notas para o meu mapeamento de texturas, porque a maioria das pessoas nem entende direito.
Então, por favor, considere usar cosseno e seno para gerar uma esfera. Ele gera muito menos faces para a mesma quantidade de detalhes.
fonte
N
peças forneceráN*N
novos triângulos, que são quadráticos, exatamente como o que você faz com a esfera UV.O script abaixo criará um icosaedro com n polígonos ... base 12. Ele também subdividirá os polígonos em malhas separadas e calculará o total de verts-duplicados e polígonos.
Não encontrei nada parecido, então criei isso. Apenas anexe o script a um GameObject e defina as subdivisões no Editor. Trabalhando na modificação de ruído a seguir.
fonte