2016-06-24 27 views
1

Ich beschäftige mich mit einem Versuchsaufbau, bei dem ein einfaches Bild einer genmodifizierten Fliege gezeigt wird. Das Bild wird auf einen Bildschirm mit bestimmten Abständen zu diesem fliegen projiziert.Wie wird die OpenGL-Perspektive korrigiert?

Nun ist es an mir, die Perspektivenkorrektur einzurichten, so dass das angezeigte Bild, z. B. ein horizontaler Balken, in einer größeren Entfernung vom Standpunkt der Fliege (experimental setup) breiter erscheint. Der Code sieht nun wie folgt aus:

glMatrixMode(GL_PROJECTION);       
glLoadIdentity(); 

if(!USEFRUSTUM) 
    gluPerspective(90.0f, 2 * width/height, 0.1f, 100.0f); 
else 
    glFrustum(92.3f, 2.3f, -25.0f, 65.0f, 50.0f, 1000.0f); 

Die Werte wurden vorher von jemandem ein paar Jahren eingegeben und wir heraus sie nicht mehr korrekt sind. Ich bin jedoch verwirrt, welche Werte eingegeben oder geändert werden müssen, damit die Projektion richtig funktioniert, weil das Sichtfeld der Fliege, wie Sie in der Versuchsanordnung sehen können, ein wenig geneigt ist.

Ich dachte an diesen Werten:

  • fovy = Winkel zwischen a und c
  • Maß Breite und Höhe auf dem Projektionsschirm
  • aber was zNear ist? Sollte ich die Entfernung von fliegen nach oben oder unten auf dem Bildschirm messen? Ich verstehe nicht, warum jemand 0.1f eingegeben hat, denn das scheint mir zu nah zu sein.
  • Wie kann ich den Wert von zFar wissen? Ist es die maximale Entfernung eines Objekts zur Fliege?

habe ich meine Informationen über glPerspective aus: https://www.ntu.edu.sg/home/ehchua/programming/opengl/CG_BasicsTheory.html Ich habe auch Simplest way to set up a 3D OpenGL perspective projection, aber dieser Beitrag nicht meinen Versuchsaufbau behandeln, die die Quelle meiner Verwirrung.

Vielen Dank für jede Hilfe!

Antwort

0

Dies ist eines der besten Beispiele, bei denen die Frustum-Methode einfacher zu verwenden ist als die Perspektive. Ein Frustum ist im Wesentlichen eine abgeschnittene Pyramide. Stellen Sie sich Ihre Fliege an der Spitze einer vierseitigen, gekippten Pyramide vor. Der Nahwert gibt den Abstand zur Basis der Pyramide und links, rechts, unten und oben den senkrechten Abstand jeder Seite der Pyramidenbasis zur Spitze an. Es ist vollkommen vernünftig, dass die Spitze "außerhalb" der Grundfläche ist. Oder im Falle Ihrer Fliege könnte die Mitte knapp über der "linken" Kante liegen.

So Ihre Originalbild vorausgesetzt, wir haben dies:

fly frustum

„In der Nähe“ gibt den „Abstand“ auf den Projektionsschirm und rechts (und natürlich auch oben, unten und links), um die jeweiligen Abstände der Spitze, err, fliege senkrecht zu den Rändern des Bildschirms.

"far" ist für die projektiven Merkmale nicht wichtig und wird nur zur Bestimmung des Tiefenbereichs verwendet.

Was können Sie in ein Programm ist folgende:

double near = ${distance to screen in mm}; 
double left = ${perpendicular to left screen edge in mm}; 
double right = ${perpendicular to right screen edge in mm}; 
double top = ${perpendicular to top screen edge in mm}; 
double bottom = ${perpendicular to bottom screen edge in mm}; 
double s = ${scaling factor from mm into OpenGL units}; 
double zrange = ${depth range in OpenGL units the far plane is behind near}; 
glFrustum(s*left, s*right, s*bottom, s*top, s*near, s*near + zrange); 

Denken Sie daran, die links, rechts, oben und unten negativ sein kann. Also sagen Sie, dass Sie eine symmetrische (unverschobene) Ansicht in einer Richtung haben möchten, dass left = -bottom und eine Verschiebung im Wesentlichen zu demselben Offset addiert/subtrahiert.

+0

Hey datenwolf! Ich danke Ihnen sehr für Ihre Antwort.Jetzt habe ich verstanden, wie man die Maße für nah, unten, links und rechts misst und wie der Kegelstumpf in meinem Fall aussieht. Was ich noch nicht verstehe ist, wie man den Skalierungsfaktor s bestimmt. Ich habe in "OpenGL Programming Guide: Der offizielle Leitfaden zum Erlernen von OpenGL, Version 3" (google books) gelesen, dass solange meine Messungen eine konsistente Einheit verwenden, ich sie nicht skalieren lassen kann. Der Tiefenbereich kann von der Sichtfeldtiefe der Fliege abhängen? Ich denke dann könnte ich mit meinen Kollegen einen angemessenen Wert besprechen. – TheCooocy

+0

@TheCooocy: Ja, Sie können "s" (d. H. S = 1) komplett weglassen, solange die gesamte Geometrie, die Sie mit OpenGL zeichnen, konsistent ist. Da Sie mit einem physischen Wesen (einem Tier) interagieren, ist es sehr sinnvoll, die Geometrie, die Sie mit OpenGL zeichnen, in den gleichen physikalischen Einheiten zu definieren, in denen das Projektionssystem "außen" gemessen wird * Abstand sollte nicht die Entfernung zum eigentlichen Bildschirm sein, aber wahrscheinlich näher an der Fliege (Abbildung eines winzigen Bildschirms direkt vor den Augen der Fliege). Aber für physische Einschränkungen in Ihrem Setup müssen Sie diesen größeren Bildschirm verwenden. – datenwolf

+0

@TheCooocy: Also, was Sie tun würden, dann ist das Verhältnis zwischen der "virtuellen" Nahdistanz 'n_' und der tatsächlichen Bildschirmdistanz' n', und skalieren Sie links, rechts, unten, oben und nah mit diesem Faktor 'n_/n '. Wenn du alles in, sagen wir, * mm * Einheiten machst, wäre das die Grenzentfernung, bei der Objekte (plötzlich) verschwinden. Aus praktischen Gründen sollten Sie für die Tiefenpufferauflösung den Wert für * far * so klein und den Wert für * near * so klein wie möglich für die Geometrie auswählen, die Sie zeichnen möchten. – datenwolf