Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

03.06.2012, 13:57

Kameraposition berechnen

Hallo Forengemeinde. :)
Mein Anliegen betrifft nicht das Spielprogrammieren direkt sondern eher das modifizieren eines Spiels. Ich hoffe, dass das in Ordnung geht.
Ich möchte einen CamHack für ein Rennspiel basteln (World Racing 2) habe aber momentan ein Brett vorm Kopf was die Mathematik angeht. Erstmal ein wenig Theorie zum Ganzen, damit es vielleicht verständlich wird. ;)

Also das Spiel bietet 6 Kameramodi + einen Versetzungsmodus. Bei diesem wird das Spiel pausiert und man kann die Kamera frei mit der Maus bewegen. Die Kamera "besteht" aus zwei Punkten á 3 Koordinaten: Einmal die Position der Kamera selbst und der Punkt auf den die Kamera ausgerichtet ist. Zusätzlich muss noch der Abstand zwischen diesen beiden Punkten gesetzt werden (lässt sich ja leicht berechnen). Die Koordinaten (X,Y,Z) sind Floats und geben den Abstand zum Mittelpunkt des Szenarios an.

So, dieser Modus bringt schon eine funktionierende Mausnavigation mit, das Spiel kann man auch leicht "entpausieren" indem man zwei Sprünge im Speicher leicht abändert. Jetzt läuft das Spiel weiter, die Kamera folgt aber nicht mehr dem Auto. Nun habe ich drei Optionen für den Hack vorgesehen: Einmal die statische Kamera die sich nur mit der Maus bewegt, dann noch eine, die dem Auto nachschaut. Hierfür ist die Kamera selber "fest", aber der Punkt den sie betrachtet bewegt sich mit dem Auto. Diese beiden funktionieren auch schon ganz klasse.
Für die "nachschauende" Kamera springe ich, nachdem die Kamerapositionen vom Spiel berechnet wurden, in eine von mir ergänzte Prozedur, die die Kamerazielkoordinaten gleichsetzt mit den Autokoordinaten und den Abstand neu berechnet, dann springe ich zurück in den normalen Spielablauf.

Mein Problemkind ist jetzt das, was das Spiel im Normalfall mitliefert: Die Kamera, die sich mit dem Auto mitbewegt. Letztendlich muss ich ja "nur" den Abstand von den beiden Kamerapunkten zum Auto beibehalten. Doch wenn ich von einem einzigen Punkt ausgehe (Position des Autos) und von diesem ausgehend die Abstände für beide Kamerapunkte addiere, so rotiert die Kamera nicht mit dem Auto. Nehme ich den Mittelpunkt von zwei Punkten (z.B. Vorder und Hinterrad) und berechne davon die Abstände kommt es auch zu merkwürdigen Effekten in denen die Kamera sich nicht mit dem Auto mitdreht.

Das kann doch eigentlich nicht schwer sein die festen Abstände zu berechnen, aber irgendwie ist bei mir "da oben" in den letzten beiden Tagen nur Murks entstanden. Könnt ihr mir vielleicht helfen?
Werte die mir bekannt sind und die ich zur Berechnung nutzen kann:
Position des Autos, Position aller vier Räder. Alles Floats, Abstände zum Szenariomittelpunkt mit je 3 Koordinaten.

Ich schätze ich habe irgendwie einfach ein Brett vor dem Kopf. :(

Liebe Grüße,
biophemoc

2

04.06.2012, 10:55

Moin,
ich war zwar auch noch nicht besonders aktiv hier, wie man sieht, aber ich denke, es ist ok, wenn ich dich als Erster im Forum Willkommen heiße ;)

Zu deinem Problem: Wie du schon sagst, die Kamera rotiert nicht mit dem Auto. Das ist auch logisch, denn wieso sollte sie es das tun, wenn du nur verlangst, dass der Abstand zum Auto immer gleich ist. Über den Drehwinkel der Kamera im Verhältnis zum Auto ist da noch nichts gesagt.
Probier mal, dass die Abstände zwischen jeweils den beiden Kamerapunkten und allen vier Rädern immer gleich sind. Dann kannst du sicher sein, dass die Kamera relativ zum Auto gesehen wirklich immer starr an der gleichen Position ist.
Wenn das immer noch nicht reicht, dann liegt das daran, dass die Kamera relativ zum Auto zwar immer in die gleiche Richtung schaut, aber sich um die Guck-Achse dreht. Ich hab noch nie in 3D programmiert, aber eigentlich hat man doch immer einen Kamerapunkt und 4 Strahlen, die von dort ausgehen und gewissenmaßen das "Sichtfenster" beschreiben? Wenn du noch weiter Probleme hast, musst du deine "merkwürdigen Effekte" bzw. dein Programm noch etwas genauer beschreiben.

Sp3iky

Treue Seele

Beiträge: 232

Beruf: Entwicklungsingenieur

  • Private Nachricht senden

3

04.06.2012, 18:46

