2014-10-06 21 views
10

Ich stoße auf ein Problem, das versucht, das OpenGL-Verhalten in einer Umgebung ohne OpenGL zu replizieren.Doppeltes orthographisches OpenGL-Projektionsverhalten ohne OpenGL

Grundsätzlich muss ich eine SVG-Datei aus einer Liste von Zeilen erstellen, die mein Programm erstellt. Diese Linien werden mit einer othigrafischen Projektion erstellt.

Ich bin sicher, dass diese Zeilen korrekt berechnet werden, denn wenn ich versuche, sie mit einem OpenGL-Kontext mit orthographischer Projektion zu verwenden und das Ergebnis in ein Bild zu speichern, ist das Bild korrekt.

Das Problem entsteht, wenn ich genau die gleichen Zeilen ohne OpenGL verwende.

ich die OpenGL Projektion und Ansicht Matrizen repliziert haben und ich verarbeiten jede Zeile Punkt wie folgt aus:

3D_output_point = projection_matrix * view_matrix * 3D_input_point 

und dann berechne ich es Bildschirm (SVG-Datei) Position wie folgt aus:

2D_point_x = (windowWidth/2) * 3D_point_x + (windowWidth/2) 
2D_point_y = (windowHeight/2) * 3D_point_y + (windowHeight/2) 

I berechnen die othographic Projektionsmatrix wie folgt aus:

float range = 700.0f; 
float l, t, r, b, n, f; 

l = -range; 
r = range; 
b = -range; 
t = range; 
n = -6000; 
f = 8000; 

matProj.SetValore(0, 0, 2.0f/(r - l)); 
matProj.SetValore(0, 1, 0.0f); 
matProj.SetValore(0, 2, 0.0f); 
matProj.SetValore(0, 3, 0.0f); 

matProj.SetValore(1, 0, 0.0f); 
matProj.SetValore(1, 1, 2.0f/(t - b)); 
matProj.SetValore(1, 2, 0.0f); 
matProj.SetValore(1, 3, 0.0f); 

matProj.SetValore(2, 0, 0.0f); 
matProj.SetValore(2, 1, 0.0f); 
matProj.SetValore(2, 2, (-1.0f)/(f - n)); 
matProj.SetValore(2, 3, 0.0f); 

matProj.SetValore(3, 0, -(r + l)/(r - l)); 
matProj.SetValore(3, 1, -(t + b)/(t - b)); 
matProj.SetValore(3, 2, -n/(f - n)); 
matProj.SetValore(3, 3, 1.0f); 

und die vie w-Matrix auf diese Weise:

CVettore position, lookAt, up; 

position.AssegnaCoordinate(rtRay->m_pCam->Vp.x, rtRay->m_pCam->Vp.y, rtRay->m_pCam->Vp.z); 
lookAt.AssegnaCoordinate(rtRay->m_pCam->Lp.x, rtRay->m_pCam->Lp.y, rtRay->m_pCam->Lp.z); 
up.AssegnaCoordinate(rtRay->m_pCam->Up.x, rtRay->m_pCam->Up.y, rtRay->m_pCam->Up.z); 

up[0] = -up[0]; 
up[1] = -up[1]; 
up[2] = -up[2]; 

CVettore zAxis, xAxis, yAxis; 
float length, result1, result2, result3; 

// zAxis = normal(lookAt - position) 
zAxis[0] = lookAt[0] - position[0]; 
zAxis[1] = lookAt[1] - position[1]; 
zAxis[2] = lookAt[2] - position[2]; 
length = sqrt((zAxis[0] * zAxis[0]) + (zAxis[1] * zAxis[1]) + (zAxis[2] * zAxis[2])); 
zAxis[0] = zAxis[0]/length; 
zAxis[1] = zAxis[1]/length; 
zAxis[2] = zAxis[2]/length; 

// xAxis = normal(cross(up, zAxis)) 
xAxis[0] = (up[1] * zAxis[2]) - (up[2] * zAxis[1]); 
xAxis[1] = (up[2] * zAxis[0]) - (up[0] * zAxis[2]); 
xAxis[2] = (up[0] * zAxis[1]) - (up[1] * zAxis[0]); 
length = sqrt((xAxis[0] * xAxis[0]) + (xAxis[1] * xAxis[1]) + (xAxis[2] * xAxis[2])); 
xAxis[0] = xAxis[0]/length; 
xAxis[1] = xAxis[1]/length; 
xAxis[2] = xAxis[2]/length; 

// yAxis = cross(zAxis, xAxis) 
yAxis[0] = (zAxis[1] * xAxis[2]) - (zAxis[2] * xAxis[1]); 
yAxis[1] = (zAxis[2] * xAxis[0]) - (zAxis[0] * xAxis[2]); 
yAxis[2] = (zAxis[0] * xAxis[1]) - (zAxis[1] * xAxis[0]); 

// -dot(xAxis, position) 
result1 = ((xAxis[0] * position[0]) + (xAxis[1] * position[1]) + (xAxis[2] * position[2])) * -1.0f; 

// -dot(yaxis, eye) 
result2 = ((yAxis[0] * position[0]) + (yAxis[1] * position[1]) + (yAxis[2] * position[2])) * -1.0f; 

// -dot(zaxis, eye) 
result3 = ((zAxis[0] * position[0]) + (zAxis[1] * position[1]) + (zAxis[2] * position[2])) * -1.0f; 

