Lighthouse3d.com

Dynamic Particle System Library

Sistema Dinâmico de Partículas
uma implementação para OpenGL

 

Licenciatura em Sistemas e Informática
Universidade do Minho
Portugal

José Miguel Araújo Ferreira [jmaferreira@hotmail.com]
Pedro Gabriel Dias Ferreira [pgabiferreira@portugalmail.pt]
Rui Manuel A.S.R. Guerra [ruiguerra@hotmail.com]

 


Downloads

 

Índice

  1. As Partículas e a Física de Newton
  2. O que é uma Partícula
  3. O que é uma Força
  4. O que é um Objecto
  5. Como utilizar o DPS
    1. Conjunto de Partículas
      1. Criar um Particula
    2. Conjunto de Forças
      1. Tipos de Forças
    3. Conjunto de Objectos
      1. Tipos de Objectos
      2. Acções de um Objecto
      3. Criar um Objecto
    4. Funções de manipulação dinâmica
  6. Demonstrações
  7. Apêndice A - Constantes e Tipos de Dados
    1. Constantes
    2. Tipos de Dados
  8. Apêndice B - Glossário de Funções
    1. Manipulação de Conjuntos
    2. Manipulação de Partículas
    3. Manipulação de Forças
    4. Manipulação de Objectos
    5. Manipulação Dinâmica

 

 

Introdução

Um sistema de partículas é uma colecção de pontos independentes que são estimulados por um conjunto de regras com a intensão de modelar de determinado efeito. Tem portanto como objectivo representar e simular alguns dos fenómenos que ocorrem no mundo real tais como a chama de um fogo, o choque de uma bola com uma parede ou a explosão de um objecto.

A necessidade de criar uma representação computacional de tais fenómenos fez com que diversas teorias sobre sistemas de partículas tenham sido criadas, cada uma focando um dominio especifico de aplicação. O modelo aqui apresentado é baseado na física Newtoniana, i.e., um modelo no qual os objectos obedecem a determinadas leis da física de Newton.

Constata-se ser trivial criar um modelo no qual grupos de objectos se movem no espaço com um determinado comportamento bem definido. No entanto torna-se complexo quando temos um sistema em que os objectos colidem entre si, reagindo de uma maneira fisicamente correcta. Contorna-se este problema regendo o sistema através da combinação de algumas leis elementares da física com outras restrições matemáticas para assim controlar o comportamento dinâmico dos objectos do sistema.

Esta aproximação ao problema é feita para um conjunto de objectos, ou dito de outra forma, conjunto de partículas, uma vez que o termo partícula descreve de forma mais abrangente e exacta uma entidade sujeita a determinadas regras físicas. Daqui surge então a noção de sistema de partículas, que corresponde a nada mais que uma colecção de partículas, tipicamente pontos materiais com comportamento dinâmico regido por um conjunto equações pertencentes ao domínio da física e da matemática Euclidiana.

Os sistemas de partículas têm sido utilizados para modelar uma vasta gama de fenómenos nos mais variados campos, como a chama de um fogo, o comportamento em de alguns bandos de pássaros, flocos de neve a cair, chuva num dia com vento e muitos outros. Todas estas entidades podem ser consideradas pontos de massa, i.e, objectos em que toda a sua massa está concentrada num único ponto. Utilizando as equações da física, que podemos resolver numericamente com relativa facilidade, conseguimos calcular o estado de cada partícula num dado momento. No final de cada série de cálculos podemos desenhar um objecto gráfico, em vez de um ponto.

 

 

As Partículas e a Física de Newton

A segunda lei de Newton diz-nos que uma partícula sujeita a uma dada força f, com uma dada massa m fica sujeita a uma aceleração a, dada pela relação f = ma.

 

Nota: as letras a vermelho representam grandezas vectoriais, tipicamente definidas num espaço tri-dimensional. As letras a azul representam conjuntos, enquanto as restantes representam grandezas escalares.

 