Was du benötigst ist der Richtungsvektor des Fahrzeugs. Solltest du den nicht direkt bekommen, lässt der sich sicher auch aus den Positionen der Vorderräder berechnen, da er ja orthogonal zum Vektor zwischen den Punkten ist.

Dann kannst du einfach vom Auto aus den neuen Kamerapunkt berechnen, indem du den normalisierten Richtungsvektor * den Abstand draufrechnest (bzw. subtrahierst, weil es ja hinter dem Auto sein muss).

Um die Kamera zu drehen könntest du zum Beispiel auch den Richtungsvektor des Autos mit dem der Kamera vergleichen und dir den Winkel der Vektoren berechnen. Das dann in eine Rotationsmatrix auf die alte Kameramatrix draufmultipliziert ergibt die korrekte Richtung der Kamera.

4

05.06.2012, 18:22

Im Mathe GK haben wir Vektorrechnung nur Oberflächlich behandelt. (leider)
Also wenn ich das richtig verstehe berechne ich einen Richtungsvektor aus dem Mittelpunkt zwischen Linkem und Rechtem Vorderrad, sowie dem Mittelpunkt/Position des Autos, diesen Normalisiere ich (Teilen der 3 Koordinaten durch die Länge des Vektors?). Das Ergebnis multipliziere (kreuzprodukt?) ich mit dem Abstand und subtrahiere/addiere das Ganze dann zur Autoposition?
Oder muss ich einen Vektor suchen, der orthogonal zu dem Vektor zwischen den Vorderrädern ist? (wobei das ja dann unendlich viele sind, oder? Außerdem würde das ja auch für den oben von mir genannten, durch die Autoposition, zutreffen. *verwirrt-sei*)
Edit: Die Drehung der Kamera erfolgt ja in dem ich einen weiteren Punkt setze. Muss ich dann wirklich mit einer Rotationsmatrix anfangen, oder kann ich nicht ebenfalls diesen "Zielpunkt" von der Autoposition berechnen wie die Kameraposition? Ich weiß auch von diesem die Abstände zum Auto. Mit Rotationsmatrizen habe ich bisher nämlich noch nicht gearbeitet. :(

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »biophemoc« (08.06.2012, 10:45)


5

12.06.2012, 19:36

Ich hoffe man verzeiht mir meinen Doppelpost nach einer Woche.



Ich habe den von mir oben beschriebenen Weg mal auf dem Papier ausprobiert (bevor ich anfange das in Assembler zu schreiben... ;) ), obwohl mir das Ganze nicht richtig vorkam. Natürlich kommt auch was falsches raus. Ich habe Sp3ikys Antwort wohl nicht richtig verstanden und ich hoffe jemand, der mehr Ahnung hat als ich, kann sich mal den von mir beschriebenen Weg anschauen.


Ich stehe voll auf dem Schlauch, habe mittlerweile so viele Sachen im Netz gelesen die mir alle nicht einleuchten wollen oder mein Problem scheinbar nicht direkt betreffen.



Hoffentlich erbarmt sich mir einer, ich würde mich freuen. :S

RmbRT

Treue Seele

Beiträge: 169

Wohnort: Darmstadt

Beruf: Student

  • Private Nachricht senden

6

12.06.2012, 21:15

So. Endlich eine Antwort :)

So - mal eine Antwort auf die Schnelle - hoffe, du hast noch nicht aufgegeben.
Mitte zwischen Vektor a und b:

C-/C++-Quelltext

1
2
3
4
5
6
vec3 midPoint(vec3 a, vec3 b)
{
    return (a+b)/2;
    //gleichwertig:
    //return vec3((a.x+b.x)/2, (a.y+b.y)/2, (a.z+b.z)/2);
}

Also zum Richtungsvektor:

C-/C++-Quelltext

1
2
3
4
5
6
vec3 direction(vec3 a, vec3 b)
{
    return b-a;
    //gleichwertig
    //return vec3(b.x-a.x, b.y-a.y, b.z-a.z);
}


Ein normalisierter Vektor v ist v / länge (v)
Länge des Vektors:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
float length(vec3 v)
{
    return sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
}
vec3 normalize(vec3 v)
{
    return v / length(v);
    //gleichbedeutend:
    /*
    float len = length(v);
    return vec3(v.x/len, v.y/len, v.z/len);
    */
}


den Richtungsvektor von (Mitte Hinterachse) zu (Mitte Vorderachse) berechnest du so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
vec3 vl, vr, hl, hr;    //v=vorne, h = hinten, l/r = links/rechts

vec3 getDirection(vec3 vl, vec3 vr, vec3 hl, vec3 hr)
{
    vec3 hmitte = midPoint(hl, hr);
    vec3 vmitte = midPoint(vl, vr);

    return direction(hmitte, vmitte);
}


Das Ergebnis multipliziere (kreuzprodukt?) ich mit dem Abstand und subtrahiere/addiere das Ganze dann zur Autoposition?

