Seite 8 von 9
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 22.07.2010, 19:36
von HeinzK
Vielen Dank für die vielen Tipps. So werde ich Stück für Stück heimelicher in der 'neuen Welt'.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 22.07.2010, 19:48
von HeinzK
Auf dem Weg von DDraw nach OpenGL ..
Der erste Durchbruch ist mit Hilfe von SDL geschafft.
Mein 'Zeichen-Programm' läuft auf Linux/Ubuntu .. "F" "R" "E" "U" "D" "E".
Über Pixel, Linien, Dreiecke, Rechtecke, Sechsecke, Kreise, Bögen, Ellipsen, Polylinien und Texte.
Heute Abend versuche ich noch OpenGL von Win32 nach Linux zu portieren. Wenn das klappt,
habe ich morgen abend Zeit für einen ausführlicheren Bericht. Bis dann.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 14:24
von kimmi
Gratlation zu deinen Fortschritten. Ich bin schon sehr gespannt, was da noch alles kommt. Wenn du deine Erfahrungen zum Portieren hier noch etwas erläutern willst, könnten bestimmt noch einige davon pofitieren.
Gruß Kimmi
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 14:29
von HeinzK
Ich tue was zeitlich möglich ist (S'ist halt' en Näbäzschopb).
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 19:02
von HeinzK
Bin leider gestern abend mit OpenGL von Windows nach Linux nicht ganz fertiggeworden ..
Ubuntu/gcc/OpenGL/X11:
Code: Alles auswählen
while (1)
{
do
{
XNextEvent(Dply, &event);
switch(event.type)
{
case KeyPress:
{
exit(0);
break;
}
case ConfigureNotify:
{
glViewport
(
0,
0,
event.xconfigure.width,
event.xconfigure.height
);
break;
}
case Expose:
{
break;
}
default:
{
break;
}
}
} while (XPending(Dply));
//> Loop(TuWas):
}
Gibt es unter X11 ein äquivalent zu PeekMessage()?
Oder wie gestalte ich am Besten meine Loop?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 19:27
von HeinzK
Ich habe im Moment eine für meine Zwecke ausreichende Lösung gefunden:
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 19:31
von Tobiking
Hast du nicht noch das Problem das XNextEvent() blockiert wenn keine Events da sind? Ich hab das damals so gelöst das ich mir mit XEventsQueued() die Zahl der Events hole und XNextEvent() nur aufrufe wenn auch Events da sind.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 20:12
von HeinzK
Danke für die Info. Ich habe mir daraus etwas zusammengereimt .. was funktioniert .. aber ich nicht sicher bin,
ob es auch ganz richtig ist. Kann mal einer einen Blick darauf werfen?
Code: Alles auswählen
while (1)
{
long lE = XEventsQueued(Dply, QueuedAfterFlush);
while (lE > 0)
{
lE--;
XNextEvent(Dply, &event);
switch(event.type)
{
case KeyPress:
{
exit(0);
break;
}
case ConfigureNotify:
{
glViewport
(
0,
0,
event.xconfigure.width,
event.xconfigure.height
);
break;
}
case Expose:
{
break;
}
default:
{
break;
}
}
}
XFlush(Dply);
//>Loop(TuWas);
}
Also: XEventsQueued() .. XNextEvent() .. XFlush() OK?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 23.07.2010, 21:28
von HeinzK
Geschafft. Die gesamte Grafik läuft unter Linux! 8-)
Einmal mit Hilfe von SDL (sehr gut) und einmal nur OpenGL (nicht so gut, wegen DrawPixels und
fehlendem ZeroMemory, FillMemory und Co.) Unter Windows habe ich nun DDraw und OpenGL am Laufen.
Aber die SDL-Version werde ich auch noch testen. Bericht folgt.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 24.07.2010, 17:05
von HeinzK
Zeiten sind das. Ich kämpf' gerade mit den letzten Kleinigkeiten.
Die Zeit zum 'Zeichnen' meiner Objekte war unter SDL fast immer Null.
Da ich aber sicher bin, dass in allen Varianten der gleiche Code abläuft,
habe ich mir den SDL_GetTicks() genauer angeschaut.
Hier meine bisherige Zeitmessung unter Linux/Ubuntu:
Code: Alles auswählen
#ifdef ZWIANER_SDL
k_dZeit = SDL_GetTicks();
#else
timeval tv;
gettimeofday(&tv, 0);
k_dZeit = ((double)tv.tv_sec * 1000.0);
k_dZeit += ((double)tv.tv_usec / 1000.0);
#endif
Und hier der Testcode:
Code: Alles auswählen
unsigned long ulLoop = 0;
double dZeit1 = pZeit->GetdZeit(); //> Ohne SDL:
double dZeit2 = SDL_GetTicks();
double dDiff1 = dZeit1;
double dDiff2 = dZeit2;
while (ulLoop < 100000) //LONG_MAX)
{
ulLoop++;
if ((ulLoop % 10000) == 0)
{
dZeit1 = pZeit->GetdZeit(); //> Ohne SDL:
dZeit2 = SDL_GetTicks();
KTRACE
(
"Zeit(Kempter/SDL): %0.5f / %0.5f\n",
(dZeit1 - dDiff1),
(dZeit2 - dDiff2)
);
dDiff1 = dZeit1;
dDiff2 = dZeit2;
}
}
Und hier das Ergebniss für 'kleine Werte':
Und hier für 'größere Werte' (* 1000):
Allerdings sind alle Werte aus dem Debugmodus.
Das ist ein typischer Fall für Probleme von "Auf dem Weg von DDraw nach OpenGL".
Man redet über die Zeit und kommt nicht auf die Idee, dass der neue Nachbar
nur in ganzen Millisekunden denkt!
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 24.07.2010, 18:19
von HeinzK
Am Ende doch noch angekommen ..
Hier nun die Ergebnisse meiner Mühen:
Hinweis1: DDraw(32bit) ist immer im Vollbildmodus. Auf meinem Testrechner 1440/900, alle anderen Test's laufen mit 800/600.
Hinweis2: Ubuntu 10 läuft bei mir (Laptop) unter VMWare.
Hinweis3: LoopR/LoopReserve ist die Restzeit die bei einer Framerate von 30 Bilder pro Sekunden noch für weitere Berechnungen übrig bleibt!
Hier die Downloads zum selber Testen:
Linux/OpenGL:
http://www.zwianer.de/$PCSpiel$/Downloa ... OpenGL.exe
Linux/SDL:
http://www.zwianer.de/$PCSpiel$/Downloa ... nenSDL.exe
Windows/OpenGL:
http://www.zwianer.de/$PCSpiel$/Downloa ... OpenGL.exe
Windows/DDraw:
http://www.zwianer.de/$PCSpiel$/Downloa ... nDDraw.exe
Zeit: Zeichnen= Durchschnitt/Maximum * Malen= Durchschnitt/Maxium
Zeit: LoopReserve= Durchschnitt bzw. DrawPixels= Minimum/Durchschnit/Maximum * LoopR= Durchschnitt
Zeichnen: Hier werden alle 'Grafischen Objektdaten', getrennt nach Gruppe/Ebene/Layer in einer Datenbank gespeichert.
Malen: Pixel werden entweder direkt (DDraw/SDL) in das VRam geschrieben oder in einem PixelBuffer (OpenGL) zwischengespeichert und dann mit
DrawPixels ausgeben.
Ich würde mich freuen wenn ihr die Downloads auf möglichst vielen Rechnern ausprobiert!
Wenn ihr die Daten mit der zusätzlichen Angabe: Betriebssystem/Rechner/Grafikkarte an mich sendet werden ich die Ergebnisse als Exceltabelle hier veröffnetlichen.
Email:
Heinz.Kempter@ZwiAner.de Betreff: Pixeltest.
EDIT:
25.07.10 8:53 Wndows/OpenGL konnten nicht geholt werden.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 25.07.2010, 15:49
von HeinzK
Ein Erfahrungsbericht:
http://zwianer.de/$PCSpiel$/Download/Te ... OpenGL.pdf
Danke für die Hilfe bis hier her.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 15:30
von HeinzK
Ich bin am Einbauen meiner CKString (anstellen von CString) in die ZwiAner:
Nun stolpere ich gerade über folgendes Problem:
Code: Alles auswählen
//> Auszüge aus dem Quelltext:
class CKString
{
public:
CKString(void);
CKString(const CKString &sKStr);
CKString(const string &sStr);
CKString(const char *cStr);
virtual ~CKString(void);
//> ... usw:
CKString operator + (const CKString &sKStr) const;
CKString operator + (const string &sStr) const;
CKString operator + (const char *sStr) const;
//> ... usw:
};
//> Einsatz:
{
CString sCa;
//> sCa = "1" + "2"; //> ???: //> Fall1c:
CString sCb;
sCa = "a";
sCb = "b";
sCa = sCb + "2"; //> Fall2c:
sCb = sCa + "1"; //> Fall3c:
sCa = "1" + sCb; //> Fall4c:
sCb = "2" + sCa; //> Fall5c:
sCa = "A" + sCb + "B" + "C"; //> Fall6c:
CKString sKa;
//> sKa = "1" + "2"; //> ???: //> Fall1k:
CKString sKb;
sKa = "a";
sKb = "b";
sKa = sKb + "2"; //> Fall2k:
sKb = sKa + "1"; //> Fall3k:
//sKa = "1" + sKb; //> Fall4k:
//sKb = "2" + sKa; //> Fall5k:
//sKa = "A" + sKb + "B" + "C"; //> Fall6k:
}
Was mich interessieren würde, wie schaff' ich es, das Fall 4,5 und 6 auch bei CKString funktionieren?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 15:34
von Aramis
Der
operator+ sollte ausserhalb der Klasse definiert werden.
Code: Alles auswählen
class CKString {
CKString(const char*) {
...
}
CKString& operator += (const CKString& other) {
...
return *this;
}
};
CKString operator+ (const CKString& a, const CKString& b) {
return CKString(a) += b;
}
Mit diesem Trick (Eigentlicher Code in '+=', operator+ ruft diesen nur auf), kannst du vermeiden die ganze Logik zum Aneinanderhaengen der Strings zu duplizieren.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 15:43
von HeinzK
Ok, werde ich ausprobieren.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 15:57
von HeinzK
operator += habe ich schon in der o.a. Schreibweise in Verwendung.
Code: Alles auswählen
sKa = sKb + "A" + "B" + "C"; //> OK:
sKa = "A" + sKb + "B" + "C"; //> Funktioniert nicht:
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 16:06
von Schrompf
Die zweite Zeile verlangt zuerst nach einem operator + (const char*, const kstring&) - hast Du einen solchen Operator definiert?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 16:10
von HeinzK
Aha, einen operator + mit zwei Argumenten! .. Hab' ich noch nicht .. aber gleich ... Danke!
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 16:14
von Aramis
Sollte nicht notwendig sein solange der Konversionskonstruktor
KCString(const char*) existiert, erreichbar ist und nicht als
explizit deklariert wird. Siehe mein Beispiel, der darin aufgeführte
operator+ genügt.
Code: Alles auswählen
CKString operator+ (const CKString& a, const CKString& b) {}
Wichtig! Dieser Operator darf *nicht* als gebundene Memberfunktion deklariert sein, weil sonst keine implizite Konversion fuer den impliziten
this-Parameter zum Einsatz kommt.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 16:14
von Schrompf
Alle + Operatoren und Artverwandte haben zwei Operanden. Aber wenn Du den Operator innerhalb der Klasse definierst, wird der erste Operand automatisch als die Klasse selbst angenommen. Sowas hier:
Code: Alles auswählen
// Variante 1
class Bla
{
Bla operator + (const Bla& dasAndereBla) const;
}
// ist gleichwertig mit einem freien Operator der Art
Bla operator + (const Bla& dasEineBla, const Bla& dasAndereBla);
Wenn Du jetzt einen operator + (const char*, const Bla&) brauchst, müsstest Du den als Variante 1 in der Klasse char* definieren... das geht natürlich nicht. Daher musst Du den als Variante 2, nämlich als freien Operator, definieren.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 16:32
von HeinzK
Ich meinte es verstanden zu haben, aber es geht noch nicht ..
Code: Alles auswählen
//> *.h, nach der Klassendeklaration:
//> Freie operatoren:
CKString operator + (const char *cStr, const CKString &sKStr) const;
//> *.cpp, nach der Klassenimplementation:
//> Freie Operatoren:
CKString operator + (const char *cStr, const CKString &sKStr) const
{
string sS(cStr);
sS.append(sKStr.GetcStr());
return sS;
}
Fehlermeldung:
error C2270: '+': Modifizierer für Funktionen, die keine Memberfunktionen sind, nicht zulässig
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 17:21
von Biolunar
Da es sich um globale Funktionen handelt macht das 'const' am Ende nach der eigentlichen Funktions-Deklaration/Definition keinen Sinn.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 17:36
von HeinzK
Super, das war's, nun funktioniert alles wie gewollt .. Danke.
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 18:01
von HeinzK
Noch ein Rätsel ..
Code: Alles auswählen
string k_sStr;
const char *CKString::GetcStr(void) const
{
return k_sStr.c_str();
}
string CKString::Format(const CKString &sKStr, ...)
{
const char *pFrm = sKStr.GetcStr();
va_list Argm;
va_start(Argm, pFrm);
k_sStr = KFormatArgmList(pFrm, Argm);
k_iStrLen = k_sStr.length();
va_end(Argm);
return k_sStr;
}
string CKString::Format(const char *pFrm, ...)
{
va_list Argm;
va_start(Argm, pFrm);
k_sStr = KFormatArgmList(pFrm, Argm);
k_iStrLen = k_sStr.length();
va_end(Argm);
return k_sStr;
}
//> Einsatz:
CKString sK1;
CKString sK2 = "\nTest: %0.2f";
sK1.Format(sK2, 100.0); //> Fall1:
sK1.Format(sK2.GetcStr(), 100.0); //> Fall2:
sK1.Format("\nTest: %0.2f", 100.0); //> Fall3
Nur Fall1 funktioniert nicht. Kann es sein, das in
k_sStr = KFormatArgmList(pFrm, Argm);
pFrm und Argm unbedingt Funktionsparameter sein müssen?
Also das pFrm nicht innerhalb der Funktion definiert werden kann?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 29.07.2010, 18:20
von Aramis
Davon ausgehend dass KFormatArgmList unefaehr so aussieht:
CKString KFormatArmList(const char*, va_list&);
: Nein. Aber ich wuerde va_start richtig aufrufen :-)
Code: Alles auswählen
va_start(Argm, pFrm); // sollte wohl eher sKStr anstelle von pFrm sein
Btw, das ganze ist ein wunderschoenes Beispiel fuer Copy'n'Paste-Fehler :-)
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 30.07.2010, 07:01
von HeinzK
Genau waren es zwei Probleme. Ich hatte den Mechanismus von va noch nicht verstanden.
Also, erstens hast du Recht (sKStr statt pFrm) und zweites darf es nicht &sKStr heissen.
Danke für die Infos .. nun läufts ...
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 30.07.2010, 08:41
von HeinzK
Mir fehlt die Erfahrung um folgendes richtig zu entscheiden:
Code: Alles auswählen
class CKString
{
public:
CKString(void);
CKString(const CKString &sKStr);
CKString(const string &sStr);
CKString(const char *cStr);
virtual ~CKString(void);
// ...
int Compare(const CKString &sKStr) const;
//> int Compare(const string &sStr) const;
//> int Compare(const char *cStr) const;
// oder
bool operator == (const CKString &sKStr) const;
//> bool operator == (const string &sStr) const;
//> bool operator == (const char *cStr) const;
// ...
};
Ist es sinnvoll die zusätzlichen Funktionen (string, char) zu definieren, oder nicht?
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 30.07.2010, 11:00
von Aramis
Ja und Nein. Notwendig sind sie nicht! Fuer's Protokoll, die genaue Vorgehensweise des Compilers beim Aufruf einer Funktion ('overload resolution'):
Der Compiler ermittelt beim Aufruf einer Funktion (also auch eines Operators) erstmal alle moeglichen Kandidaten (d.h. alle gleich benannten Funktionen im aktuellen Namensraum sowie den via ADL erreichbaren). Danach versucht er, fuer jede dieser Funktionen moegliche Konversionen fuer die Parameter zu finden: er geht alle Parameter von links nach rechts durch und ermittelt eine Art "Rang", der angibt wie muehsam die Konversion ist. Danach nimmt er die Funktion mit dem niedrigsten Rang - gibt es davon 2 oder mehr, ist der Aufruf mehrdeutig. Auf die gefundene Funktion wendet er dann Zugriffskontrolle an, sie muss erreichbar sein.
Jetzt auf deinen Fall bezogen:
Falls er existiert wird hier der genau passende
bool CKString :: operator == (const char *cStr) const; aufgerufen (Rang 0, keine Konversion notwendig). Existiert er nicht, so wird
bool CKString :: operator == (const CKString &sKStr) const; aufgerufen, wobei der
const char* implizit nach
CKString konvertiert wird - dies ist moeglich, da der sog. Konversionskonstruktor
CKString(const char *cStr); existiert, erreichbar ist und nicht als
explicit deklariert ist (ein relativ hoher Rang, benutzerdefinierte Konversionen aufzurufen versucht der Compiler zu vermeiden, aber es gibt keine andere Alternative in dem Fall).
Dennoch kann es sinnvoll sein solche, eigentlich unnoetigen Operatoren zu implementieren: ich nehme an dein
CKString erstellt eine Kopie des Strings in einem neuen Speicherbereich, der via
malloc,new,… alloziert wird. Dementsprechend würde im obigen Beispiel - wenn der
CKString == const char*-Operator nicht definiert ist voellig umsonst eine temporaerer
CKString erstellt.
Durch die 'Spezialisierung' der bereits fuer die meisten Faelle implementierten Vergleichsfunktion fuer diese Spezialfaelle erreichst du also deutlich hoehere Performance. Bei einer String-Klasse haette ich daher dazu tendiert diese Operatoren tatsaechlich zu implementieren.
Was mich aergert ist aber folgendes: 2 Leute (Schrompf und Ich) haben dir in zusammen mindestens 4 Postings geschrieben, dass Operatoren wie
operator== ausserhalb der Klasse gehoeren, weil sonst keine implizite Konversion fuer den ersten Parameter stattfinden kann (
bool CKString :: operator == (const CKString &sKStr) const sieht der Compiler ja intern als
bool operator == (const CKString* const this, const CKString &sKStr), d.h. der
this-Pointer ist einfach der implizite erste Parameter. Fuer diesen wird aber *keine* implizite Konversion durchgefuehrt. Mit deiner String-Klasse wuerde also
CKString s ;"hi!" == s in Wahrheit wieder den
CKString-Konversionskonstruktor auf "hi" aufrufen anstelle die optimierte Variante fuer
const char* == CKString - und das, ohne dass du es bemerken wuerdest).
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 30.07.2010, 11:27
von HeinzK
Was mich aergert ..
Tschuldigung, aber ich verstehe jetzt erst die Zusammenhänge .. der Worte hab' ich wohl vernommen, aber der Sinn ist nicht vorbeigekommen ..
Ich habe bisher noch nie mit Operatoren gearbeitet. Zwar habe ich eine Menge darüber gelesen, aber man muss
damit arbeiten (testen, spielen), um die ganze Wahrheit zu erkennen. Vielen Dank für die ausführliche Info (s.o.)!
Re: Auf dem Weg von DDraw nach OpenGL ..
Verfasst: 02.08.2010, 20:47
von HeinzK
:D .. Mädels und Jungs .. :D .. Hurra .. :D
====================================
Ich habe gerade das 1. ZwiAner-Level unter SDL-Grafik (Fullsreen) gespielt! Läuft super .. später mehr .. (02.08.2010 20:44) ..
PS:
Weiteres Hurra .. gerade das 1. ZwiAner-Level unter OpenGL (800/600) gespielt (02.08.2010 21:11).
Es ist 21:48 02.08.2010, auch das 'alte', bewährte DDraw (Fullscreen) läuft im neuen Gewand .. puuhhh!