// Set the computed values in the view matrix. 
matView.SetValore(0, 0, xAxis[0]); 
matView.SetValore(0, 1, yAxis[0]); 
matView.SetValore(0, 2, zAxis[0]); 
matView.SetValore(0, 3, 0.0f); 

matView.SetValore(1, 0, xAxis[1]); 
matView.SetValore(1, 1, yAxis[1]); 
matView.SetValore(1, 2, zAxis[1]); 
matView.SetValore(1, 3, 0.0f); 

matView.SetValore(2, 0, xAxis[2]); 
matView.SetValore(2, 1, yAxis[2]); 
matView.SetValore(2, 2, zAxis[2]); 
matView.SetValore(2, 3, 0.0f); 

matView.SetValore(3, 0, result1); 
matView.SetValore(3, 1, result2); 
matView.SetValore(3, 2, result3); 
matView.SetValore(3, 3, 1.0f); 

Die Ergebnisse, die ich von OpenGL und von der SVG-Ausgabe erhalten sind ganz anders, aber in zwei Tagen konnte ich nicht mit einer Lösung kommen.

Dies ist die OpenGL-Ausgabe enter image description here

Und das ist meine SVG-Ausgabe enter image description here

Wie Sie sehen, es ist eine Drehung nicht corrent ist.

Irgendeine Idee warum? Die Linienpunkte sind die gleichen und hoffentlich auch die Matrizen.


Die Erstellung der Matrizen, die ich erstellt habe, hat nicht funktioniert. Ich meine, die Matrizen waren falsch, denke ich, weil OpenGL nichts gezeigt hat. Also habe ich versucht, das Gegenteil zu tun, ich habe die Matrizen in OpenGL erstellt und sie mit meinem Code verwendet. Das Ergebnis ist besser, aber noch nicht perfekt.

Jetzt denke ich, dass ich etwas falsch mache, die 3D-Punkte in 2D-Bildschirmpunkte zu kartieren, weil die Punkte, die ich bekomme, in Y invertiert sind und ich immer noch einige Linien nicht perfekt übereinstimmend habe.

Dies ist, was ich die OpenGL-Matrizen und meine bisherigen Ansatz mit 3D-Punkte auf 2D-Platz auf dem Bildschirm abzubilden (dies ist die SVG, OpenGL nicht machen):

enter image description here


Ok das der Inhalt der Ansicht Matrix I aus OpenGL erhalten:

enter image description here

die Projektionsmatrix Dies ist I erhalten von OpenGL:

enter image description here

Und das ist das Ergebnis, das ich mit diesen Matrizen bekommen und meine 2D-Punkt durch Ändern Y Koordinatenberechnung wie bofjas sagte:

enter image description here

Es ist wie einige Umdrehungen sieht fehlen. Meine Kamera hat sowohl auf der X- als auch auf der Y-Achse eine Drehung von 30 °, und es sieht so aus, als wären sie nicht korrekt berechnet.

Jetzt verwende ich die gleichen Matrizen OpenGL tut. Also denke ich, dass ich einige falsche Berechnungen mache, wenn ich den 3D-Punkt in 2D-Bildschirmkoordinaten abbilde.

+1

Nur zur Info: Ihre Methode fehlt die homogene Teilung nach der Projektion Transformation. Es ist für eine orthographische Projektion nicht wichtig, aber wichtig für eine perspektivische Projektion. Was die schlechte Rotation in deinem SVG-Fall anbelangt, muss ich das noch untersuchen. – datenwolf

+0

BTW: Was passiert, wenn Sie die erstellten Matrizen in OpenGL laden und versuchen, das Bild mit diesen zu rendern? 'glMatrixMode (...); glLoadMatrix (...) 'falls Sie die feste Funktionspipeline verwenden. – datenwolf

+0

und BTW könnten Sie den Inhalt der Matrizen drucken. – joojaa

Antwort

1

Anstatt Ihren eigenen Code zu debuggen, können Sie transform feedback verwenden, um die Projektionen Ihrer Zeilen mit der OpenGL-Pipeline zu berechnen. Anstatt sie auf dem Bildschirm zu rasterisieren, können Sie sie in einem Speicherpuffer speichern und anschließend direkt im SVG speichern. Die Einrichtung ist ein wenig kompliziert und hängt von der genauen Einrichtung Ihres OpenGL-Codepath ab, aber es könnte eine einfachere Lösung sein.

Gemäß Ihrem eigenen Code sieht es so aus, als ob Sie irgendwo X- und Y-Koordinaten gemischt haben, oder Zeilen-Haupt- und Spalten-Haupt-Matrizen.

0

Ich habe dieses Problem auf eine wirklich einfache Weise gelöst. Da, wenn ich mit OpenGL zeichne funktioniert es, ich habe gerade die Matrizen in OpenGL erstellt und dann mit glGet() abgerufen. Mit diesen Matrizen ist alles in Ordnung.

+0

Im letzten Abschnitt Ihres Beitrags haben Sie gesagt, dass "ich die gleichen Matrizen verwende OpenGL" und Sie hatten immer noch Probleme. Wie sonst könnten Sie feststellen, dass es sich um die gleichen Matrizen handelt, wenn nicht mit dem Befehl 'glGet'? – ybungalobill