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

11.09.2012, 19:08

Objekt auf Kugeloberfläche ausrichten (LWJGL/Java)

Hallo,
ich versuche derzeit einen kleine Weltraumsimulation zu programmieren und hänge schon seit zwei Tagen an einem Problem.
Google und die Forensuche konnten mir dabei leider auch nicht weiter helfen.
Ich möchte von meinem Raumschiff aus Gebäude auf Planeten bauen, die Planeten sind dabei einfach perfekte runde Kugeln.
Den Schnittpunkt zu berechnen, also da wo das Gebäude später stehen soll, ist kein Problem.
Ich hänge jetz draran, dass das Dach des Gebäudes immer vom Mittelpunkt des Planeten weg zeigen soll,
also am Vektor Mittelpunkt/Gebäudeposition ausgerichtet ist.
Diese beiten Punkte habe ich, das müsste doch genügen oder nicht?
Ich habe versucht das Problem mittels Quaternionen zu lösn:

Mit dieser Methode wandle ich die Vektoren in ein Quaternion um:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
public static Quaternion createRotationQuaterion(Vector3f a, Vector3f b){
        a = a.normalise(new Vector3f());
        b = b.normalise(new Vector3f());
        Vector3f d = Vector3f.cross(a,b,new Vector3f()).normalise(new Vector3f()); //normlize hinzugefügt
        float co = Vector3f.dot(Vector3f.add(a, b, new Vector3f()).normalise(new Vector3f()),a);
        float si = (float) Math.sqrt(1.0 - co*co);
        return new Quaternion(d.x*si,d.y*si,d.z*si,co); //vec4(d * si, co);
}


Danach wandel ich das Quaternion in eine Matrix, bzw in einen FloatBuffer um, um es mittels GL11.glMultMatrix(..) darzustellen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public static Matrix4f getRotationMatrix(Quaternion q) {
        Matrix4f ret = new Matrix4f();

        float xx = q.x * q.x;
        float xy = q.x * q.y;
        float xz = q.x * q.z;
        float xw = q.x * q.w;
        float yy = q.y * q.y;
        float yz = q.y * q.z;
        float yw = q.y * q.w;
        float zz = q.z * q.z;
        float zw = q.z * q.w;
        
        ret.m00 = 1 - 2 * (yy + zz);
        ret.m01 = 2 * (xy - zw);
        ret.m02 = 2 * (xz + yw);
        ret.m10 = 2 * (xy + zw);
        ret.m11 = 1 - 2 * (xx + zz);
        ret.m12 = 2 * (yz - xw);
        ret.m20 = 2 * (xz - yw);
        ret.m21 = 2 * (yz + xw);
        ret.m22 = 1 - 2 * (xx + yy);
        ret.m03 = ret.m13 = ret.m23 = ret.m30 = ret.m31 = ret.m32 = 0;
        ret.m33 = 1;

        return ret;
    }


C-/C++-Quelltext

1
2
3
4
5
6
public static FloatBuffer quaternionToFloatBuffer(Quaternion q){
        FloatBuffer fb = BufferUtils.createFloatBuffer(32);
        Rotation.getRotationMatrix(q).store(fb);
        fb.flip();
        return  fb;
}


Wenn ich es dann versucher darzustellen (als erstes Translatieren auf die Schnittpunksposition, dann Rotieren mit glMultMatrix(..)),
bleibt das Ergebnis leider ernüchternd. Das Dach des Gebäudes zeigt irgentwo hin, nur leider nicht dahin wohin es soll.
Ich habe schon einige andere Dinge versucht, nur leider bleibt das Ergebniss immer das selbe, kann mir jemand weiterhelfen, bzw mir sagen, was ich falsch mache?

Mfg,
Mick

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

11.09.2012, 20:13

Du kannst einfach den Vektor der in die Richtung des "Daches" zeigt in die Matrix schreiben.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

11.09.2012, 20:14

