OpenGL (14.) - Ucelený částicový systém
Protože na českém internetu je jen velmi málo informací ohledně programování uceleného částicového systému, rozhodl jsem se navrhnout základní strukturu, kterou lze využít pro většinu efektů s částicemi - Plápolající oheň s dýmem, jiskry ve zkratu na vedení, tryskající gejzír vody, oheň za raketou nebo její explose, déšt, sníh nebo rozstříknutí krve po zabitém nepříteli. Věřím, že tyto informace budou pro většinu z vás přínosem. Protože se jedná o poměrně rozsálné téma, rozhodl jsem se jej rozdělit i do několika příštích článků.
Particle Manager
Jak začít? Je třeba vytvořit nějaký Particle manager, který se bude starat (vytvářet, rušit, nastavovat) o jednotlivé částicové systémy. Jeho datová struktura je zde:
type
ParticleManagerC = class
private
ParticleSystem: Array of ParticleSystemC;
public
Camera: CameraC;
procedure AddParticleSystem(Name: string);
procedure RemoveParticleSystem(Name: string);
function FindParticleSystem(Name: string): ParticleSystemC;
procedure Update;
procedure Render;
constructor Create;
end;
Vše budeme psát do samostatné unity, kterou uložíme jako ParticleManagerU.pas. Konstruktor Create vytvoří objekt ParticleManager, destructor ho opět uvolní z paměti. Procedura AddParticleSystem vytvoří nový částicový systém a nastaví mu defaultní hodnoty, RemoveParticleSystem odstraní požadovaný systém. Funkcí FindParticleSystem vybereme systém a můžeme změnit jeho chování. Třídou CameraC oznamujeme manageru, jakou souřadnici má kamera v prostoru. To využijeme při zobrazování samotných částic - jsou otočeny vždy kolmo ke kameře. Místo této třídy můžeme vkládat jen tyto samotné souřadnice. Procedura Update se stará o aktualizování pozice, přidávání nových a rušení starých částic. Procedurou Render Všechny aktivní částice vykreslíme.
![]() |
| Podobné efekty lze vytvořit jedině v precizně naprogramovaných systémech. |
Potom do zdrojového kódu programu, který využívá částicový systém stačí přidat:
uses
ParticleManagerU;
var
ParicleManager: ParticleManagerC;
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
ParticleManager := ParticleManagerC.Create;
ParticleManager.AddParticleSystem('Fire');
ParticleManager.Camera := Camera;
end;
Podrobný popis funkcí je zde:
constructor ParticleManagerC.Create;
begin
end;
destructor ParticleManagerC.Free;
begin
end;
procedure ParticleManagerC.AddParticleSystem(Name:string);
begin
setlength(ParticleSystem,length(ParticleSystem)+1);
ParticleSystem[length(ParticleSystem)-1] := ParticleSystemC.Create;
ParticleSystem[length(ParticleSystem)-1].Name := Name;
ParticleSystem[length(ParticleSystem)-1].Active := true;
end;
procedure ParticleManagerC.RemoveParticleSystem(Name: string);
var
i: integer;
begin
for no:=1 to length(ParticleSystem)-1 do begin
if ParticleSystem[i].Name = Name then begin
//zde vymažeme ParticleSystem[i] a všechny další
//posuneme o jeden dopředu...
end;
end;
end;
function ParticleManagerC.FindParticleSystem(Name: string): ParticleSystemC;
var
i: integer;
begin
for i:=1 to length(ParticleSystem)-1 do begin
if ParticleSystem[i].Name = Name then begin
result := ParticleSystem[i];
end;
end;
end;
![]() |
| Toto je nejjednoduší aplikace částicového systému. |
procedure ParticleManagerC.Update;
var
i, j: integer;
Time: single;
CountNew: integer;
begin
Time := GetTickCount/100;
//Pro aktivní každý částicový systém...
for i:=0 to length(ParticleSystem)-1 do with ParticleSystem[i] do begin
if Active = true then begin
CountNew := 0;
//...a pro každou částici dělej:
for j:=0 to length(Particles)-1 do begin
//Pokud vyhasla...
if Particles[j].EndTime <= time then begin
if CountNew>10 then continue;
//Vygeneruj novou částici...
Particles[j].Position := Position;
Particles[j].OldPosition := Position;
//Nastavíme náhodný rozptyl každé nové částice
Particles[j].Direction := VectorAdd(
Direction,
AffineVectorMake(
(random(DirectionError)-DirectionError/2)/127,
(random(DirectionError)-DirectionError/2)/127,
(random(DirectionError)-DirectionError/2)/127));
//... a nastav její životnost náhodně v rozmězí 1 krát až 1,5 krát LifeTime.
Particles[j].EndTime := Time+Lifetime*(1+random(LifeTimeError)/512);
inc(CountNew);
//Pokud nevyhasla, vypočítej její novou pozici.
end else begin
Particles[j].OldPosition := Particles[j].Position;
Particles[j].Direction[1] := Particles[j].Direction[1] - Gravity/100;
Particles[j].Position :=
VectorAdd(
Particles[j].Position,
VectorScale(
VectorScale(
Particles[j].Direction,
Speed),
(Particles[j].EndTime-Time)/LifeTime));
end;
end;
end;
end;
end;
procedure ParticleManagerC.Render;
var
i: integer;
begin
//Pro aktivní každý částicový systém...
for i:=0 to length(ParticleSystem)-1 do with ParticleSystem[i] do begin
if Active = true then begin
Material.Activate;
ParticleSystem[i].Render(Camera);
Material.DeActivate;
end;
end;
end;
Vyšlo 07.08.2002, v blogu: 0 1 2 3 4 5 6 7 8
Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení
Poslední články
- Engine (2.) - Timing
- Engine (1.) - Logování
- OpenGL (17.) - Light mapping - úvod
- OpenGL (16.) - Fading
- Herní grafické enginy (3.) - GLScene
- Herní grafické enginy (2.) - Pythian Project
- OpenGL (15.) - Ucelený částicový systém - pokračování
- OpenGL (14.) - Ucelený částicový systém
- OpenGL (13.) - Nastavení OpenGL v jazyce C/C++
- 3D Studio MAX (13.) - Popis modifikačních funkcí ve 3D Studiu MAX
- OpenGL (12.) - visualizační plugin pro WinAMP
- Delphi (10.) - knihovna FMOD
- Herní grafické enginy (1.) - MEngine od Mister Group
- Delphi (9.) - Download 2
- Delphi (8.) - Download

