Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Schreiben einer kleinen 3D-Engine - Timer (https://www.delphipraxis.net/18683-schreiben-einer-kleinen-3d-engine-timer.html)

Jörn 23. Mär 2004 09:43


Schreiben einer kleinen 3D-Engine - Timer
 
Ich habe mir seit Anfang des Jahres eine Menge Wissen über 3D-Engines angelesen und kleine Tests gemacht (insbesondere zu Netzwerk). Nun möchte ich testweise eine eigene, kleine Engine schreiben. Dies auf Basis der VCL, für Grafik verwende ich OpenGL, für Sound OpenAL, und für den Netzwerkteil die klassischen Komponenten TServerSocket und TClientSocket. Dann benötige ich aber noch einen Timer! Der normale von Delphi ist mir zu ungenau. Den von DelphiX möchte ich so in dieser Form nicht verwenden, weil ich diese ganze Komponenten-Sammlung nicht installieren möchte/kann (macht bei mir in der Schule Probleme mit dem Delphi6 PE, liegt laut Lehrer am Schulnetzwerk weil Delphi nicht lokal installiert ist und auf dem Server liegt). Also bräuchte ich einen Timer, den ich über eine einfache Unit einbinden kann. Gibt es das schon vorgefertigt? Wie kann ich es im Zweifelsfalle realisieren? Ich kann zwar eigene Komponenten schreiben bzw ableiten, aber ich habe keinen Schimmer, wie ich ein 'OnTimer'-Ereignis selber schreibe.

Wer kann mir helfen?

MfG

Robert 23. Mär 2004 12:11

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Also folgende Hilfe könnte ich geben:

Delphi besitzt eine OnIdle Routine, die die Applikation (die Winmain-Routine quasi) aufruft, wenn keine Nachrichten (WM_PAINT etc.) zu verarbeiten sind.

Sie ist ziemlich hochauflösend. Schau mal unter OnIdle in der Online-Hilfe.

Ansonsten einfach mit einem Thread machen. Es gibt da glaube ich einen DXTimer, der ziemlich gute Auflösungen schaffen soll.

Jörn 23. Mär 2004 12:21

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Dieser DXTimer ist der von DelphiX. Dann kenn ich auch noch den SanosTimer, der hat aber keine .pas und ich hab daher keine Ahnung wie ich den verwenden kann. Dann kenn ich noch den HighResTimer, den kann ich installieren und so, aber der hat nur einen Prozedur zum einmaligen warten und keine Schleife mit OnTimer-Ereignis. Könnte das aber mit einer boolean-Variable mache und einer Repeat-until-Schleife die solange ausgeführt wird bis ich die Variable auf false setze. Andere Vorschläge?

neolithos 23. Mär 2004 12:22

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Ich habe dieses Problem mit einem Thread und CreateWaitableTimer realisiert.

Das Ereignis kann man durch eine CallBack
Delphi-Quellcode:
type
  T??? = class
    fOnTimer : TNotifyEvent;

    property OnTimer : TNotifyEvent read fOnTimer write fOnTimer;

  if Assigned(fOnTimer) then
     fOnTimer(Self);
oder

eine Botschaft auslösen

PostMessage(hwndMain, WM_APP + ????, 0, 0);

Jörn 23. Mär 2004 17:22

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Die Möglichkeit gefällt mir wirklich gut! Aber ich habe da 3 Fragen:
  • Ich sehe da nix mit Thread?!?
  • die letzten beiden Zeilen, kommen die wirklich da hin (if Assigned..) ?
  • wie wird assigned(fOnTimer) = true? Muss ich da noch eine Prozedur schreiben die immer entsprechend wartet, und dann dieses Ereignis irgendwie auslöst? Und wenn ja, dann weiss ich leider auch nicht wirklich wie ich das anstellen muss...

MfG

EDIT: Wenn ich die Hilfe richtig verstehe, muss ich das TNotifyEvent da verändern. Da muss dieses Warten rein. Und wenn ich dann auch noch richtig liege, das ich auf die property OnTimer in dieser Prozedur schreibend zugreifen kann und auf true setze, wird das Event ausgelöst oder wie??

neolithos 23. Mär 2004 17:49

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Das war natürlich nur eine Skizze.

Für den kompletten Timer braucht man schon etwas mehr Code.

Ich wollte dir da nur ein paar Stichworte gegeben, die die Idee formen könnten.

Na gut, etwas mehr:

Delphi-Quellcode:
type
  TExTimer = class (TThread)
  private
    fOnTimer : TNotifyEvent;

    hClose : Cardinal;
  protected
    procedure Execute; override;
  public

Hinweis: in Destroy muss der Thread über das hClose-Event beendet werden!!!

    property OnTimer : TNotifyEvent read fOnTimer write fOnTimer;
  end;

procedure TExTimer.Execute;
var hTimer : Cardinal;
    lQuit : Boolean;
    aObjs : array [0..1] of Cardinal;
begin
  hClose := CreateEvent( ??? ); // Event damit der Thread sauber beendet werden kann
  hTimer := CreateWaitableTimer(nil, false, nil);
  SetWaitableTimer(hTimer, ???);
 
  aObjs[0] := hTimer;
  aObjs[1] := hClose;

  lQuit := false;
  repeat
    case WaitForMultipleObjects(2, @aObjs, false, INFINITE, false) of
         WAIT_OBJECT_0:
           if Assigned(fOnTimer) then
              fOnTimer(Self);
         WAIT_OBJECT_0 + 1:
           lQuit := true;
         else
            // Fehler
    end;
    end;
  until not lQuit;

  CloseHandle(hTimer);
end;
Das Teil ist noch nicht FERTIG!

Jörn 23. Mär 2004 18:42

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Ja das hilft meinem Verständnis schon sehr. Vielen Dank erstmal, ich werde mir das mal genauer ansehen.

MfG

OregonGhost 24. Mär 2004 17:57

Re: Schreiben einer kleinen 3D-Engine - Timer
 
Möchtest du den Timer haben, um eine bestimmte Zeit abzuwarten und dann benachrichtigt zu werden, oder möchtest du über den Timer die gesamte Engine laufen lassen?
In letzterem Fall rate ich dir davon ab, schreib' schön deine Gameloop selbst und verwende zur Zeitmessung zum Beispiel den PerformanceCounter (QueryPerformanceCounter).

Es gibt da einen Artikel zu dem Thema. In dem wird ausführlich erklärt, warum weder OnIdle noch ein beliebiger Timer verwendet werden sollten, um eine Game Engine am laufen zu halten.
http://www.mvps.org/directx/articles..._game_loop.htm
Achtung: Der Artikel beschreibt die Hintergründe, den Code am Ende würde ich allerdings so nicht empfehlen (Framebegrenzung sollte man nur dann implementieren, wenn es wirklich notwendig ist und wenn man weiß warum). Der Code unter "Keeping Awake" ist aber ein optimaler Ausgangspunkt.

[Addendum]
http://www.mvps.org/directx/articles..._functions.htm zeigt noch etwas über die Auswahl der richtigen Zeitfunktionen.
[/Addendum]

Jörn 24. Mär 2004 19:20

Re: Schreiben einer kleinen 3D-Engine - Timer
 
OregonGhost, hab mir das aufmerksam durchgelesen. Die Idee dahinter ist zwar in einem kommerziellen Spiel o.ä. sinnvoll, da meine Engine aber im Großen und Ganzen nur zum Testen und lernen da sein wird, werde ich auf Timer und OnIdle zurückgreifen. Und die Zeitmessung zwischen Frames mache ich schon über den PerformanceCounter der CPU. Daraus ergibt sich bei einem leeren OpenGL-Vollbild bei 1024x768x32 auf einem Athlon TBird mit 256 MB RAM und einer Radeon9600 bisher stolze 1400 FPS. Also wird die Leistung auch bei etwas komplexeren Szenen ausreichen... Trotzdem vielen Dank!


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz