Como dobrar um objeto no OpenGL?

11

Existe uma maneira de dobrar um objeto, como um cilindro ou um avião usando o OpenGL?

Sou iniciante no OpenGL (estou usando o OpenGL ES 2.0, se isso importa, embora eu suspeite que a matemática seja a mais importante nesse caso, por isso, de alguma forma, é independente da versão), eu entendo o básico: traduzir, girar, transformações matriciais, etc. Eu queria saber se existe uma técnica que permita alterar a geometria de seus objetos (neste caso, dobrando-os)?

Quaisquer links, tutoriais ou outras referências são bem-vindos!

Valentin Radu
fonte

Respostas:

11

O que você precisa fazer para "dobrar" um objeto é aplicar uma combinação apropriada de conversão / rotação / escalonamento a apenas alguns subconjuntos dos vértices do objeto em questão - provavelmente ponderando essa transformação de acordo.

Para fazer isso de uma maneira agradável, será necessário o uso de mais vértices do que seria estritamente necessário para descrever a malha original. Por exemplo, um cilindro simples pode ter apenas vértices em cada extremidade, mas se você deseja que ele se dobre no meio, precisará de vértices também.

Se tudo o que lhe interessa é muito específico, deformações pontuais de formas muito simples (como o seu plano acima mencionado), provavelmente você pode fazer isso manualmente. Por exemplo, decida o "eixo de dobra" do seu plano e calcule as transformações apropriadas para cada linha de vértices do plano para obter a rotação apropriada sobre esse eixo de dobra, dependendo da distância deles, e aplique-o à geometria (possivelmente na CPU, pois seria a mais direta, pelo menos inicialmente). Mas essa técnica não seria bem dimensionada e seria muito entediante.

Como pode ser tão complicado descobrir corretamente como ponderar uma transformação para cada vértice individual de um conjunto para obter a deformação desejada (especialmente para objetos mais práticos e complicados), muitos jogos usam uma técnica chamada animação esquelética . Em um nível alto, isso envolve associar um conjunto separado de geometria (o "esqueleto") à sua malha. Essa geometria representa os ossos do seu objeto e você define (geralmente nas ferramentas de modelagem) um mapeamento entre os vértices do modelo real e os ossos do esqueleto - quais ossos são associados a cada vértice e quanto esse osso afeta a deformação desse vértice. Em seguida, o esqueleto é animado diretamente e a animação é transferida para o modelo real através da relação entre os ossos e seus vértices.

Normalmente nesta técnica, o mapeamento entre o esqueleto e a malha real é definido no momento da produção do ativo. As animações também podem ser construídas então ou podem ser processadas em tempo de execução. A aplicação das transformações de animação na malha real ocorre em tempo de execução. Geralmente, nenhum novo vértice é gerado no tempo de execução, o que significa que o intervalo de deformações bonitas é implicitamente fixo na malha quando ele é criado originalmente.

Em teoria, também se poderia aplicar mosaico e subdivisão à malha em tempo de execução com base na análise das transformações na animação e, assim, produzir os vértices apropriados para criar uma animação que não foi necessariamente planejada. Não tenho conhecimento imediato de nenhum trabalho sobre esse assunto.

Veja também:

Vaillancourt
fonte
9

Para a matemática real da deformação, isso pode ficar muito complicado, por que você não começa aqui? .

Agora vou falar sobre como você pode aplicar isso, supondo que você já tenha a matemática de como fará suas deformações.

2 maneiras:

1) Em cada quadro, visite todos os vértices no modelo de cilindro e faça o deslocamento de alguma maneira.

2) Desloque os vértices no sombreador de vértice enquanto você está renderizando. O OpenGL ES 2.0 suporta shaders de vértice. Então você está com sorte, de certa forma.

Deseja apenas distorcer o objeto como ele aparece na tela ou deseja distorcer o objeto para que todos os objetos do jogo saibam que ele foi deformado?

Se você distorcer o objeto no sombreador de vértice, isso acontecerá imediatamente antes da exibição / rasterização , portanto, isso significa que nenhum dos objetos do jogo saberá da deformação . Isso é bom se você está simplesmente criando um protetor de tela ou se as deformações são tão pequenas que não afetam a forma colidível do objeto.

Quando você distorce a geometria no sombreador de vértices, os vértices originais do modelo na verdade não se movem (eles apenas parecem se mover ).

Deformação no vertex shader

Não deformado:

não deformado

Deformado

deformado

Isto é do capítulo 6 do tutorial cg , (programa nº 14).

O código shader para produzir essa deformação é algo como

// choose a displacement amount
float displacement = scaleFactor * 0.5 * sin(position.y * frequency * time) + 1 ;

// displace it in the direction of the normal
float4 displacementDirection = float4(normal.x, normal.y, normal.z, 0) ;

// move the vertex
float4 newPosition = position + displacement * displacementDirection ;

// transform (as normal)
oPosition = mul(modelViewProj, newPosition) ;

Como você pode ver, isso acontece logo antes da exibição (o vertex shader ocorre na GPU), portanto, o código da CPU praticamente não tem como acessar a posição do vértice transformado (existem maneiras de enviar dados da GPU para a CPU (principalmente por meio de texturas), mas nós não vai lá).

bobobobo
fonte
8

O que você está tentando alcançar é basicamente um subconjunto do tópico de deformação de malha. Mas como você é iniciante, receio que esse tipo de informação possa ser um pouco estranho por enquanto. Vou tentar estabelecer as noções básicas.

Para fazer isso, você precisará de duas coisas:

  1. Sua malha precisa ter vértices suficientes para você transformar. Por exemplo, se for um plano, você precisará garantir que ele seja realmente criado como uma espécie de grade, com muitos vértices para deformar. A mesma coisa com um cilindro. Pode ser possível conseguir isso em tempo de execução com mosaico, mas não sei muito sobre o assunto.
  2. Você precisa usar um sombreador de vértice para deformar os vértices. Basicamente, o sombreador de vértice cuida do cálculo da posição final transformada de cada vértice, para que você possa aplicar qualquer deformação a eles.

Não tenho certeza de quão útil será, mas dê uma olhada neste recurso OpenGL, pois parece ser o tipo de coisa que você precisa:

http://www.ozone3d.net/tutorials/mesh_deformer_p3.php#part_3

Captura de tela desse link:

insira a descrição da imagem aqui

Editar

Acabei de ver a resposta de Josh e concordo que a animação esquelética também é uma maneira muito elegante de encapsular esse problema, especialmente quando suas deformações começam a se tornar mais complexas e mais difíceis de representar matematicamente.

Mas lembre-se, os dois pontos acima ainda se aplicam - você só pode deformar vértices; portanto, obviamente eles precisam existir em primeiro lugar, e é por isso que sua malha precisa ter uma quantidade decente de densidade de vértices. E geralmente é o sombreador de vértices que impulsiona a animação esquelética e faz a mistura de vértices e tal.

A propósito, você também pode fazer isso na CPU, mas hoje em dia geralmente é uma opção melhor fazê-lo na GPU, e é por isso que enfatizo o sombreador de vértice, e você deve procurá-lo. Não é realmente muito mais difícil programaticamente do que fazê-lo na CPU de qualquer maneira.

David Gouveia
fonte