blog.vi-kan.net One thought after another

1st particle-challenge: Getting something unto the screen

No firework, but its somethingA couple of days ago, I took a challenge to show that making a particle engine is not that hard. I also stated that the first part of the challenge would be to get something unto the screen, and that is as far as I have come. I have enough code to emit particles unto the screen, beautifully rendered as small triangles in various colors.

Well – its no firework, but it’s a start…

For those who are interested in the code, it’s available for  download here. The lib-folder contains two libraries that I use. First of all, there is the Free Pascal OpenGL Headers used for rendering. Second, there is a folder called ‘SDL’, which is a older version of the Delphi Container and Algorithm Library (DeCAL).  I started using it for many, many years ago, back when it was a commercial product. It was called Standard Delphi Library, but was renamed to avoid confusion with ‘Simple DirectMedia Library’. I guess it’s time to find something else, and when I start using Delphi 2009, I will for sure.

So, how did I put something unto the screen?

I started off with a simple TParticle class with information about position, velocity, color, time to live and age.

 TParticle = class(TObject)
  public
    constructor Create;

    procedure Update(DeltaFrame: int64);

    property Position: TVector3D read FPosition write FPosition;
    property Velocity: TVector3D read FVelocity write FVelocity;

    property Color: TColorFA read FColor write FColor;

    property TimeToLive: int64 read FTimeToLive write FTimeToLive;
    property Age: int64 read GetAge;
    property Dead: boolean read FDead write FDead;
  end;

Then followed a TParticleManager to hold all the particles.

 TParticleManager = class(TObject)
  public
    constructor Create;
    destructor Destroy; override;

    procedure AddEmitter(Emitter: TParticleEmitter);

    procedure ProcessFrame;

    property Particles: DArray read FPArticles;
  end;

For each ‘game loop’, the particle manager will loop through all particles, destroying those that have lived their age, and telling the others to update them self. When calling Update( ) on the particle, it pass in the tickcount since update. This is to ensure a relatively smooth and natural movement even if the fps is not stable.

 procedure TParticleManager.ProcessFrame;
  var
    CurrentFrame: int64;
    FrameDelta: int64;
  begin
    CurrentFrame := GetTickCount;
    FrameDelta := CurrentFrame - FLastFrame;

    RemoveDeadParticles;
    EmittNewParticles(FrameDelta);
    ProcessParticles(FrameDelta);

    FLastFrame := CurrentFrame;
  end;

It will also contain a list of TParticleEmitters. The particle emitter will get it’s chance to emit new particles once every loop. It is the emitters responsibility to give the new particles a initial position and velocity.

 TParticleEmitter = class(TObject)
  public
    constructor Create;
    procedure EmittParticles(TimeSinceLastFrame: int64; Particles: DArray);

    property ParticlesPrTick: extended read FParticlesPrTick write FParticlesPrTick;
  end;

The rendering is separated into it’s own class, TRendrer. This class will to all the OpenGL initialization-stuff. It is given a list of objects to render, where each item must implement the IRenderItem interface. In this way, the rendrer do not need to know anything about what it renders. It just setup a place for the rendering to happend, and asks the item to draw it self.

 TRendrer = class(TObject)
  public
    constructor Create(AHandle: THandle);
    destructor Destroy; override;

    procedure Render(ItemsToRender: DArray);

    procedure HandleResize(NewSize: TRect);
  end;

To make the particle able to render it self, I have made a sub class, TVisualParticle, which implements IRenderItem. For now, it just draws a small triangle in the particles color.

procedure TVisualParticle.Render;
begin
  glPushMatrix();
  glTranslatef(Position.x, Position.y, Position.z);

  glBegin(GL_TRIANGLES);
    glColor4f(Color.Red, Color.Green, Color.Blue, Color.Alpha);
    glVertex3f(-0.1,-0.1, 0);
    glVertex3f( 0.1,-0.1, 0);
    glVertex3f( 0.0, 0.1, 0);
  glEnd;

  glPopMatrix;
end;

From here, there are a couple of things that needs improvements. I need to explore OpenGL a bit more to get control over ‘the world’ that the particles lives in. Maybe a camera-model or something is needed. I don’t know. I also need to look into ways of rendering a little more interesting particles then triangles… And then there are physics – particles should be able to react to gravity and other forces as well. I’m not sure where I will start though. Time will show…

comments powered by Disqus