OpgenGL & Text ausgeben; Sekundär: Kollisionsabfrage
-
Hallo,
Ich habe gerade heute damit angefangen, mich ein wenig mit den Dingen zu befassen, die nicht ANSI C sind (namentlich OpenGL und windows.h). Daher bitte ich um ein wenig Nachsicht ;).Ich versuche aktuell, in einer mit OpenGL gerenderten Szene ein wenig Schrift auszugeben. Dabei habe ich keinerlei Anspruch an die Optik, sondern will wirklich nur 2-4 chars sichtbar machen.
Hier mal ein gaanz grober Überblick:
#include <windows.h> #include <gl/gl.h> #include <math.h> #include <conio.h> #include <gl/openglut.h> //... char * pointsP1 = malloc(4 * sizeof(char)); //... void RenderFunktion() { //... glRasterPos2f(-0.9 , 0.95); glColor3f(1.0 , 1.0 , 1.0); glutBitmapString(GLUT_BITMAP_HELVETICA_18 , pointsP1); }
Das Programm läuft nun nur, wenn ich die glutBitmapString-Zeile auskommentiere, ansonsten startet es nicht einmal. Eventuell habe ich irgendwas falsch verlinkt, oder es fehlt eine Datei oder glutBitmapString hat irgendeine Rechnung mit mir zu begleichen...
Falls mir jemand sagen kann, wie ich einfach und sicher innerhalb einer OpenGL-Szenerie ein paar chars auf den Bildschirm spucken kann, dann wäre mir damit sehr geholfen.
Und da der Thread schonmal offen ist:
Ich habe auch ein paar Absturzprobleme mit einer Kollisionsabfrage. Ich habe die Vermutung, dass daran die verwendete arctan-Funktion schuld ist, aber sicher bin ich da nicht.
Das Problem sieht in etwa so aus: Ich habe zwei Vektoren, deren Winkel zueinander ich bestimmen will (dabei wird zweimal die atan-Funktion benutzt). Ich denke mal, dass es da noch eine bessere Lösung gibt, falls jemand ein paar Tipps parat hat, wie ich eine schnelle und saubere Kollisionsabfrage realisieren kann, wäre ich auch darüber erfreut.
-
Schau dir mal das NEHE example für Text an.
Zu Kollisionen kann ich dir leider nichts sagen, schau halt mal wo GENAU das Programm abstürzt.
-
Danke, diese NEHE-Tutorials sehen sehr nützlich aus.
Was die Kollision angeht: Das Programm stürzt ab, wenn eine ganz bestimmte Kollision stattfinden soll (es sieht nach 90° aus). Genauer komme ich da leider momentan nicht ran.
-
Mit NEHEs Tutorial habe ich es wirklich geschafft, mein Programm mit Schrift zu versehen. Leider war ich zu faul, um seinen Quelltext Zeile für Zeile zu verstehen, aber die Funktionalität ist erstmal da :). Also erstmal vielen Dank für den Tipp.
Was die Kollisionsabfrage angeht, habe ich jetzt mit einer ganz anderen Methode zumindest die Abstürze beseitigt. Allerdings wird noch nicht richtig "kollidiert".Ich will einfach nur zwei Gegenstände in 2 Dimensionen kollidieren lassen. Mein momentaner Ansatz dafür ist, dass ich das geometische Zentrum der Gegenstände bestimme, von dort aus einen Kreis um das Objekt lege und warte, ob sich die Kreise zweier Objekte irgendwann überlappen. Ist das der Fall, will ich noch ein wenig präziser nachrechnen, da es ja nicht nur Kreise bzw. Kugeln als Gegenstände gibt.
Leider funktioniert aber auch dieser Ansatz nicht zuverlässig (ich habe mich extra eine Weile hingesetzt und die ganzen Formeln aufgestellt :(). Falls jemand Tipps hat, wie ich da ohne abzugucken weiterkomme, immer her damit :).
-
Stiefel2000 schrieb:
Ich will einfach nur zwei Gegenstände in 2 Dimensionen kollidieren lassen. Mein momentaner Ansatz dafür ist, dass ich das geometische Zentrum der Gegenstände bestimme, von dort aus einen Kreis um das Objekt lege und warte, ob sich die Kreise zweier Objekte irgendwann überlappen. Ist das der Fall, will ich noch ein wenig präziser nachrechnen, da es ja nicht nur Kreise bzw. Kugeln als Gegenstände gibt.
Leider funktioniert aber auch dieser Ansatz nicht zuverlässig (ich habe mich extra eine Weile hingesetzt und die ganzen Formeln aufgestellt :(). Falls jemand Tipps hat, wie ich da ohne abzugucken weiterkomme, immer her damit :).Was klappt denn nicht bzw. wie sehen denn deine Formeln aus?
Also der Ansatz mit dem Kreis ist auf jeden fall gut. Da brauchst du ja nur den Pythagoras und die beiden Radien der Kreise (im Grunde kannst du das auch mit den Quadraten der Radien machen damit du nicht die Wurzel ziehen musst was Leistung spart). Klappt da etwas bei dir nicht? Oder bei der Spezialisierung?
-
Lass das doch mal mit attachtem Debugger laufen und schau dir an, welche Bedingung für den Crash sorgt. Da solltest du mehr interessante Informationen erhalten.
Gruß Kimmi
-
Einen Crash habe ich ja seit dem Verwenden des Kreis-Ansatzes nicht mehr.
Der Gedanke, das Wurzelziehen einzusparen, gefällt mir auf jeden Fall sehr gut, das ganze ist nämlich ein wenig zeitkritisch :).
Ich hänge mal den Quelltext meiner Kollisionsabfrage an
double collision_detection(double * O1P1 , double * O1P2 , double * O2P1 , double * O2P2 , unsigned short is_center1 , unsigned short is_center2) { //entweder: zwei extremale Punkte des Objektes (Reihenfolge wichtig, Vektor zeigt stets von P1 nach P2; in diesem Fall jeweilige is_center-Variable gleich Null //oder : erster Vektor ist Objektzentrum, zweiter ist Radiusvektor (nur Betrag wichtig); in diesem Fall jeweilige is_center-Varialbe gleich 1 double * centerO1 = malloc(2 * sizeof(double)); double * centerO2 = malloc(2 * sizeof(double)); double * distanceV = malloc(2 * sizeof(double)); double distance; double radius1 , radius2; double angle; if(!is_center1) { centerO1[0] = 0.5 * (O1P2[0] - O1P1[0]) + O1P1[0]; //Differenz-Vektor zeigt von P1 nach P2; Ergebnisvektor vom Ursprung zum Mittelpunkt des Systems centerO1[1] = 0.5 * (O1P2[1] - O1P1[1]) + O1P1[1]; radius1 = 0.5 * _wurzel((O1P2[0] - O1P1[0]) * (O1P2[0] - O1P1[0]) + (O1P2[1] - O1P1[1]) * (O1P2[1] - O1P1[1])); } else { centerO1[0] = O1P1[0]; //Vektor zeigt vom Ursprung zum Mittelpunkt des Systems centerO1[1] = O1P1[1]; radius1 = _wurzel(O1P2[0] * O1P2[0] + O1P2[1] * O1P2[1]); } if(!is_center2) { centerO2[0] = 0.5 * (O2P2[0] - O2P1[0]) + O2P1[0]; //Differenz-Vektor zeigt von P1 nach P2; Ergebnisvektor vom Ursprung zum Mittelpunkt des Systems centerO2[1] = 0.5 * (O2P2[1] - O2P1[1]) + O2P1[1]; radius1 = 0.5 * _wurzel((O2P2[0] - O2P1[0]) * (O2P2[0] - O2P1[0]) + (O2P2[1] - O2P1[1]) * (O2P2[1] - O2P1[1])); } else { centerO2[0] = O2P1[0]; centerO2[1] = O2P1[1]; radius2 = _wurzel(O2P2[0] * O2P2[0] + O2P2[1] * O2P2[1]); } distanceV[0] = centerO1[0] - centerO2[0]; //Vektor zeigt von O2 nach O1 distanceV[1] = centerO1[1] - centerO2[1]; distance = _wurzel(distanceV[0] * distanceV[0] + distanceV[1] * distanceV[1]); if((distance - radius2) <= radius1) { if(!just_reflected) //globale Variable, die aussagt, ob vor kurzer Zeit bereits eine Kollision beider Objekte stattfand - verhindert doppelte Behandlung bei Grenzfällen { just_reflected = reflection_diff; //reflection_diff ist ein empirisch gewählter int; just_reflected wird bei jedem Kollisionstest um 1 verringert --> zeitlicher Abstand angle = acos((distanceV[0] * (O1P1[0] - O1P2[0]) + distanceV[1] * (O1P1[1] - O1P2[1])) / (distance * _wurzel((O1P1[0] - O1P2[0]) * (O1P1[0] - O1P2[0]) + (O1P1[1] - O1P2[1]) * (O1P1[1] - O1P2[1])))); if(angle > PI / 4.) angle = PI - angle; return(angle); //Vektor zeigt jetzt von P2 nach P1 - evt. besser? } } return(0); }
So, ist ziemlich lang geworden. Der Winkel, der am Ende berechnet wird, entspricht praktisch dem Aufprallwinkel zwischen z.B. einer Wand und einem Objekt. Der wird benötigt, damit die folgende Reflektion richtig berechnet werden kann.
Soweit ich das Programm jetzt testen konnte, wird die Kollision nicht so durchgeführt, wie ich mir das gedacht habe, irgendwo muss also ein (Denk-)Fehler sein.
-
Also bevor ich mir die ganze Mathematik angucke:
in den Zeilen 4 bis 6 reservierst du Speicher - aber wo gibst du ihn wieder frei? Das sind zwar jedes Mal nur 48 Byte, aber irgendwann ist der Speicher dann voll...
Und warum benutzt du malloc? Willst du denn reines C verwenden?
Denn zweitens ist das Ganze ziemlich unübersichtlich. Es wäre besser, eine einfache Klasse namens Vector oder so zu schreiben, die auch gleich die Grundoperationen (addieren, Pythagoras etc) mit beinhaltet. Außerdem bräuchtest du nicht jeden Wert einzeln zu übergeben. Klassen wären dann natürlich C++. Es würde dir auf jeden Fall einiges erleichtern, du hättest eine kürzere bzw. übersichtlichere Methode und könntest auch so den Fehler leichter finden bzw. ihn vielleicht gar nicht erst machen
-
Nein, keine Klassen für mich bitte.
Natürlich könnte ich da ein paar Dinge optimieren, bei einem free() in einer Funktion war ich mir gar nicht sicher, ob es denn nötig ist. Dann werde ich das zufügen - auch wenn es mir kein bisschen weiterhilft ;).