Was genau bezweckst du mit der Quaternion? Durch den Punkt allein ist die Ausrichtung deines Hauses noch nicht ausreichend bestimmt, du musst auch noch irgendwie die Rotation um die Achse, die durch den Kugelmittelpunkt geht, festlegen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (11.09.2012, 20:23)


4

12.09.2012, 21:36

Danke für die Schnellen Antworten!

@DeKugelschieber: Kannst du das genauer beschreiben? in welche Felder müssten die Koordinaten des Richtungsvektors eingetragen werden und wie genau? einfach die bestehenden Felder ersetzen?

@dot: Wie meinst du das genau? Ich habe ja zwei Vekoren - hier ist der Code, wie ich die schon geposteten Methoden Aufrufe:

C-/C++-Quelltext

1
2
3
4
5
6
7
      /* An Schnittpunkt verschieben */
            GL11.glTranslatef(intersection.x, intersection.y, intersection.z);  
            
            /* Rotieren */
            GL11.glMultMatrix(quaternionToFloatBuffer(createRotationQuaterion(calcDirection(planet.getPosition(), building.getPosition()), planet.getPosition())));
            
            // Zeichnen


Ich muss mich leider entschuldigen, mit Mathe, Formeln und so weiter, tue ich mich meistens recht schwer^^
Das mit den Quaterionen hat bis jetz gut für meine Kamera funktioniert, deswegn hab ich versuch damit meine Rotation für das Gebäude zu realisieren.

Mfg,
Mick

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

5

13.09.2012, 15:18

Wenn du den Vektor hast der das Gebäude ausrichten soll, also auf der Kugel steht und von ihr wegzeigt erstellst du ein Koordinatensystem anhand diesen. Machst also quasi folgendes:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
vec3 z = gebauedeausrichtungsvektor; // lokale Z-Achse, den hast du ja schon wie du sagst
z.normalize();

vec3 x = vecCross(vec3(0, 1, 0), z); // X Achse errechnen
x.normalize();

vec3 y = vecCross(x, z); // Y Achse errechnen
y.normalize();

mat4 am = mat4(x.x, x.y, x.z, 0, // X Achse eintragen
 y.x, y.y, y.z, 0, // Y Achse eintragen
 z.x, z.y, z.z, 0, // Z Achse eintragen
 0, 0, 0, 1);


Was mat4 und vec3 sind sollte ja klar sein. vecCross() errechnet das Kreuzprodukt aus zwei Vektoren. normalize() normalisiert den Vektor.
Danach kannst du mit dieser Matrix weiterrechnen (rotieren, skalieren, whatever).

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

13.09.2012, 15:24

C-/C++-Quelltext

1
vec3 x = vecCross(vec3(0, 1, 0), z); // X Achse errechnen

Klappt nur nicht, wenn z = (0, 1, 0) ist, denn dann ist das Kreuzprodukt der Nullvektor.

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

7

13.09.2012, 17:38

Zitat

Klappt nur nicht, wenn z = (0, 1, 0) ist, denn dann ist das Kreuzprodukt der Nullvektor.


Ja, muss halt entsprechend an den up Vektor angepasst werden. Ich hab das hier eben aus einem gaaanz altem Projekt kopiert. Aber er wollte ja wissen wie man das in die Matrix einträgt.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

13.09.2012, 17:42

Was genau sind denn deine Vektoren a und b?

9

13.09.2012, 22:38

@dot: a und b sind bei mir Kugelmittelpunkt und die Gebäudeposition.

@DeKugelschieber: Vielen Dank, mit deinem Code funktioniert es tadellos! Ich hatte schon befürchtet, es wird nichts mehr :D

Allgemein möchte ich mich bei allen, die versucht haben zu helfen, bedanken. Danke!

Mfg,
mick

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

10

15.09.2012, 19:58

Zitat

Vielen Dank, mit deinem Code funktioniert es tadellos! Ich hatte schon befürchtet, es wird nichts meh


Kein Problem. Ich bin ja doch zu was nütze :D

Werbeanzeige