Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Jul 16, 2025 11:55

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Fr Feb 24, 2012 20:35 
Offline
DGL Member

Registriert: Mo Aug 23, 2010 19:45
Beiträge: 16
Programmiersprache: Delphi und noch mehr
Hallo Leute,

ich bins mal wieder. Da ich ja ausgiebiger Fan von LED Matrizen und LED Cubes bin, kam mir der Gedanke mal mit OpenGL eine große Matrix/Cube (im Grunde is es nur eine Dimension mehr) darzustellen um damit ein wenig mit Animation rumzuspielen.
Also im Grunde mein bisheriger Stand ist soweit, dass man ein Array hat wo der Zustand des aktuellen Pixels steht (an oder aus). Dieses Array wird dann mit OpenGL (OnIdle Methode) dargestellt.

Nun möchte ich gerne die Animationen fortlaufend haben und diese soll man natürlich auch ein- und ausschalten können. Im Grunde dachte ich, ich nehme dafür ein Timer den kann ich ein- und ausschalten und im Timerevent wird dann nur noch in einer Case-Anweisung überprüft welche Animation hat man ausgewählt und diese Prozedur wird dann aufgerufen.

Jetzt kommt aber der Punkt an dem ich hängen bleiben. Ich möchte erstmal eine einfach Animation in dem der ganze Cube einfach blinkt. Die Prozedur ist in dem Punkt einfach eine Periode. Im Grunde im Pseudocode sieht das so aus:
Code:
  1. LED Cube an
  2. 500ms warten
  3. LED Cube aus
  4. 500ms warten


So aber nun kommt das. Wie gestalte ich das 500ms warten, so dass er nebenher noch rendern kann?
Sleep legt ja den aktuellen Thread schlafen und somit freezt mein Programm. Meine anderen Versuche mit Delay (GettickCount und Application.ProcessMessages) und einem anderen Thread der eine Variable hochzählt und in meiner Animationsprozedur einfach mit einer repeat ... until variable = 500 Application.ProcessMessages aufruft haben auch zu einem Freeze geführt.

So langsam weiße ich auch nicht mehr weiter und ob das mit einem 2ten Thread funktioniert habe ich auch keine Ahnung. Vielleicht weiß jemand von euch weiter und kann mir helfen ich wäre euch sehr dankbar darüber.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Feb 24, 2012 21:34 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Dein komplettes Programm sollte in der OnIdle-Methode stattfinden. Das ist quasi deine Hauptschleife. Mit Blick auf mögliche Animationen die du vermutlich implementieren willst, solltest du zunächst solltest du die Zeit messen die seit dem letzten Frame (aka Aufruf von OnIdle) vergangen ist. Vom Prinzip kann man das mit GetTickCount machen, was allerdings extrem ungenau ist. Es ist besser QueryPerformanceCounter zu benutzen, einfach die Forensuche benutzen, dazu gibt es häufiger Fragen hier. Z.B. hier:
viewtopic.php?f=10&t=10243&start=0

Nun solltest du irgendwie die Zeit in Sekunden seit dem letzten Frame in einer Variable haben, traditionell deltaTime genannt.

Nun kannst du damit eine beliebe Animation mit einem Index clock und der Länge length sehr genau abspielen. Du brauchst keiner Timer-Klasse (oder gar extra Threads o.O) mehr, du musst nur clock um deltaTime weiter rücken.

Hier mal als Beispiel eine Animation die die LED blicken lässt, aber nicht statisch an/aus sondern mit variabler Helligkeit:
Code:
  1. // initialisierung
  2. length := 2;   // Animationsdauer 2 Sekunden
  3. clock := 0;
  4. direction := 1;
  5.  
  6. // update (jedes Frame)
  7. clock := clock + direction * deltaTime;
  8. if (clock >= length) then begin
  9.     clock := 2*length - clock;  // wir werden quasi niemals genau auf length landen
  10.     direction := -1; // Richtung umkehren
  11. end else if (clock < 0) begin
  12.     clock := -clock;
  13.     direction := 1;  
  14. end;
  15. brightness := clock / length; // brightness liegt zwischen 0 und 1...einfach mit der Farbe multiplizieren.


Für jede LED bzw. Animation hättest du nun so eine clock-Variable.
Damit es gut aussieht empfiehlt es sich noch ein smoothstep auf die Interpolation anzuwenden. Dies wirkt deutlich weicher/besser:
Code:
  1. brightness := brightness*brightness*(3 - 2*brightness);

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Feb 25, 2012 11:44 
Offline
DGL Member

Registriert: Mo Aug 23, 2010 19:45
Beiträge: 16
Programmiersprache: Delphi und noch mehr
Danke schonmal für deine Hilfe, ich werde mich heute Abend mal damit beschäftigen.
Danke nochmal.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Feb 26, 2012 15:50 
Offline
DGL Member

