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, g=Green, b=Blue, a=Alpha
Retorno
Nada
Descrição
Define a cor das partículas através dos diferentes valores de Red, Green, Blue e Alpha

 

Protótipo
void dpsColor3f(DPSfloat r, DPSfloat g, DPSfloat b);
Argumentos
r, g, b definidos em [0.0, 1.0]
r=Red, g=Green, b=Blue
O valor de alpha é colocar a 1.0
Retorno
Nada
Descrição
Define a cor das partículas através dos diferentes valores de Red, Green e Blue.

 

Protótipo
void dpsRGBADev(DPSfloat rdev, DPSfloat gdev, DPSfloat bdev, DPSfloat adev);
Argumentos
rdev, gdev, bdev, adev definidos em [0.0, 1.0]
rdev=Desvio Red, gdev=Desvio Green, bdev=Desvio Blue
Retorno
Nada
Descrição
Define o desvio padrão para cada uma das componentes de cor.

 

Protótipo
void dpsPosition3f(DPSfloat rx, DPSfloat ry, DPSfloat rz);
Argumentos
rx=Posição no eixo dos xx, ry=Posição no eixo dos yy, rz=Posição no eixo dos zz
Retorno
Nada
Descrição
Define a posição das partículas.

 

Protótipo
void dpsVelocity3f(DPSfloat vx, DPSfloat vy, DPSfloat vz);
Argumentos
vx=Velocidade no eixo dos xx, vy=Velocidade no eixo dos yy, vz=Velocidade no eixo dos zz
Retorno
Nada
Descrição
Define a velocidade vectorial das partículas.

 

Protótipo
void dpsAgef(DPSfloat age);
Argumentos
age=idade inicial da partícula.
Tipicamente este valor é definido a zero.
Retorno
Nada
Descrição
Define a idade inicial das partículas.

 

Protótipo
void dpsMassf(DPSfloat mass);
Argumentos
mass=massa da partícula
Retorno
Nada
Descrição
Define a massa das partículas.

 

Protótipo
void dpsMeshFunc(DPSvoid (*mesh)(DPSulong));
Argumentos
mesh=função que desenha o objecto pretendido.
O argumento da função fornecida deve ser um DPSulong, que representa o número de vezes que a função foi invocada. A utilidade deste argumento é poder alterar a forma da partícula ao longo do tempo.
Retorno
Nada
Descrição
Define a forma das partículas. A função mesh é invocada sempre que a partícula vai ser desenhada.

 

Protótipo
void dpsMeshRoll(DPSboolean roll);
Argumentos
roll=DPS_TRUE ou DPS_FALSE
Retorno
Nada
Descrição

Define se a mesh deve rodar de forma a seguir o movimento da partícula. Caso esse seja o caso, é fundamental que a mesh seja desenhada na origem, de pé e virada para a frente.

dpsMeshRoll(DPS_FALSE);
dpsMeshRoll(DPS_TRUE);

 

Protótipo
void dpsDieFunc(DPSvoid (*die)(DPShandle, DPSshandle, DPSshandle, DPSshandle));
Argumentos

die=função que é chamada quando uma partícula morre.
Os argumentos da função fornecida são handles para a partícula que morreu, para o conjunto das partículas, para o conjunto das forças e para o conjunto dos objectos.
A utilidade deste mecanismo é termos controlo total sobre o que fazer quando uma determinada partícula morre. Como por exemplo, gerar umas quantas partículas no local do óbito e aplicar uma explosão, para dar um efeito do tipo foguete a rebentar.

Retorno
Nada
Descrição
Defne a função que é invocada sempre que uma partícula morre.

 

Protótipo
void dpsCollideFunc(DPSvoid (*collide)(DPShandle, DPSshandle, DPSshandle, DPSshandle));
Argumentos

collide=função que é chamada quando uma partícula colide com algum objecto.
Os argumentos da função fornecida são handles para a partícula que colidiu, para o conjunto das partículas, para o conjunto das forças e para o conjunto dos objectos.
A utilidade deste mecanismo é termos controlo total sobre o que fazer quando uma determinada partícula colide. Como por exemplo, gerar umas quantas partículas no local da colisão e aplicar uma explosão, para dar um efeito do tipo granada a bater no chão.

Retorno
Nada
Descrição
Defne a função que é invocada sempre que uma partícula colide com um objecto.

 

Protótipo
DPShandle dpsNewParticle();
Argumentos
Nenhum
Retorno
Um handle para a partícula. Permite que a partícula seja removida ou alterada mais tarde.
Descrição
Cria uma nova partícula no conjunto de partículas actual, com a propriedades actualmente definidas.

 

 

Conjunto de Forças

As forças são fundamentais num sistema de partículas. Com elas podemos simular efeitos como gravidade, vento, explosões, tornados, etc.
Tivemos uma enorme preocupação na optimização do código, pois funções como dpsNewGravitate exigem muito poder de cálculo.
Muitas das forças respeitam a relação: aceleração proporcional ao inverso do quadrado da distancia (ou raio de acção da força). O parâmetro epsilon é sempre adicionado à distancia para evitar que a aceleração seja infinita quando as partículas estão muito próximas do núcleo (ou seja, para evitar buracos negros).