Uma das consequências mais imediatas da física de Newton é que, uma partícula de massa ideal, i.e, uma partícula cuja toda a sua massa está concentrada num único ponto, tem o seu estado completamente definido pelo vector velocidade e pelo vector aceleração.

 

  • p = <x, y, z>
  • v = <vx, vy, vz>
  • a = <ax, ay, az>

Com as equações do movimento uniformente acelerado:

  • r = r0 + vt
  • v= v0 + at,

e sabendo que v = r' e que a = r'', temos que a = f/m, conseguindo-se assim definir a qualquer momento a posição e a velocidade da partícula.

 

Nota: Além do seu estado (posição e velocidade), cada partícula pode ainda ter associado um conjunto de atributos, como a massa, cor, idade, forma, etc.

 

Um força, ou um conjunto de forças F, determina o comportamento do sistema. Essas forças são baseadas no estado da partícula e podem variar ao longo do tempo.

Tipicamente podemos ter três tipos de forças a actuar sobre um conjunto de partículas:

  1. Forças partícula-partícula (p.e. repulsão e atracção entre partículas)
  2. Forças aplicadas ao sistema (p.e. vento, gravidade, tornado)
  3. Forças partícula-objecto (p.e choque entre uma partícula e um objecto físico)

Finalmente pode dizer-se que o estado duma partícula é obtido através de métodos numéricos, que permitem obter uma aproximação ao conjunto das funções e equações diferenciais que regem o sistema. Assim cada iteracção permite obter um novo estado para o sistema de partículas.

 

 

As Partículas e a Geometria de Euclides

Para se definir algumas das características de um objecto foi necessário recorrer a um conjunto de equações da geometria a partir das quais se conseguem extrair os parâmetros necessários para a definição dum objecto, p.e., orientação do objecto ou os seus vectores ortonormais.

A equação mais frequentemente utilizada foi a de um plano (ax + by + cz + d) definido por um ponto e por um vector normal. Esta equação foi utilizada não só na definição do próprio objecto plano mas também no cálculo de outros objectos planares como o rectângulo, o triângulo ou o disco.

Para a detecção da colisão de um partícula com um objecto foi necessário calcular a distância de um ponto p (posição actual da partícula) a um plano (no caso dos objectos com estrutura plana).
Utiliza-se a seguinte equação para o este efeito: dist = - (px.a + py.b + pz.c + d) / sqrt (a^2 + b^2 + c^2).

Existem na geometria cartesiana duas operações que são a base para todo o trabalho sobre vectores. São elas o produto vectorial e o produto escalar.
O produto escalar entre dois vectores u e v é definido da seguinte maneira: u . v = ux.vx + uy.uy + uz.Vz. O resultado é um número real igual ao produto das normas dos vectores pelo co-seno do ângulo formado pelos dois vectores.
O produto vectorial entre dois vectores u e v é dado pelo cálculo do determinante de terceira ordem entre o conjunto de vectores directores do espaço e pelos próprios vectores u e v. O resultado é um vector cujas componentes em x, y e z são <uy.vz - Vy.Uz, Vx.Uz - ux.vz, ux.vy - uy.Vx>.

 

 

O que é uma Partícula

Como já foi referido anteriormente, uma partícula é um ponto material que possui determinados atributos sobre os quais forças poderão actuar:

 

Domínio
Atributo
Tipo
Descrição
Propriedades físicas duma partícula
position
vectorial
Posição no espaço onde a partícula se encotra
velocity
vectorial
Velocidade actual da partícula
mass
escalar
Massa da partícula
Propriedades que definem o aspecto gráfico duma partícula
age
escalar
Define a idade duma partícula. Tipicamente uma partícula nasce, tem um tempo de vida e morre.
color
vectorial
Permite definir a cor duma partícula.
mesh
função
Define a forma visual duma partícula.
roll
booleano
Permite dizer ao sistema se queremos ou nao que a forma definida por mesh se molde ao movimento da partícula.
Metodos que são invocados na presença de determinados eventos
collide
função
Quando uma partícula colide com um objecto, este método é invocado.
die
função
Quando uma partícula morre, este método é invocado.

 

 

