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
-
- As Partículas e a Física
de Newton
-
- O que é uma Partícula
- O que é uma Força
- O que é um Objecto
- Como utilizar o DPS
- Conjunto de Partículas
- Criar um Particula
- Conjunto de Forças
- Tipos de Forças
- Conjunto de Objectos
- Tipos de Objectos
- Acções de um Objecto
- Criar um Objecto
- Funções de manipulação
dinâmica
- Demonstrações
- Apêndice A - Constantes e Tipos
de Dados
- Constantes
- Tipos de Dados
- Apêndice B - Glossário
de Funções
- Manipulação de Conjuntos
- Manipulação de Partículas
- Manipulação de Forças
- Manipulação de Objectos
- 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.
Com as equações do movimento uniformente acelerado:
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:
-
Forças partícula-partícula
(p.e. repulsão e atracção entre partículas)
-
Forças aplicadas ao sistema
(p.e. vento, gravidade, tornado)
- 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:
- Definir os conjuntos de partículas, forças
e objectos.
- Calcular uma iteração para um conjunto
de partículas.
- 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 |
|
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 |
|
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 |
|
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 |
|
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.
|
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.
|
|