Frage

Ich habe einen guten damit zu kämpfen, während jetzt. Ich versuche, die Bildschirmkoordinaten des Scheitels in einem Modell auf dem Bildschirm meines NDS mit devkitPro zu bestimmen. Die Bibliothek scheint einige Funktionen von OpenGL, aber insbesondere die gluProject Funktion fehlt, zu implementieren, die würde (ich nehme an) erlauben Sie mir nur genau das zu tun, leicht.

Ich habe eine gute versucht, während jetzt die Bildschirmkoordinaten manuell die Projektion Matrizes mit zu berechnen, die in der DS-Registern gespeichert sind, aber ich habe nicht mit viel Glück gewesen, auch wenn man versucht, die Projektionsmatrix zu bauen aus kratzen basierend auf OpenGL-Dokumentation. Hier ist der Code, ich versuche zu verwenden:

void get2DPoint(v16 x, v16 y, v16 z, float &result_x, float &result_y)
{
 //Wait for the graphics engine to be ready
 /*while (*(int*)(0x04000600) & BIT(27))
  continue;*/

 //Read in the matrix that we're currently transforming with
 double currentMatrix[4][4]; int i; 
 for (i = 0; i < 16; i++)
  currentMatrix[0][i] = 
  (double(((int*)0x04000640)[i]))/(double(1<<12));

 //Now this hurts-- take that matrix, and multiply it by the projection matrix, so we obtain
 //proper screen coordinates.
 double f = 1.0 / tan(70.0/2.0);
 double aspect = 256.0/192.0;
 double zNear = 0.1;
 double zFar = 40.0;
 double projectionMatrix[4][4] = 
 {
  { (f/aspect), 0.0, 0.0, 0.0 },
  { 0.0, f, 0.0, 0.0 },
  { 0.0, 0.0, ((zFar + zNear) / (zNear - zFar)), ((2*zFar*zNear)/(zNear - zFar)) },
  { 0.0, 0.0, -1.0, 0.0 },
 };

 double finalMatrix[4][4];
 //Ugh...
 int mx = 0; int my = 0;
 for (my = 0; my < 4; my++)
  for (mx = 0; mx < 4; mx++)
   finalMatrix[mx][my] = 
   currentMatrix[my][0] * projectionMatrix[0][mx] + 
   currentMatrix[my][1] * projectionMatrix[1][mx] + 
   currentMatrix[my][2] * projectionMatrix[2][mx] + 
   currentMatrix[my][3] * projectionMatrix[3][mx] ;

 double dx = ((double)x) / (double(1<<12));
 double dy = ((double)y) / (double(1<<12));
 double dz = ((double)z) / (double(1<<12));

 result_x = dx*finalMatrix[0][0] +  dy*finalMatrix[0][1] + dz*finalMatrix[0][2] + finalMatrix[0][3];
 result_y = dx*finalMatrix[1][0] +  dy*finalMatrix[1][1] + dz*finalMatrix[1][2] + finalMatrix[1][3];

 result_x = ((result_x*1.0) + 4.0)*32.0;
 result_y = ((result_y*1.0) + 4.0)*32.0;


 printf("Result: %f, %f\n", result_x, result_y);

} 

Es gibt viele Verschiebungen beteiligt ist, arbeitet die DS intern über Punkt-Notation festgelegt und ich brauche zu konvertieren, dass mit zu verdoppelt Arbeit. Was ich immer scheint etwas zu sein correct-- die Pixel perfekt übersetzt werden, wenn ich eine flache Quad bin mit, dass der Bildschirm konfrontiert ist, aber die Rotation ist wackelig. Auch, weil ich von der Projektionsmatrix werde (die für die Bildschirmbreite / Höhe Konten?) Die letzten Schritte, die ich zu verwenden bin, um zu tun scheint nicht richtig überhaupt. Sollte nicht die Projektionsmatrix den Schritt bis zu Bildschirmauflösung für mich werden, erreichen?

Ich bin ziemlich neu, um all dies, ich habe auf Matrix math einen fairen Griff bekomme, aber ich bin nicht so geschickt wie ich in 3D-Grafik sein möchte. Hat jemand hier eine Art und Weise kennen, da die 3D, nicht transformierten Koordinaten eines Modells Scheitel und auch die Matrizes gegeben, die auf sie angewandt werden, um tatsächlich mit den Bildschirmkoordinaten zu kommen, ohne Funktion gluProject OpenGL zu verwenden? Können Sie etwas offensichtlich, dass ich fehlte in meinem Code sehen? (Ich werde klären, wenn möglich, ich kann es raue weiß, ist dies ein Prototyp arbeite ich an, Sauberkeit ist keine hohe Priorität)