Nein, nicht ganz - multiplizieren geht so:
Du willst ja nicht den Orthogonalen Vektor zu zwei anderen (Kreuzprodukt), sondern einen vektor strecken (also skalieren).

C-/C++-Quelltext

1
2
3
4
vec3 scale(vec3 v, float factor)
{
    return vec3(v.x*factor, v.y*factor, v.z*factor);
}


So. Ich gehe davon aus, du hast eine Klasse für die Kamera, ich werde eine eigene Benutzen:

C-/C++-Quelltext

1
2
3
4
5
6
class Cam
{
public:
    vec3 position;
    vec3 direction;
};


Hier eine Funktion, hoffe sie erfüllt deinen Zweck:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
void UpdateCamDir(Cam &cam, vec3 vl, vec3 vr, vec3 hl, vec3 hr)
{
    vec3 hmitte = midPoint(hl, hr);
    vec3 vmitte = midPoint(vl, vr);

    vec3 autoMitte = midPoint(hmitte, vmitte);

    cam.direction = getDirection(cam.origin, autoMitte);
}


so könnte das im Programm aussehen (für Feste Kameraposition):

C-/C++-Quelltext

1
2
3
4
5
//...
auto.updatePos(frameTime);
cam.position = calculateNewCamPos(...) ; //deine Funktion für die feste position der kamera.
UpdateCamDir(cam, auto.vl, auto.vr, auto.hl, auto.hr);
//...


und so für relative Kameraposition:

C-/C++-Quelltext

1
2
3
4
5
6
//...
auto.updatePos(frameTime);
//cam.dir bleibt gleich - da die kamera immer in einem bestimmten Winkel zum auto bleibt.
vec3 auto_mitte = midPoint(midPoint(auto.vr, auto.vl), midPoint(auto.hl, auto.hr));
cam.position = auto_mitte + scale(cam.dir, -CAM_DIST);  // -CAM_DIST = Kamera-Abstand zum auto-mittelpunkt.
//...


so...
das war ein ganzer Batzen! ;)
hoffe, du kannst das alles gut nachvollziehen ;)
PS.: Bei Fehlern / Fragen / Unklarheiten, frage mich einfach (brauchst dich für nichts schämen - jeder steht mal auf dem Schlauch ;))
MfG, RmbRT
"Dumm ist, wer dummes tut."

7

13.06.2012, 13:35

Danke erstmal für deine Antwort, ich habe mir alles mal angeschaut, jedoch betrifft es mein Problem nicht direkt (so wie ich das jetzt verstanden habe), was aber an mir liegt und meinen uneindeutigen Formulierungen. Ich versuche das Ganze mal an einem Beispiel zu erklären.

Erste Skizze:
Hier mal ein vereinfachtes Auto, 4x2 LE groß (ja, ich weiß, die quer LE sind länger als die horizontalen und vertikalen, ich hoffe es ist trotzdem verständlich)
Das Auto steht im Mittelpunkt des Szenarios. Die Kamera (grün) liegt bei (3|2|1) also drei LE hinter dem Automittelpunkt, zwei LE rechts davon und eine LE darüber.
Rot ist unser normalisierter Richtungsvektor.

Zweite Skizze:
Jetzt dreht sich das Auto (einfach mal angenommen es würde sich auf der Stelle drehen und sich nicht fortbewegen). Es steht immer noch bei (0|0|0), aber der Richtungsvektor zeigt natürlich in eine andere Richtung. Die Kamera müsste jetzt rein logisch gesehen ja bei (-2|3|1) liegen (wieder drei LE hinter dem Auto Mittelpunkt, zwei rechts davon und eine nach oben)
Aber wie berechne ich das? Für mich ist das einfach logisch und die Mathematik dahinter kann ja auch nicht schwer sein. Muss ja irgendetwas mit dem Richtungsvektor des Fahrzeugs sowie dem Abstand relativ zum Fahrzeug zu tun haben.



Die Zielkoordinate (habe so viel gelesen mittlweile, bei gluLookAt in OpenGL heißt der Punkt center) habe ich erstmal weggelassen um nicht weiter zu verwirren, diese müsste sich ja letztendlich gleich wie die Kamera berechnen lassen nur mit dem anderen Abstand.

RmbRT

Treue Seele

Beiträge: 169

Wohnort: Darmstadt

Beruf: Student

  • Private Nachricht senden

8

13.06.2012, 22:30

Also das müsstest du wahrscheinlich mit Matrizen lösen... ich kenne mich da leider überhaupt nicht aus - Ich bin in der Schule noch nicht so weit angelangt ;).
Oder du guckst mal im Wiki nach "Konzepte für 3D-Spiele (Umsetzung der Steuerung)". Da hab ich ein alternatives konzept beschrieben, in dem man intern nicht mit richtungsvektoren, sondern winkeln arbeitet, und die Richtungsvektoren nur für die übergabe an Funktionen wie gluLookAt(...) berechnet. Der vorteil ist, dass man sie leichter drehen kann :D
MfG, RmbRT
"Dumm ist, wer dummes tut."

Werbeanzeige