A definição dum ou mais conjuntos de forças é assegurada pelas seguintes funções:

 

Protótipo
DPSshandle dpsGenForceSystem(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 forças.

 

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

 

Protótipo
void dpsEndForceSystem();
Argumentos
Nenhum
Retorno
Nada
Descrição
Fecha o conjunto actual de forças.

 

Tipos de Forças

De seguida são enumeradas todas as forças possiveis de adicionar ao conjunto de forças:

 

Protótipo
DPShandle dpsNewDamping(DPSfloat d0, DPSfloat d1, DPSfloat d2, DPSfloat vlowSqr, DPSfloat vhighSqr);
Argumentos
Se a velocidade de uma partícula não se encontra no intervalo [vlow, vhigh], então cada componente da velocidade é multiplicada pelas constantes de damping. Por norma damping_x, damping_y, damping_z são semelhantes. Como não existem limites para os valores de damping, se usarmos valores superior a 1.0 as partículas serão aceleradas.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula a resistencia do ar, diminuindo a velocidade das partículas.

 

Protótipo
DPShandle dpsNewExplosion(DPSfloat x, DPSfloat y, DPSfloat z, DPSfloat velocity, DPSfloat magnitude, DPSfloat stdev, DPSfloat epsilon, DPSfloat age);
Argumentos
x, y, z = centro da explosão; velocity=velocidade com que as partículas são afastadas do centro; magnitude=intensidade da força; stdev=desvio padrão da velocidade; age=idade da força (quanto maior for a idade menor é a intensidade da explosão)
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula uma explosão. Afasta todas as partículas do centro, com uma força proporcional á magnitude.

 

Protótipo
DPShandle dpsNewFollow(DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
magnitude=intensidade da força, max_radius=raio de acção da força
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Acelera a partícula na direcção da seguinte partícula do conjunto.
Isto permite dispor as partículas em fila indiana. Cada partícula é acelerada na direcção da partícula seguinte do conjunto, com uma força proporcional a magnitude.

 

Protótipo
DPShandle dpsNewGravity(DPSfloat x, DPSfloat y, DPSfloat z);
Argumentos
Os argumentos dados representam o vector aceleração de gravidade, que será adicionado ao vector velocidade de cada partícula.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula o efeito gravidade acelerando as partículas numa dada direcção.

 

Protótipo
DPShandle dpsNewGravitate(DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
magnitude=cada partícula é acelerada em direcção a todas as outras partículas com uma força proporcional a magnitude; max_radius=define o raio máximo de influência desta acção. Assim partículas que distam mais do que max_radius não se influenciam.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula forças de atracção entre as partículas.

 

Protótipo
DPShandle dpsNewSpeedlimit(DPSfloat min, DPSfloat max);
Argumentos
min, max=limites de velocidade
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Obriga a velocidade de cada partícula manter-se entre um dado valor mínimo e um máximo.

 

Protótipo
DPShandle dpsNewTargetColor(DPSfloat c1, DPSfloat c2, DPSfloat c3, DPSfloat alpha, DPSfloat scale);
Argumentos
c1=red, c2=green, c3=blue, alpha=alpha, scale=numero de iterações necessárias para atingir a cor destino.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Faz com que a cor das partículas seja alterada para a cor especificada. Se o valor de scale for maior que zero esta força efectua uma transição suave entre a cor original e a cor destino.

 

Protótipo
DPShandle dpsNewVortex(DPSfloat p0, DPSfloat p1, DPSfloat p2, DPSfloat axis0, DPSfloat axis1, DPSfloat axis2, DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
p0, p1, p2= ponto central; axis0, axis1, axis2= eixo; magnitude=intensidade da força; max_radius=raio de accção
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Movimenta as partículas em torno de um eixo.
O centro e o axis definem uma linha infinita, onde o centro representa a origem do vortex e o axis é um vector ao longo dessa linha, cujo comprimento é irrelevante. Usando-se um epsilon semelhante á magnitude pode-se aumentar o raio de influencia do vortex. O raio_max define o campo de actuação desta força.

 

Protótipo
DPShandle dpsNewKillOld(DPSfloat age_limit, DPSboolean kill_less_than);
Argumentos
age_limite=limite de idade, kill_less_than=elimina as partículas mais antigas ou as mais recentes que age_limit
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Elimina as partículas com idade superior a age_limit se o argumento Kill_less_than for falso. Se o argumento Kill_less_than for verdadeiro, elimina todas as partículas com idade inferior a age_limit.

 

 

Conjunto de Objectos

Este conjunto de entidades permite dar às partículas um comportamento idêntico a determinados eventos do mundo real.

A interacção entre objectos e partículas pode ser dividida em duas fases: detecção e reacção. A detecção da partícula é feita inserindo a sua posição no plano do objecto. A sua reacção depende do tipo de acção definida para o objecto, sendo no caso da colisão (ver DPS_COLLIDE) algo do tipo da reflexão da luz numa superfície, no caso do evitar (ver DPS_AVOID) algo do género de uma partícula com carga negativa desviar-se de outra partícula com carga negativa. No caso da acção "morrer" (ver DPS_KILL) a partícula desaparece e no caso da fonte (ver DPS_SOURCE) são geradas partículas com um determinado débito. Note que no caso das acções colidir e "morrer" pode ser declarada uma acção a exercer sobre a partícula, por exemplo, uma partícula que colide pode morrer e serem geradas nessa posição e instante várias partículas.

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

 

Protótipo
DPSshandle dpsGenObjectSystem(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 objectos.

 

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

 

Protótipo
void dpsEndObjectSystem();
Argumentos
Nenhum
Retorno
Nada
Descrição
Fecha o conjunto actual de objectos.

 

 

Tipos de Objectos

Os objectos implementados neste sistema de partículas correspondem a figuras geométricas comuns. São eles: esfera, rectângulo, triângulo, plano, cilindro, cone e cubo. Com estes podemos compor objectos mais complexos.

Na criação de um objecto, feita através das funções abaixo enumeradas (LINK), devemos ter a consciência da existência de dois dois grupos de argumentos.

  • O primeiro indica a localização geográfica do objecto, bem como todos os restantes parâmetros necessários para definir a estrutura do objecto, tais como vectores directores, vectores normais ou ainda raios internos e externos.
  • O segundo grupo de argumentos diz respeito ao tipo de acção associada ao objecto e os parâmetros que modelam essa acção, sendo que estes últimos são dependentes do tipo de acção definida, i.e., variam de acção para acção.

 

Acções de um Objecto

 

Action
DPS_COLLIDE
Descrição

A colisão é evento exacto e instantâneo, muito idêntico ao fenómeno da luz a reflectir numa superfície. É sabido da física que existem dois tipos de colisões: elásticas e inelásticas. Nas colisões inelásticas, a partícula não perde enegia pelo que a magnitude da sua velocidade não é alterada. No entanto após a colisão a direcção da partícula é alterada sendo a direcção dada por uma reflexão perfeita. Assim dada a normal no ponto de colisão p e a posição anterior da partícula podemos calcular a direcção da reflexão perfeita. A distância da partícula à superfície reflectora é igual à distância que esta teria se tivesse penetrado o objecto no caso da ausência da colisão.

No caso anterior, a componente tangencial da velocidade fica inalterada, sendo apenas a direcção da componente normal invertida. Um cálculo ligeiramente mais complexo é feito para o caso da colisão elástica, onde a partícula perde alguma da sua energia quando colide com o objecto.

Var1
Fricção, i.e., quando a velocidade da partícula é superior à velocidade de corte (var3), a componente tangencial é multiplicada por (1- fricção).
Var2
Resistência, ou de outra forma coeficiente de restituição, i.e., fracção da componente normal da velocidade da partícula retida após o choque.
Var3
Velocidade de corte. Este parâmetro é utilizado para lidar correctamente com forças de contacto. As forças de contacto podem ser explicadas com um exemplo: quando temos uma partícula sujeita a uma força que a empurra ao longo de uma superfície. A partícula não pode penetrar na superfície, mas também não pode saltar, devido à força que está a ser aplicada nela. Assim variando este parâmetro podemos definir a forma como a partícula desliza ao longo da superfície.

 

Action
DPS_AVOID
Descrição

Esta acção permite que a partícula se vá desviando progressivamente quando detecta que vai colidir com o objecto.

 

Var1
Magnitude, indica com que intensidade a velocidade da partícula é alterada para poder evitar o objecto.
Var2
Epsilon, é um parâmetro utilizado em acções cuja intensidade depende do inverso da distância. Um exemplo deste tipo de acções são as forças atractivas entre partículas cuja intensidade é inversamente proporcional ao quadrado da distância. Quando as distâncias são muito reduzidas temos um intensidade infinita. Assim o valor de epsilon é adicionado ao raio, ou distância para evitar esta situação. Note-se que é quase sempre utilizada um valor constante (DPS_EPSILON) de epsilon para estes casos.
Var3
Lookahead, i.e., número de unidades de tempo que são utilizadas para detectar uma colisão. Isto permite que uma partícula se vá desviando objecto de uma forma mais ou menos drástica. Assim se o valor do lookahead for grande permite um desvio mais suave do objecto. Valores mais pequenos deste parâmetro conduz a um desvio mais acentuado.

 

Action
DPS_SOURCE
Descrição

Esta acção define o objecto como uma fonte de partículas.

 

Var1
Débito de criação, i.e., número de partículas geradas por unidade de tempo.
Var2
Magnitude da velocidade, i.e., módulo da velocidade da partícula gerada. O vector velocidade dependendo do objecto que gera a partícula, têm tipicamente o vector director do plano complanar ao objecto. Existe porém uma excepção. A esfera gera partículas com uma velocidade orientada em todas as direcções, tal como seria de esperar.
Var3
Desvio padrão da velocidade, i.e., valor da norma da velocidade com o qual as partículas são geradas seguindo uma distribuição normal. Isto serve essencialmente para dar um efeito mais natural ao "nascimento" das partículas. Este valor é aplicado à velocidade da partícula gerada concentrando a maior parte da seus valores em torno de um valor médio mas permitindo que as velocidades oscilem entre valor e uma gama de valores determinada por este desvio padrão.

 

Action
DPS_KILL
Descrição

Nesta acção temos um caso simples em que a partícula ao colidir com o objecto é simplesmente removida do conjunto de partículas a que pertence, ou seja deixa de existir para o sistema. Nesta acção os parâmetros deixam de fazer sentido, estando presentes na função apenas por questões de coerência.

 

Var1
Don't care
Var2
Don't care
Var3
Don't care

 

 

Criar um Objecto

De seguida são apresentados os protótipos das funções que permitem adicionar objectos ao nosso sistema de partículas.

 

Protótipo
DPShandle dpsNewSphere(DPSfloat x, DPSfloat y, DPSfloat z, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x,y,z=centro da esfera; ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria uma nova esfera no conjunto de objectos actual.
A esfera pode ser maciça bastando ter o raio interior igual zero. Pode também ser oca se o raio interior for maior que zero;

 

Protótipo
DPShandle dpsNewPlane(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0 = ponto do plano; x1,y1,z1 = vector normal ao plano
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo plano no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewRectangle(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat x2, DPSfloat y2, DPSfloat z2, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0 = o =ponto base do rectângulo; x1,y1,z1 = u = vector director do rectângulo; x2,y2,z2 = v =vector director do rectângulo;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo rectangulo no conjunto de objectos actual.
O resultado é um losângulo em que os seus cantos são : o, o+u, o+u+v, o+v;
Os vectores não devem ser paralelos mas não precisam de ser ortongonais nem normais;

 

Protótipo
DPShandle dpsNewTriangle(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat x2, DPSfloat y2, DPSfloat z2, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0; x1,y1,z1; x2,y2,z2; definem os três vértices do triângulo, podendo este ter uma forma arbitrária;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo triangulo no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewDisc(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x,y,z=centro do disco; x1,y1,z1 = vector normal ao disco;ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo disco no conjunto de objectos actual. Um disco é como um circulo mas no espaço tri-dimensional, ou seja, não possui altura.

 

Protótipo
DPShandle dpsNewCone(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= centro da base; x1,y1,z1 = outra extremidade ;ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo cone no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewCylinder(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= centro da base; x1,y1,z1 = outra extremidade; ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo cilindro no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewCube(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= vértice do cubo; x1,y1,z1 = vértice do cubo;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição

Cria um novo cubo no conjunto de objectos actual.
O cubo gerado é centrado e alinhado nos eixos.

 

 

Funções de manipulação dinâmica

Para além das funções que permitem criar conjuntos e entidades pertencentes a esses conjuntos (nomeadamente, partículas, forças e objectos) existem ainda funções que permitem conhecer e alterar o estado actual do sistema de partículas. Existem três destas funções que são muito importantes e sempre necessárias em qualquer utilização do DPS: dpsTimeIncrementf, dpsIterateParticles, dpsDrawParticleSystem.
Todas estas funções encontram-se descritas de seguida:

 

Protótipo
void dpsTimeIncrementf(DPSfloat dt);
Argumentos
dt = Incremento de tempo.
Valores normais para este valor são oscilam entre 0.0 e 1.0.
Retorno
Nada
Descrição
Define o incremento de tempo dt que deve ser utilizado sempre que é calculada uma nova iteração. Este parametro é muito importante, pois se não for definido o sistema não anima. Pode ser redefinido ao longo do tempo de simulação de modo a acelerar ou diminuir a velocidade da mesma.

 

Protótipo
void dpsIterateParticles(DPSshandle particles, DPSshandle forces, DPSshandle objects);
Argumentos
particles=handle para o conjunto de partículas, forces=handle para o conjunto de forças, objects=handle para o conjunto de objectos.
Retorno
Nada
Descrição
Calcula uma iteração do sistema, ou seja, move as partículas sujeitas a forças para uma nova posição no espaço.

 

Protótipo
void dpsDrawParticleSystem(DPSbitfield mask, DPSshandle handle);
Argumentos

mask=tipo de visualização, handle=handle para o conjunto de partículas que queremos desenhar.

Mask é, tal como o nome indica, uma máscara de bits. Essa máscara de bits pode ser conseguida através duma disjunção dos seguintes valores possíveis:

DPS_POINTS
Desenha cada partícula como um ponto.
DPS_LINES
Desenha cada partícula como uma linha de comprimento directamente proporcional à norma da velocidade.
DPS_COLOR
Faz com que as partículas sejam desenhadas coloridas
DPS_MESHES
Utiliza a função fornecida ao sistema por dpsMeshFunc para desenhar as partículas. Neste contexto a propriedade DPS_COLOR é ignorada, pois a cor é fornecida pela função que desenha a mesh.


Retorno
Nada
Descrição
Desenha um conjunto de partículas usando o tipo de visualização definido por mask.

 

Protótipo
void dpsParticlePosition3fv(DPSvector3f position, DPShandle p);
Argumentos
position=vector de três posições passado por referência que retorna a posição da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a posição de uma dada partícula num dado momento.

 

Protótipo
void dpsParticleVelocity3fv(DPSvector3f velocity, DPShandle p);
Argumentos
velocity=vector de três posições passado por referência que retorna a velocidade da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a velocidade de uma dada partícula num dado momento.

 

Protótipo
void dpsParticleColor4fv(DPSvector4f color, DPShandle p);
Argumentos
color=vector de quatro posições passado por referência que retorna a velocidade da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a cor de uma dada partícula.

 

Protótipo
void dpsRemoveParticle(DPSshandle shandle, DPShandle phandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para a partícula.
Retorno
Nada
Descrição
Remove uma partícula de um conjunto de partículas.

 

Protótipo
void dpsRemoveForce(DPSshandle shandle, DPShandle fhandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para a força.
Retorno
Nada
Descrição
Remove uma força de um conjunto de forças.

 

Protótipo
void dpsRemoveObject(DPSshandle shandle, DPShandle ohandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para o objecto.
Retorno
Nada
Descrição
Remove um objecto de um conjunto de objectos.

 

Protótipo
DPSulong dpsLiveParticles(DPSshandle handle);
Argumentos
handle=para o conjunto de partículas.
Retorno
Numero de partículas do conjunto.
Descrição
Permite saber o numero de partículas dum conjunto de partículas.

 

 

Demonstrações

Juntamente com o DPS são incluídas algumas demonstrações das suas potencialidades.

Vulcão
Screen Shots
Descrição
São colocados diversos objectos do tipo DPS_SPHERE debaixo dum gerador de partículas do tipo cone. A gravidade puxa as partículas para baixo e estas chocam com as esferas, morrendo num plano que delimita o mundo.
A cada 100 unidades de tempo ocorre uma explosão.

 

Foguetes
Screen Shots

Descrição
Temos um gerador do tipo cone, de modo a obter uma maior dispersão das partículas geradas. Possuímos também uma força da gravidade que acelera as partículas para baixo. Sempre que uma partícula morre é invocada uma função que coloca dezenas de partículas e uma explosão no local do óbito.

 

Voar pelo espaço
Screen Shots

Descrição
Um gerador em forma de circulo lança partículas de encontro à câmara. As partículas quando nascem são de cor preta e quando estão próximas da câmara são brancas de forma a garantir um maior realismo à simulação. Esta demonstração pretende exemplificar como é possivel utilizar a pseudo-força TargetColor para fazer variar a cor das partículas.

 

Naves espaciais
Screen Shots

Descrição
Esta demonstração pretende mostrar a capacidade de desenhar uma partícula com a forma que se desejar e capacidade de fazer o roll dos objectos, ou seja, permitir que o objecto rode de acordo com a direcção do seu movimento.

 

Cascata
Screen Shots

Descrição

É apenas, mais uma cascata. Nenhum sistema de partículas pode deixar de o exemplificar.
É de notar a forma como as partículas escorregam pelo plano.

 

Exponenciação
Screen Shots

Descrição

É colocada uma partícula no mundo. Quando esta colide com o plano que o delimita esta divide-se em duas. As novas partículas reagem da mesma forma. Assim, em poucos segundos, possuímos um mundo populado de forma exponencial.

 

 

Apêndice A - Contantes e Tipos de Dados


Constantes

 

Domínio
Constante DPS
Valor
Descrição
Valores boleanos
DPS_FALSE
0x00
Falso
DPS_TRUE
0x01
Verdadeiro
Apontadores
DPS_NULL
0x00
Nulo
Tipos de Objectos
DPS_AVOID
0x01
Tipo de objecto - Objecto a evitar
DPS_COLLIDE
0x03
Tipo de objecto - Objecto de colisão
DPS_KILL
0x05
Tipo de objecto - Eliminador de partículas
DPS_SOURCE
0x07
Tipo de objecto - Fonte de partículas
Argumentos
DPS_EPSILON
1e-3f
Aproximação ao infinito
Tipos visuais de partículas
DPS_COLOR
0x40
Desenhar as cores das partículas
DPS_LINES
0x04
Desenhar partículas como linhas
DPS_POINTS
0x01
Desenhar partículas como pontos
DPS_MESHES
0x02
Desenhar partículas como objectos

 

Tipos de Dados

 

Tipo DPS
Tipo C
Descrição
DPSfloat
float
Real
DPSvector3f
float[3] Vector de reais
DPSvector4f
float[4] Vector de reais
DPSenum
unsigned int Enumeração de valores constantes
DPSboolean
unsigned char Booleano
DPSvoid
void Void
DPSsizei
int Inteiro
DPSulong
unsigned long Contador
DPShandle
void* Handle para uma partícula, força ou objecto
DPSshandle
unsigned long Handle para um conjunto
DPSbitfield
unsigned int Maskara de bits

 

 

Apêndice B - Glossário de Funções

 

Manipulação de Conjuntos

 

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.

 

Protótipo
DPSshandle dpsGenForceSystem(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 forças.

 

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

 

Protótipo
void dpsEndForceSystem();
Argumentos
Nenhum
Retorno
Nada
Descrição
Fecha o conjunto actual de forças.

 

Protótipo
DPSshandle dpsGenObjectSystem(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 objectos.

 

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

 

Protótipo
void dpsEndObjectSystem();
Argumentos
Nenhum
Retorno
Nada
Descrição
Fecha o conjunto actual de objectos.

 

 

Manipulação de Partículas

 

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, g=Green, b=Blue, a=Alpha
Retorno
Nada
Descrição
Define a cor das partículas através dos diferentes valores de Red, Green, Blue e Alpha

 

Protótipo
void dpsColor3f(DPSfloat r, DPSfloat g, DPSfloat b);
Argumentos
r, g, b definidos em [0.0, 1.0]
r=Red, g=Green, b=Blue
O valor de alpha é colocar a 1.0
Retorno
Nada
Descrição
Define a cor das partículas através dos diferentes valores de Red, Green e Blue.

 

Protótipo
void dpsRGBADev(DPSfloat rdev, DPSfloat gdev, DPSfloat bdev, DPSfloat adev);
Argumentos
rdev, gdev, bdev, adev definidos em [0.0, 1.0]
rdev=Desvio Red, gdev=Desvio Green, bdev=Desvio Blue
Retorno
Nada
Descrição
Define o desvio padrão para cada uma das componentes de cor.

 

Protótipo
void dpsPosition3f(DPSfloat rx, DPSfloat ry, DPSfloat rz);
Argumentos
rx=Posição no eixo dos xx, ry=Posição no eixo dos yy, rz=Posição no eixo dos zz
Retorno
Nada
Descrição
Define a posição das partículas.

 

Protótipo
void dpsVelocity3f(DPSfloat vx, DPSfloat vy, DPSfloat vz);
Argumentos
vx=Velocidade no eixo dos xx, vy=Velocidade no eixo dos yy, vz=Velocidade no eixo dos zz
Retorno
Nada
Descrição
Define a velocidade vectorial das partículas.

 

Protótipo
void dpsAgef(DPSfloat age);
Argumentos
age=idade inicial da partícula.
Tipicamente este valor é definido a zero.
Retorno
Nada
Descrição
Define a idade inicial das partículas.

 

Protótipo
void dpsMassf(DPSfloat mass);
Argumentos
mass=massa da partícula
Retorno
Nada
Descrição
Define a massa das partículas.

 

Protótipo
void dpsMeshFunc(DPSvoid (*mesh)(DPSulong));
Argumentos
mesh=função que desenha o objecto pretendido.
O argumento da função fornecida deve ser um DPSulong, que representa o número de vezes que a função foi invocada. A utilidade deste argumento é poder alterar a forma da partícula ao longo do tempo.
Retorno
Nada
Descrição
Define a forma das partículas. A função mesh é invocada sempre que a partícula vai ser desenhada.

 

Protótipo
void dpsMeshRoll(DPSboolean roll);
Argumentos
roll=DPS_TRUE ou DPS_FALSE
Retorno
Nada
Descrição

Define se a mesh deve rodar de forma a seguir o movimento da partícula. Caso esse seja o caso, é fundamental que a mesh seja desenhada na origem, de pé e virada para a frente.

dpsMeshRoll(DPS_FALSE);
dpsMeshRoll(DPS_TRUE);

 

Protótipo
void dpsDieFunc(DPSvoid (*die)(DPShandle, DPSshandle, DPSshandle, DPSshandle));
Argumentos

die=função que é chamada quando uma partícula morre.
Os argumentos da função fornecida são handles para a partícula que morreu, para o conjunto das partículas, para o conjunto das forças e para o conjunto dos objectos.
A utilidade deste mecanismo é termos controlo total sobre o que fazer quando uma determinada partícula morre. Como por exemplo, gerar umas quantas partículas no local do óbito e aplicar uma explosão, para dar um efeito do tipo foguete a rebentar.

Retorno
Nada
Descrição
Defne a função que é invocada sempre que uma partícula morre.

 

Protótipo
void dpsCollideFunc(DPSvoid (*collide)(DPShandle, DPSshandle, DPSshandle, DPSshandle));
Argumentos

collide=função que é chamada quando uma partícula colide com algum objecto.
Os argumentos da função fornecida são handles para a partícula que colidiu, para o conjunto das partículas, para o conjunto das forças e para o conjunto dos objectos.
A utilidade deste mecanismo é termos controlo total sobre o que fazer quando uma determinada partícula colide. Como por exemplo, gerar umas quantas partículas no local da colisão e aplicar uma explosão, para dar um efeito do tipo granada a bater no chão.

Retorno
Nada
Descrição
Defne a função que é invocada sempre que uma partícula colide com um objecto.

 

Protótipo
DPShandle dpsNewParticle();
Argumentos
Nenhum
Retorno
Um handle para a partícula. Permite que a partícula seja removida ou alterada mais tarde.
Descrição
Cria uma nova partícula no conjunto de partículas actual, com a propriedades actualmente definidas.

 

 

Manipulação de Forças

 

Protótipo
DPShandle dpsNewDamping(DPSfloat d0, DPSfloat d1, DPSfloat d2, DPSfloat vlowSqr, DPSfloat vhighSqr);
Argumentos
Se a velocidade de uma partícula não se encontra no intervalo [vlow, vhigh], então cada componente da velocidade é multiplicada pelas constantes de damping. Por norma damping_x, damping_y, damping_z são semelhantes. Como não existem limites para os valores de damping, se usarmos valores superior a 1.0 as partículas serão aceleradas.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula a resistencia do ar, diminuindo a velocidade das partículas.

 

Protótipo
DPShandle dpsNewExplosion(DPSfloat x, DPSfloat y, DPSfloat z, DPSfloat velocity, DPSfloat magnitude, DPSfloat stdev, DPSfloat epsilon, DPSfloat age);
Argumentos
x, y, z = centro da explosão; velocity=velocidade com que as partículas são afastadas do centro; magnitude=intensidade da força; stdev=desvio padrão da velocidade; age=idade da força (quanto maior for a idade menor é a intensidade da explosão)
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula uma explosão. Afasta todas as partículas do centro, com uma força proporcional á magnitude.

 

Protótipo
DPShandle dpsNewFollow(DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
magnitude=intensidade da força, max_radius=raio de acção da força
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Acelera a partícula na direcção da seguinte partícula do conjunto.
Isto permite dispor as partículas em fila indiana. Cada partícula é acelerada na direcção da partícula seguinte do conjunto, com uma força proporcional a magnitude.

 

Protótipo
DPShandle dpsNewGravity(DPSfloat x, DPSfloat y, DPSfloat z);
Argumentos
Os argumentos dados representam o vector aceleração de gravidade, que será adicionado ao vector velocidade de cada partícula.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula o efeito gravidade acelerando as partículas numa dada direcção.

 

Protótipo
DPShandle dpsNewGravitate(DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
magnitude=cada partícula é acelerada em direcção a todas as outras partículas com uma força proporcional a magnitude; max_radius=define o raio máximo de influência desta acção. Assim partículas que distam mais do que max_radius não se influenciam.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Simula forças de atracção entre as partículas.

 

Protótipo
DPShandle dpsNewSpeedlimit(DPSfloat min, DPSfloat max);
Argumentos
min, max=limites de velocidade
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Obriga a velocidade de cada partícula manter-se entre um dado valor mínimo e um máximo.

 

Protótipo
DPShandle dpsNewTargetColor(DPSfloat c1, DPSfloat c2, DPSfloat c3, DPSfloat alpha, DPSfloat scale);
Argumentos
c1=red, c2=green, c3=blue, alpha=alpha, scale=numero de iterações necessárias para atingir a cor destino.
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Faz com que a cor das partículas seja alterada para a cor especificada. Se o valor de scale for maior que zero esta força efectua uma transição suave entre a cor original e a cor destino.

 

Protótipo
DPShandle dpsNewVortex(DPSfloat p0, DPSfloat p1, DPSfloat p2, DPSfloat axis0, DPSfloat axis1, DPSfloat axis2, DPSfloat magnitude, DPSfloat epsilon, DPSfloat max_radius);
Argumentos
p0, p1, p2= ponto central; axis0, axis1, axis2= eixo; magnitude=intensidade da força; max_radius=raio de accção
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Movimenta as partículas em torno de um eixo.
O centro e o axis definem uma linha infinita, onde o centro representa a origem do vortex e o axis é um vector ao longo dessa linha, cujo comprimento é irrelevante. Usando-se um epsilon semelhante á magnitude pode-se aumentar o raio de influencia do vortex. O raio_max define o campo de actuação desta força.

 

Protótipo
DPShandle dpsNewKillOld(DPSfloat age_limit, DPSboolean kill_less_than);
Argumentos
age_limite=limite de idade, kill_less_than=elimina as partículas mais antigas ou as mais recentes que age_limit
Retorno
Hande para a força. Permite que a força seja removida ou alterada mais tarde.
Descrição
Elimina as partículas com idade superior a age_limit se o argumento Kill_less_than for falso. Se o argumento Kill_less_than for verdadeiro, elimina todas as partículas com idade inferior a age_limit.

 

 

Manipulação de Objectos

 

Protótipo
DPShandle dpsNewSphere(DPSfloat x, DPSfloat y, DPSfloat z, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x,y,z=centro da esfera; ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria uma nova esfera no conjunto de objectos actual.
A esfera pode ser maciça bastando ter o raio interior igual zero. Pode também ser oca se o raio interior for maior que zero;

 

Protótipo
DPShandle dpsNewPlane(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0 = ponto do plano; x1,y1,z1 = vector normal ao plano
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo plano no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewRectangle(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat x2, DPSfloat y2, DPSfloat z2, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0 = o =ponto base do rectângulo; x1,y1,z1 = u = vector director do rectângulo; x2,y2,z2 = v =vector director do rectângulo;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo rectangulo no conjunto de objectos actual.
O resultado é um losângulo em que os seus cantos são : o, o+u, o+u+v, o+v;
Os vectores não devem ser paralelos mas não precisam de ser ortongonais nem normais;

 

Protótipo
DPShandle dpsNewTriangle(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat x2, DPSfloat y2, DPSfloat z2, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0; x1,y1,z1; x2,y2,z2; definem os três vértices do triângulo, podendo este ter uma forma arbitrária;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo triangulo no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewDisc(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x,y,z=centro do disco; x1,y1,z1 = vector normal ao disco;ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo disco no conjunto de objectos actual. Um disco é como um circulo mas no espaço tri-dimensional, ou seja, não possui altura.

 

Protótipo
DPShandle dpsNewCone(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= centro da base; x1,y1,z1 = outra extremidade ;ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo cone no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewCylinder(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSfloat ri, DPSfloat ro, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= centro da base; x1,y1,z1 = outra extremidade; ri,ro = raio interior e exterior;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição
Cria um novo cilindro no conjunto de objectos actual.

 

Protótipo
DPShandle dpsNewCube(DPSfloat x0, DPSfloat y0, DPSfloat z0, DPSfloat x1, DPSfloat y1, DPSfloat z1, DPSenum action, DPSfloat var1, DPSfloat var2, DPSfloat var3);
Argumentos

x0,y0,z0= vértice do cubo; x1,y1,z1 = vértice do cubo;
action, var1, var2, var3 = ver tipo de objectos;

 

Retorno
Um handle para o objecto. Permite que objecto seja removido ou alterado mais tarde.
Descrição

Cria um novo cubo no conjunto de objectos actual.
O cubo gerado é centrado e alinhado nos eixos.

 

 

Manipulação Dinâmica

 

Protótipo
void dpsTimeIncrementf(DPSfloat dt);
Argumentos
dt = Incremento de tempo.
Valores normais para este valor são oscilam entre 0.0 e 1.0.
Retorno
Nada
Descrição
Define o incremento de tempo dt que deve ser utilizado sempre que é calculada uma nova iteração. Este parametro é muito importante, pois se não for definido o sistema não anima. Pode ser redefinido ao longo do tempo de simulação de modo a acelerar ou diminuir a velocidade da mesma.

 

Protótipo
void dpsIterateParticles(DPSshandle particles, DPSshandle forces, DPSshandle objects);
Argumentos
particles=handle para o conjunto de partículas, forces=handle para o conjunto de forças, objects=handle para o conjunto de objectos.
Retorno
Nada
Descrição
Calcula uma iteração do sistema, ou seja, move as partículas sujeitas a forças para uma nova posição no espaço.

 

Protótipo
void dpsDrawParticleSystem(DPSbitfield mask, DPSshandle handle);
Argumentos

mask=tipo de visualização, handle=handle para o conjunto de partículas que queremos desenhar.

Mask é, tal como o nome indica, uma máscara de bits. Essa máscara de bits pode ser conseguida através duma disjunção dos seguintes valores possíveis:

DPS_POINTS
Desenha cada partícula como um ponto.
DPS_LINES
Desenha cada partícula como uma linha de comprimento directamente proporcional à norma da velocidade.
DPS_COLOR
Faz com que as partículas sejam desenhadas coloridas
DPS_MESHES
Utiliza a função fornecida ao sistema por dpsMeshFunc para desenhar as partículas. Neste contexto a propriedade DPS_COLOR é ignorada, pois a cor é fornecida pela função que desenha a mesh.


Retorno
Nada
Descrição
Desenha um conjunto de partículas usando o tipo de visualização definido por mask.

 

Protótipo
void dpsParticlePosition3fv(DPSvector3f position, DPShandle p);
Argumentos
position=vector de três posições passado por referência que retorna a posição da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a posição de uma dada partícula num dado momento.

 

Protótipo
void dpsParticleVelocity3fv(DPSvector3f velocity, DPShandle p);
Argumentos
velocity=vector de três posições passado por referência que retorna a velocidade da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a velocidade de uma dada partícula num dado momento.

 

Protótipo
void dpsParticleColor4fv(DPSvector4f color, DPShandle p);
Argumentos
color=vector de quatro posições passado por referência que retorna a velocidade da partícula p.
p=handle para a partícula.
Retorno
Nada
Descrição
Retorna a cor de uma dada partícula.

 

Protótipo
void dpsRemoveParticle(DPSshandle shandle, DPShandle phandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para a partícula.
Retorno
Nada
Descrição
Remove uma partícula de um conjunto de partículas.

 

Protótipo
void dpsRemoveForce(DPSshandle shandle, DPShandle fhandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para a força.
Retorno
Nada
Descrição
Remove uma força de um conjunto de forças.

 

Protótipo
void dpsRemoveObject(DPSshandle shandle, DPShandle ohandle);
Argumentos
shandle=handle para o conjunto, phandle=handle para o objecto.
Retorno
Nada
Descrição
Remove um objecto de um conjunto de objectos.

 

Protótipo
DPSulong dpsLiveParticles(DPSshandle handle);
Argumentos
handle=para o conjunto de partículas.
Retorno
Numero de partículas do conjunto.
Descrição
Permite saber o numero de partículas dum conjunto de partículas.