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

31

25.12.2006, 22:51

Ich bin doch schon gleich am Ende!
Bitte nur den letzten schritt!
Bitte!
Gruß Flo

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

32

25.12.2006, 22:56

Ja, aber was bringt dir das?
Du willst doch sicher mehr als nur das.

33

25.12.2006, 23:09

Zitat von »"F-Wölkchen"«

Also ich dachte was bei hoehe rauskommt wäre eine Zahl zwischen 0 bis unendlich.
Also das die höhe vom Terrain 0 ist und die kamera x (also variable hoehe).
Deswegen dachte ich mir das die Kamera 6 einheiten über dem Terrain schweben soll.
Doch ich kann es selber nicht herleiten weil ich diese ganze Rechnung nicht verstehe (8. Klasse). :?

Also alleine komm ich da leider nicht weiter. sry.

Gruß Flo


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
// den Wert 6 finde ich etwas groß

if(interpolierterBodenwert.y + 6.0f <= Kamera.y)
{
    // Keine Kollision

}
else
{
    // Kollision bzw. du befindest dich darunter

}


@F-Wölkchen

Warum hast du eigentlich alle Werte berechnet?
Es reicht doch einfach die 4 umliegenden Punkte (also um die Kamera herum) der Heightmap zu nehmen und dann den Mittelwert zu bestimmen.

Im simpelsten Fall bestimmst du wirklich nur die 4 Punkte und rechnest dann.

C-/C++-Quelltext

1
float interpolierterWertY = (Punkt0.y + Punkt1.y + Punkt2.y + Punkt3.y) / 4.0f;


Das ist zwar nicht das Beste was du machen kannst aber zumindest bekommst du schonmal ein Ergebnis. Du solltest jetzt aber bedenken das wirklich der Mittelpunt berechnet wurd was die Sache sehr ungenau macht wenn du am Rand stehst. Da hilft wirklich nur interpolieren wie es hier bereits beschrieben wurde.

Aber probier es mal mit meiner simplen Lösung hier und wenn das soweit funktioniert tauschst du einfach schnell die simple Rechnung durch die etwas kompliziertere Interpolation.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

34

25.12.2006, 23:38

Zitat von »"chriss"«

Im simpelsten Fall bestimmst du wirklich nur die 4 Punkte und rechnest dann.

C-/C++-Quelltext

1
float interpolierterWertY = (Punkt0.y + Punkt1.y + Punkt2.y + Punkt3.y) / 4.0f;

Das ist Quatsch. Dann kannst du genausogut die Kamerakoordinaten runden und den nächsten Gitterpunkt unverändert nehmen. Deine Methode erhöht nicht die Genauigkeit der Höheninformation. Es wird genauso viele Sprünge in der Höhe geben wie wenn du einfach die Koordinaten rundest und an der entsprechenden Stelle in der Height-Map schaust.

35

26.12.2006, 01:37

Stimmt genau David. Aber so hat er schonmal eine Rechnung drinn die er gegen eine Sinnvolle austauschen kann wenn das soweit funktioniert. Soweit ich das Problem verstanden habe geht es ja nicht um ungenauigkeit sondern darum das es gar nicht geht.

36

26.12.2006, 12:58

Genau!

Du hast völlig recht.
Es geht mir erstmal nicht darum wie genau das ist!
Es soll einfach nur "Ansatzweise" wenigstens klappen.

Jetzt zu der "einfachen" Rechnung:


Zitat

float interpolierterWertY = (Punkt0.y + Punkt1.y + Punkt2.y + Punkt3.y) / 4.0f;


Hier jetzt mal mein Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
hoehe = (A.y+B.y+C.y+D.y)/4; 
          
            
           
            if(Cam.mPos.x > A.x && Cam.mPos.x < D.x && Cam.mPos.z > A.z && Cam.mPos.z < B.z){   
            Cam.mPos.y = hoehe+2;          
            }


Klappen tut das leider nicht.
Ich wollte einfach die höhe des Terrains Quadrates berachnen und diese einfach als höhe für die Kamera angeben + 2 (über der Oberfläche).
Natürlich wollte ich dann vorher prüfen ob sich die Kamera in diesem Quadrat befindet.

Doch was ist da falsch?

Gruß Flo

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

37

26.12.2006, 13:45

was klappt nicht bzw. woran scheitert es?

38

26.12.2006, 14:14

@F-Wölkchen

Ich versteh den Sinn deiner Abfrage nicht so ganz.

Als erstes musst du die 4 umliegenden Punkt bestimmen. Das könntest du machen indem du (sehr unperfomant) alle Punkte der Heightmap abfragst und den Abstand zur Kamera berechnest. Die 4 Punkte mit dem geringsten Abstand zur Kamera nimmst du dann.

Als nächstes berechnest du die Durchschnittshöhe.

Als letztes prüfst du ob die Durchschnittshöhe geringer der Kamera ist (keine Kollision).




Sollte das dann mal funktionieren würde es sich anbieten einen Blick auf die Interpolationsfunktion zu werfen die bereits gepostet wurde. Geht das dann auch kannst du deine Heightmap einteilen (z.B. BSP Tree oder ähnliches) um die Anzahl an Tests zu minimieren.

