PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL und Bewegung im Raum!


Ganon
2003-10-02, 16:40:06
Hi,

ich habe hier einen Raum. Mit der Maus kann ich mich frei im Raum drehen. In alle Richtungen. Mit W/S/A/D kann ich mich auf den Achsen entsprechend "bewegen".

Nur da ist das Problem. Momentan verschiebe ich alles auf der X/Y/Z-Achse. D.h. gucke ich nach rechts und drücke "W", dann bewegt er sich logischer Weise nach links. Wie mache ich das denn nun das er in die Blickrichtung läuft?

Ich poste mal die wichtigen Code-Teile (Sprache C++/OpenGL/GLUT und als System ein Mac):

Mausbewegung:

void mouse(int button, int state, int x, int y)
{
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
mousemotion = 1;
mousex = x;
mousey = y;
};

if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
mousemotion = 0;
};
}
//Callback Funktion: Reaktion auf Mausbewegung
void motion(int x, int y)
{
if (mousemotion)
{
xangle = xangle - (y - mousey);
yangle = yangle - (x - mousex);
mousex = x;
mousey = y;
};
}




Modell-Positionen neu berechnen:


glViewport( 0, 0, width, height );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat wh = width/height;
gluPerspective(60.0f,wh,1.0f,30000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
glTranslatef(posxO, posyO, poszO);



Tastaturabfrage:

case 'd':
posxO += 0.25f;
break;

case 'a':
posxO -= 0.25f;
break;

case 'f':
posyO += 0.25f;
break;

case 'r':
posyO -= 0.25f;
break;

case 'w':
poszO += 0.25f;
break;

case 's':
poszO -= 0.25f;
break;



Ist es nun möglich das Programm so zu ändern, das er da macht was ich gerne hätte, oder müsste da komplett etwas geändert werden?

Danke!

che g
2003-10-02, 17:23:11
Möglich ist alles. :)

Am Anfang "siehst" du genau an der Z-Achse entlang, d.h. bei "w" u. "s" musst du nur die Z-Position ensprechend ändern. Soweit so gut. Stell dir nun vor du drehst dich um 45° nach rechts und drückst "w". Dann musst du nicht mehr nur auf der Z-Achse die Position ändern sondern auch auf der X-Achse (du bewegst dich ja "schräg" nach rechts)
Die Position ändert sich weiters nicht um irgendeinen Wert, sondern auf der Z-Achse genau um cos(yangle) und auf der X-Achse um sin(yangle). Falls du das nicht verstehst solltest du dich zuerst etwas mit Trignometrie beschäftigen.

Noch lustiger wird das ganze wenn du auch den xangle änderst, also schräg nach oben oder unten siehst. Dann ändert sich auch noch die Y-Position (um sin(xangle)) und bei der X und Z Position müssen entsprechende Korrekturen vorgenommen werden.

Eine andere Möglichkeit ist eine Kamera, bei der die Blickrichtung nicht durch 2 Winkel sondern durch einen Richtungsvektor angegeben wird. Dann brauchst du bei "w" und "s" nur am Richtungsvektor entlangzufahren, und bei "a" und "d" am Kreuzprodukt von Richtungsvektor und z.b. (0,1,0)

mfG

Abe Ghiran
2003-10-02, 17:32:13
Hi...
Du musst nur bei der Tastaturabfrage und dem ändern von posx / posz den aktuellen Winkel für die Rotation um die y Achse (yangle in deinem code) berücksichtigen, z.B. so:


// strafe right
case 'd':
posxO += cos(yangle)*0.25f;
poszO += sin(yangle)*0.25f;
break;

// strafe left
case 'a':
posxO += (-cos(yangle))*0.25f;
poszO += (-sin(yangle))*0.25f;
break;

// forward
case 'w':
posxO += (-sin(yangle))*0.25f;
poszO += (-cos(yangle))*0.25f
break;

// backwards
case 's':
posxO += sin(yangle)*0.25f;
posyO += cos(yangle)*0.25f;
break;


Mit diesem code würdest du bei yangle = 0° in Richtung der negativen z Achse gucken, wenn yangle größer wird, drehst du dich nach links, wenn es kleiner wird nach rechts.
Wenn du das anders haben willst, musst du entsprechend die Vorzeichen oder die trigonometrischen Funktionen tauschen.

Grüße, Jan

Edit: che g war schneller dafür habe ich Beispielcode ;D

Gnafoo
2003-10-02, 17:45:03
meine Empfehlung:
http://nehe.gamedev.net/data/articles/article.asp?article=08

cu DerTod

Ganon
2003-10-02, 22:34:44
Hi,

danke schon mal! Ich werde es nachher gleich mal ausprobieren!

@Der Tod