O que é uma Força

Uma força é toda e qualquer entidade que permite alterar o estado duma partícula.
No DPS existem fundamentalmente dois tipos de forças, as baseadas na física e outras, às quais passaremos a chamar pseudo-forças. As forças baseadas na física são já nossas conhecidas, pois ocorrem frequentemente na natureza. Alguns exemplos destas forças são a gravidade, o vortex, vento, entre outras.

As pseudo-forças permitem-nos, basicamente, alterar determinadas propriedades duma partícula, porém não ocorrem tipicamente na natureza. Alguns exemplos destas forças especiais são: a eliminação de partículas, a alteração da sua cor ou da sua velocidade, entre outras.

 

O que é um Objecto

Permitir que as partículas mudem de estado através de um conjunto de equações, é notoriamente insuficiente para modelar determinados comportamentos do mundo real tais como colisões, desvios de objectos ou até o desaparecimento ou fragmentação aquando de uma colisão com um objecto.

Aqui entram os objectos do sistema de partículas. Estes não passam de entidades geométricas como esferas, rectângulos, discos entre outros, com uma acção bem definida e com um conjunto de parâmetros que modelam o comportamento de uma partícula quando com estes interage.

No DPS existem quatro acções que cada objecto pode desempenhar (salvo algumas excepções):

 

Acção
Descrição
Collide
modela o choque de uma partícula com o objecto.
Avoid
Faz com que uma partícula se vá desviando progressivamente de um objecto.
Kill
Mata uma partícula quando esta penetra no objecto.
Source
Faz de um objecto uma fonte de partículas.

 

Todas estas acções são à partida suficientes para cobrir a generalidade dos casos a simular.

 

Nota: A cada objecto é associada apenas a uma acção, pelo que este desempenhará essa acção em todo o seu tempo de vida.

 

 

Como utilizar o DPS

Deixemos por agora a física e a matemática e vamos analisar o funcionamento do API.
O modo de funcionamento do API é bastante simples e intuitivo. A sintaxe utilizada é semelhante à utilizada pelas display lists do OpenGL, como veremos de seguida.

Uma vez compreendidos os conceitos inerentes às partículas, forças e objectos, passamos a explicar como todas estas entidades se relacionam.

No DPS (Dynamic Particle System, ou em português, Sistema Dinâmico de partículas) existem três dominios diferentes que interagem entre si: o dominio das partículas, das forças e dos objectos.

Para animar um sistema de partículas é necessário fornecer ao API estes três dominios, ainda que algum deles ou até todos, sejam vazios. É necessário portanto, definir um conjunto de partículas P, um conjunto de forças F e um conjunto de objectos O.

Numa segunda fase é necessário dizer ao sistema quais os conjuntos que interagem conjuntamente. Esta relação é conseguida através da função dpsIterateParticles, que calcula uma nova posição para cada uma das partículas do conjunto P, que estão sob a influência dum conjunto de forças F e um conjunto de objectos O. É necessário compreender que para uma iteração conjunta destes três conjuntos é necessário ter definido um incremento de tempo dt diferente de zero (ver dpsTimeIncrementf), senão a iteração não produz resultados visto que o tempo de simulação não foi alterado. É também necessário compreender que esta função deve ser chamada várias vezes durante o tempo de vida duma animação, pois apenas calcula uma e só uma iteração. Tipicamente esta função é chamada pela função glutIdleFunc pertencente à biblioteca GLUT.

A terceira e última fase operacional do DPS é desenhar. De nada serviria todo cálculo se não se monstrasse os resultados do processamento.

 

Nota: Este API tem como principal aplicação o desenvolvimento de efeitos visuais não interactivos. Embora seja utilizada física Newtoniana não foi nossa intenção fazer um ambiente de simulação físicamente perfeito.

 