Registriert: Mo Aug 23, 2010 19:45
Beiträge: 16
Programmiersprache: Delphi und noch mehr
So ich mir das nun nochmal genauer angeschaut. Und soweit ich das richtig sehe, dann meinst du auch das ich die Anweisungen wie Cube an, Cube aus, Ebene 3 an, Säule 8 an auch im Render darstellen soll oder?
Das ist doch dann eigentlich viel mehr Rechenarbeit oder nicht?

Ich hätte da halt schon gern die ganzen Animation in einer Unit und die "Zeichenroutinen" (also einfach schnell ne Anweisung Cube an die dann das Array füllt oder Rahmen der Größe 4) in einer anderen Unit, denn natürlich habe ich auch vor einen größeren LED Cube zu bauen, dann kann ich die Animation einfach "übersetzen".


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Feb 26, 2012 17:41 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
So ich mir das nun nochmal genauer angeschaut. Und soweit ich das richtig sehe, dann meinst du auch das ich die Anweisungen wie Cube an, Cube aus, Ebene 3 an, Säule 8 an auch im Render darstellen soll oder?
Das ist doch dann eigentlich viel mehr Rechenarbeit oder nicht?

Ich bin mir nicht ganz sicher was du meinst. Niemand hindert dich daran deinen Quellcode schön zu strukturieren. Üblicherweise sieht OnIdle ungefähr so aus:
Code:
  1. deltaTime := ....Zeitmessung...
  2.  
  3. Update(deltaTime);
  4. Render();

Die ganze Logik mit deinen Animationen findet in Update statt. Hier würdest du eben für jede LED eine Farbe setzen (oder was auch immer). Die Funktion Render rendert einfach nur ohne irgendwas am Zustand der Szene zu ändern. Diese Trennung wird insbesondere dann sinnvoll wenn du später feststellst das du für irgendeinen Spezialeffekt (Schatten, Reflektion, Glow, ...) die Szene mehrfach rendern musst.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Mär 01, 2012 20:09 
Offline
DGL Member

Registriert: Mo Aug 23, 2010 19:45
Beiträge: 16
Programmiersprache: Delphi und noch mehr
Naja so wie du das meinst so sehe ich das ja dann noch ein, dann zähl ich in dieser Funktion dann die Zeit hoch und hab dann eine Statusvariable (in dem Falle dann Boolean). Im Prinzip dann so (ist jetzt nur Pseudocode):
Code:
  1.  
  2. inc(i);
  3. if i = 500 and ison then
  4. begin
  5. led cube off
  6. i = 0
  7. ison = false
  8. end
  9. else if i = 500 and not ison then
  10. begin
  11. led cube an
  12. i = 0
  13. ison = true
  14. end
  15.  


Wie mache ich das denn nun, wenn ich zum Beispiel eine durchlaufende Ebene haben will? Da wäre dann die Logik in etwa so:
Code:
  1.  
  2. ebene 1 an
  3. 500 ms warten
  4. ebene 1 aus
  5. ebene 2 an
  6. 500 ms warten
  7. ebene 2 aus
  8. ebene 3 an
  9. 500 ms warten
  10. //und so weiter
  11.  


Dann hätte ich ja theoretisch mehrere Statusvariablen, richtig? Oder gäbe es da auch eine besser Möglichkeit eine Wartezeit zu realisieren?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Mär 02, 2012 18:01 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Du hast eine "clock" für die ganze Animation:
Code:
  1. if (clock < 0.5) {
  2.    ebene 1 an
  3. }
  4. else if (clock < 1.0) {
  5.    ebene 1 aus
  6.    ebene 2 an
  7. }
  8. else if (clock < 1.5) {
  9.    ebene 2 aus
  10.    ebene 3 an
  11. }
  12. ...


Dieses if-Konstrukt lässt sich natürlich auch leicht als Schleife bauen.
Das ist natürlich die einfache Lösung.


Du kannst dir auch ein richtiges Animationssystem bauen. Etwa eine Basisklasse Animation. Davon eine EbenenAnimation ableiten die eine Ebene an oder ausschalten kann. Dann definierst du dir noch eine AnimationSequence, so dass du mehrere Objekte der Klasse Animation hintereinander ausführen kannst.
Code:
  1. sequence.add(EbenenAnimation(EBENE_1, AN, 0.0));
  2. sequence.add(EbenenAnimation(EBENE_1, AUS, 0.5));
  3. sequence.add(EbenenAnimation(EBENE_2, AN, 0.5));
  4. sequence.add(EbenenAnimation(EBENE_2, AUS, 1.0));
  5. sequence.add(EbenenAnimation(EBENE_3, AN, 1.0));

....

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 20 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 15 Queries | GZIP : On ]