Viel Erfolg und als wichtigsten Tipp:
Mal dir mal auf ein Blatt Papier auf was du machen willst ;)

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

39

27.12.2006, 10:27

Ich glaube, hier liegt mal wieder ein Verständnisproblem vor.

Zuerst ist zu beachten, dass man verschiedene Koordinatensysteme hat. Das erste ist das Koordinatensystem in der HeightMap, das einfach das 2D Koordinatensystem von ganzen Zahlen des Bildes ist. Weil das dicht an einer Textur ist, nenne ich die Punkte dort einfach mal (u, v). An jeder solchen Koordinate ist eine Höheninformation w = h(u, v) gespeichert. Soweit war das sicher jedem klar.

Dann gibt es noch das 3D Weltkoordinatensystem, in dem sich die Kamera und die gezeichneten Dreiecke für das Terrain befinden. Die Kamera befindet sich an den Koordintaten (cx, cy, cz). Das sind alles reelle Zahlen, die wir z.B. als float abbilden.

Zu jedem Pärchen [(u, v), w] (das habe ich mit Absicht so geschrieben!) gibt es ebenfalls eine eindeutige Weltkoordinate (X(u), Y(v), Z(w))

Die Funktionen X und Y definieren, wie die 2D Punkte der HeightMap als Gitter in den 3D-Raum abgebildet werden und sind meistens einfache Skalierungen (X(u) = g * u), also einfach umzukehren. Im einfachsten Fall nimmt man g = 1.0, dann kann man u und v direkt als x und y übernehmen (umgekehrt nicht, weil die Nachkommastellen einen Strich durch die Rechnung machen; später mehr dazu). Die Umkehrfunktionen nenne ich U(x) = x / g und V. Wichtig dabei ist, das U und V immernoch eine reele Zahl als Ergebnis haben.

Die Funktion Z sieht generell genauso aus, kann aber auch komplizierter sein (das ist für diesen Fall nicht so wichtig).

Die eigentliche Aufgabe, so wie das Problem in den letzten paar Posts beschrieben wurde, ist nun folgende:

Finde zu cx und cy die vier Punkte (cu_1, cv_1), ..., (cu_4, cv_4), die Nachbarn von (cu, cv) = (U(cx), V(cy)) sind. Das ist die Prüf-Facette innerhalb der HeightMap. Dazu suche den nächstkleineren Ganzzahlwert von cu und cv (::floor), was den "linken oberen" Nachbarn (cu_1, cv_1) ergibt (den Nachkommateil ncu = cu - ::floor (cu) und ncv merkt man sich). Für die rechten Nachbarn ist die u-Koordinate um 1 höher und für die unteren ist die v-Koordinate um 1 höher.

Wenn man bei der Rechnung im negativen Bereich landet, oder Punkte erhält, die gar nicht mehr in der HeightMap liegen können, befindet sich die Kamera auch nicht mehr über der HeightMap und man kann auch nichts ausrechnen.

Damit kann man nun bestimmen, ob die Kamera "oberhalb" der Facette ist, indem man cz mit dem Höhenwert h(cu, cv) innerhalb der Facette vergleicht. Der ist nicht direkt definiert, weil cu und cv keine ganzen Zahlen sind, darum muss man den interpolieren (oder anders abschätzen).

Ein paar einfache Abschätzungen sind das Maximum, das Minimum der Höhenwerte der Nachbarn oder eben der Durchschnitt der vier Höhen. Für einfache Anwendungen, oder eine HeightMap, die hoch genug auflöst, ist das sicher nicht falsch.

Man kann aber auch den Wert aus den Höhen der Nachbarn bilinear interpolieren. Dazu braucht man die beiden Nachkommaanteile ncu und ncv.

Quellcode

1
2
3
4
  h (cu, cv) = (1.0 - ncu) * (1.0 - ncv) * lo +
               ncu * (1.0 - ncv) * ro +
               (1.0 - ncu) * ncv * lu +
               ncu * ncv * ru;

[l, r][o, u] steht für links / rechts oben / unten. (Das ist hier wirklich wichtig; wenn man die Reihenfolge durcheinanderbringt, liefert die Berechnung falsche Ergebnisse!)

Wie man leicht sieht, ist der Durchschnittswert der Höhen ein Spezialfall der bilinearen Interpolation, nämlich für ncu = ncv = 0.5. Technisch betrachtet kann man mit bilinearer Interpolation auch nur dann die exakte Höhe berechnen, wenn man die Facette entsprechend trianguliert. Dazu müsste man pro Facette einen "Fan" um den Durchschnittspunkt der Facette in Weltkoordinaten legen.

Normalerweise teilt man die Facetten aber nur in zwei Dreiecke auf, so dass bilineare Interpolation auch wieder nur eine Abschätzung (wenn auch eine bessere) ist. Will man das auch noch abbilden, bleibt das Prinzip aber das gleiche. Finde heraus, über welchem Dreieck der Facette man sich befindet, bestimmt aus cx und cy ein tu und tv, das die relative Position im Dreieck bestimmt, berechne damit den Höhenwert aus den drei Eckpunkten, und man ist fertig. Die Berechnung von tu und tv lasse ich mal als Übung für euch. (a.k.a. ich bin zu faul, das eben selbst herzuleiten :))

Gruss,
Rainer
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

Werbeanzeige