Dank einem Haufen!

PS: Wie ich es verstehe, currentMatrix, die ich aus dem DS-Registern ziehen, sollte werden gibt mir die kombinierte Projektion, Translation und Rotation Matrix, wie es die genaue Matrix sein soll, die los ist durch eigene Hardware des DS, zumindest nach den Angaben bei GBATEK wird für die Übersetzung verwendet. In der Praxis scheint es nicht eigentlich die Projektionskoordinaten auf sie angewendet haben, was ich etwas mit meinen Fragen zu tun hat annehmen. Aber ich bin mir nicht sicher, wie die Projektion der Berechnung selbst nicht ist, unterschiedliche Ergebnisse erzeugen.

War es hilfreich?

Lösung

Das ist fast richtig.

Die richtigen Schritte sind:

  • Multiplizieren mit Modelview Projection Matrix (wie Sie bereits getan haben).

  • Verlängern 3D Scheitels zu einer homogenen Koordinate durch eine W-Komponente mit dem Wert 1. Eg Zugabe Ihrer (x, y, z) -Vektor wird (x, y, z, w) mit w = 1.

  • Multiplizieren Sie diesen Vektor mit dem Matrixprodukt. Ihre Matrix sollte 4x4 und Ihren Vektor der Größe seine 4. Das Ergebnis wird ein Vektor von size4 sein als auch (nicht fällt w noch!). Das Ergebnis dieser Multiplikation ist Ihr Vektor in Clip-Raum. Zu Ihrer Information: Sie können schon ein paar sehr nützliche Dinge hier mit diesem Vektor tun: Test, ob der Punkt auf dem Bildschirm ist. Die sechs Bedingungen sind:

    x < -w : Point is outside the screen (left of the viewport)
    x >  W : Point is outside the screen (right of the viewport)
    y < -w : Point is outside the screen (above the viewport)
    y >  w : Point is outside the screen (below the viewport)
    z < -w : Point is outside the screen (beyond znear)
    z >  w : Point is outside the screen (beyond zfar)
  • Projekt Ihres Punkt in 2D-Raum. Um dies zu tun divide x und y durch w:
  x' = x / w;
  y' = y / w;
  • Wenn Sie sich in der Tiefe-Wert interessiert (zum Beispiel, was mit dem Z-Buffer geschrieben wird) kann man z projizieren auch:
 z' = z / w
  • Beachten Sie, dass der vorherige Schritt nicht funktioniert, wenn w gleich Null ist. Dieser Fall happends wenn Ihr Punkt auf die Kameraposition gleich ist. Das Beste, was Sie in diesem Fall tun können, ist zu Satz x ‚und y‘ zu Null. (Den Punkt in der Mitte des Bildschirms im nächsten Schritt bewegen ..).

  • Letzter Schritt: Holen Sie sich das OpenGL Darstellungskoordinaten und wenden Sie es:

  x_screen = viewport_left + (x' + 1) * viewport_width  * 0.5;
  y_screen = viewport_top  + (y' + 1) * viewport_height * 0.5;
  • Wichtig: Die y des Bildschirms koordinieren kann dem Kopf stehen. Im Gegensatz zu den meisten anderen grafischen APIs in OpenGL y = 0 die Unterseite des Bildschirms.

Das ist alles.

Andere Tipps

werde ich noch ein paar Gedanken zu Nils' gründlichen Antwort hinzuzufügen.

  1. nicht verdoppelt verwenden. Ich bin mit NDS nicht vertraut, aber ich bezweifle es hat keine Hardware für Doppel math.
  2. Ich bezweifle auch Modellansicht und Projektion nicht bereits multipliziert, wenn Sie die Hardware-Register lesen. Ich habe noch eine Hardwareplattform, um zu sehen, dass die volle MVP nicht direkt in den Registern verwendet werden.
  3. die Matrix Speicher in Register können oder nicht in der gleichen Reihenfolge wie OpenGL sein. wenn sie die Multiplikation Matrix-Vektor-Anforderungen nicht, ist in der anderen Reihenfolge durchgeführt werden.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top