Para isto basta utilizar a função dpsDrawParticleSystem, que recebe como argumento um conjunto de partículas e desenha-o no canvas aberto pelo OpenGL.

 

Resumo: Basicamente, para se ter um sistema de partículas a funcionar é necessário fazer três coisas:

  1. Definir os conjuntos de partículas, forças e objectos.
  2. Calcular uma iteração para um conjunto de partículas.
  3. Desenhar o conjunto das partículas.

 

 

Conjunto de Partículas

Este é o mais importante dos conjuntos a definir. Sem partículas as forças pura e simplesmente não actuam, ou seja, actuam sobre nada. É sempre necessário criar um conjunto de partículas, ainda que este possa ser vazio. Podem ser adicionadas partículas uma a uma, em posições específicas se desejarmos ter um sistema pequeno e controlado, ou então utilizar um objecto como gerador de partículas dinâmico (ver objecto geradores de partículas).

A definição dum ou mais conjuntos de partículas é assegurada pelas seguintes funções:

 

Protótipo
DPSshandle dpsGenParticleSystem(DPSsizei range);
Argumentos
range=numero de conjuntos a gerar
Retorno
Um handle para o primeiro conjunto gerado. Os seguintes são endereçaveis por handle + n. Este handle será utilizado para identificar um conjunto de partículas.
Descrição
Cria range numero de conjuntos de partículas.

 

Protótipo
void dpsNewParticleSystem(DPSshandle handle);
Argumentos
handle=identificador do conjunto de partículas
Retorno
Nada
Descrição
Indica ao DPS que passamos a trabalhar sobre o conjunto de partículas handle. A partir de agora podemos adicionar partículas a este conjunto. Não esquecer que, uma vez utilizado, devemos fechar o conjunto com dpsEndParticleSystem.

 

Protótipo
void dpsEndParticleSystem();
Argumentos
Nenhum
Retorno
Nada
Descrição
Fecha o conjunto actual de partículas.

 

Segue-se um pequeno exemplo de como utilizar estes três conceitos:

 

Criar um conjunto de partículas

01 DPSshandle ps_handle; 02 int number_of_sets = 1;
03 ps_handle = dpsGenParticleSystem(number_of_sets); 04 dpsNewParticleSystem(ps_handle); 05 dpsNewParticle(); 06 dpsEndParticleSystem();
Este pequeno excerto de código permite criar um conjunto de partículas e adicionar ao mesmo uma partícula.
 

No exemplo anterior não foram definidas quaisquer propriedades da partícula, portanto esta seria criada com os seus valores por defeito. Para definirmos os atributos das partículas são utilizadas variáveis de estado tal como no Open GL.

 

Definir alguns atributos para uma partícula

01 dpsNewParticleSystem(ps_handle); 02 dpsColor3f(0.5, 0.5, 0.5); 03 dpsPosition3f(0.0, 0.0, 0.0); 04 dpsVelocity(1.0, 0.0, 0.0); 05 dpsNewParticle(); 06 dpsEndParticleSystem();
Neste exemplo é colocada uma partícula cinzenta na origem do universo com uma velocidade de 1.0 na direcção do eixo dos xx.

 

 

Criar uma partícula

Para criar uma partícula é necessário definir uma série de propriedades relevantes que irão determinar o comportamento da mesma no seu instante inicial. Uma vez definidas essas propriedades basta invocar a função dpsNewParticle para que uma nova partícula seja adicionada ao conjunto.

Para definir as propriedades duma partícula são utilizadas diversas funções de estado que definem como todas as partículas vão ser geradas a partir da definição desse estado.

As funções de estado que definem os atributos das partículas a gerar (incluíndo as geradas dinamicamente usando objectos geradores) são:

 

Protótipo
void dpsColor4f(DPSfloat r, DPSfloat g, DPSfloat b, DPSfloat a);
Argumentos
r, g, b, a definidos em [0.0, 1.0]
r=Red