Ich kenne die Tuts von NeHe. Ich habe die auch in meinen Lesezeichen! Nur leider ist deren Code immer aufbauend auf dem davorigen. Deswegen sind dort auch noch Texturteile usw. drinnen, die dann einfach nur stören.

Trotzdem Danke!

Ganon
2003-10-03, 17:18:26
Hi,

ich habe das jetzt mal ausprobiert. Er springt wild im Raum rum wenn ich die Mausbewege, während ich eine Taste drücke.

Gast
2003-10-03, 17:26:41
Wie wärs mit ner kleinen Debugausgabe, die anzeigt was du da berechnest bei welchen Tasten?
Damit findest du den Fehler wahrscheins sehr schnell....

Ganon
2003-10-03, 19:25:45
Hi!

OK! Mache ich später!

Ich hätte da noch ein anderes Problem. Und zwar, wenn ich ein Objekt texturiere und dann mit glEnable(GL_TEXTURE_2D) die Texturen anschalte, dann wird ein anderes Objekt, welches noch über glColor gefärbt ist, nicht oder kaum noch beleuchtet. Es ist dann fast schwarz.
Wenn ich jedoch ein fertiges Objekt von glut einfüge, dann wird das Korrekt dargestellt!

Woran könnte es liegen, dass das Objekt so dunkel wird?

zeckensack
2003-10-03, 21:09:30
Original geschrieben von Ganon
Hi!

OK! Mache ich später!

Ich hätte da noch ein anderes Problem. Und zwar, wenn ich ein Objekt texturiere und dann mit glEnable(GL_TEXTURE_2D) die Texturen anschalte, dann wird ein anderes Objekt, welches noch über glColor gefärbt ist, nicht oder kaum noch beleuchtet. Es ist dann fast schwarz.
Wenn ich jedoch ein fertiges Objekt von glut einfüge, dann wird das Korrekt dargestellt!

Woran könnte es liegen, dass das Objekt so dunkel wird? Weil die Textur noch aktiv ist :)
Du übergibst zwar keine Texturkoordinaten, aber GL 'merkt' sich die letzten aktuellen, und wendet sie auf alle weiteren Vertices an.
Du mußt einfach zwischendurch die Texturen abschalten, und dann wieder einschalten, dann geht's.

che g
2003-10-03, 21:45:47
Original geschrieben von zeckensack
Weil die Textur noch aktiv ist :)
Du übergibst zwar keine Texturkoordinaten, aber GL 'merkt' sich die letzten aktuellen, und wendet sie auf alle weiteren Vertices an.
Du mußt einfach zwischendurch die Texturen abschalten, und dann wieder einschalten, dann geht's.

Oder passende Vertexnormalen generieren. Bei glut werden die praktischwerweise mitgeliefert, darum gibts da keine Probleme. Aber bei selbstegebauten Objekten ist man auch für die Normalen selbst verantwortlich.

mfG

Ganon
2003-10-03, 22:51:30
Ahh, danke!

Gut zu wissen. Läuft jetzt!

Ganon
2003-11-12, 17:56:22
Hi,

habe jetzt endlich mal wieder Zeit gefunden. Naja! Ich habe mal meinen Kollegen gefragt. Er ist Mathematiker und hatte auch schnell ein Ergebiss.

Nur leider scheinen sich sein Ergebnis und OpenGL nicht so richtig zu verstehen. *ggg*

Er gab mir für Vorwärts (also 'w') folgende Formeln):

x = sin(yangle) * cos(xangle)
y = sin(xangle) * cos(yangle)
z = cos(yangle) * cos(xangle)

Naja! OK! Nun habe ich mal versucht es einzusetzen:


case 'w':
posxO -= (sin(yangle*bog) * cos(xangle*bog))*0.25f;
posyO += (sin(xangle*bog) * cos(yangle*bog))*0.25f;
poszO += (cos(yangle*bog) * cos(xangle*bog))*0.25f;
break;


"*bog" ist die Umrechnung ins Bogenmaß, welches in einem anderen Thread mal vor kam.

Das da oben funktioniert auch fast. Nur bei einigen Werten xangle und yangle Werten macht er Müll. Dann geht er nämlich entweder genau Spiegelverkehrt und bleibt ganz stehen und rührt sich nicht (bei xangle=90 und yangle=90 bleibt er z.B. ganz stehen).

Wisst ihr warum er so etwas macht?

Danke!

ScottManDeath
2003-11-12, 18:39:15
ich tippe mal auf "gimbal lock". ich kanns dir nicht genau erklären, das hat was mit eulerschen winkeln zu tun, am besten mal googlen. die 3 winkel(um die xyz achsen) sind nicht in der lage rotationen im raum eindeutig zu repräsentieren. das geht aber z.b. mit quaternions(rotationsachse + winkel um die achse). diese kann man dann in eine rotationsmatrix oder die 3 winkel umwandeln