OpenGL-実行するとスタックオーバーフロー、実行しないとスタックアンダーフロー!


7

私は大学のマルチメディアクラスに参加しており、クラスの一部としてOpenGLを「学習」しています。OpenGLカメラとモデルビューの動作を理解しようとしているので、この例を見つけました。私はOpenGLバインディングを使用してサンプルをPythonに移植しようとしています-これはOpenGLをはるかに速く起動するため、テスト目的の場合ははるかに優れています-しかし、このコードのglPushMatrixでスタックオーバーフローエラーが発生し続けます。

  def cube(): 
      for x in xrange(10):
          glPushMatrix()
          glTranslated(-positionx[x + 1] * 10, 0, -positionz[x + 1] * 10); #translate the cube
          glutSolidCube(2); #draw the cube
          glPopMatrix();

このリファレンスによると、それはマトリックススタックがいっぱいのときに発生します。

それで、「まあ、満杯の場合は、マトリックスをスタックの一番上からポップして、スペースができるようにしよう」と考えました。私はコードを次のように変更しました:

  def cube(): 
      glPopMatrix()
      for x in xrange(10):
          glPushMatrix()
          glTranslated(-positionx[x + 1] * 10, 0, -positionz[x + 1] * 10); #translate the cube
          glutSolidCube(2); #draw the cube
          glPopMatrix();

そして今、私はバッファアンダーフローエラーを受け取ります-これはスタックが1つだけの行列を持っているときに明らかに起こります。

だから私は私の理解のベースから離れているだけですか?または、マトリックスのスタックサイズを増やす方法はありますか?

また、カメラ/モデルマトリックスがどのように連携するかを理解するための優れた(オンライン)リファレンス(例など)を誰かが持っている場合は、心から感謝します!

ありがとう!

編集:

ここに完全なコードのペーストビンがあります:http : //pastebin.com/QXxNisuA


2
それはあなたのコード全体ですか?対応するglPopMatrixがないglPushMatrixをこれ以上実行していないのですか?forがglPushMatrix命令のみに影響を与えていないと確信していますか?
r2d2rigo

はい、他のコードを確認する必要があります。射影行列はどこに設定していますか?GL_MODELVIEWモードに切り替えましたか?(射影行列スタックは信じられないほど小さいです。)
TheBuzzSaw '27

2番目のコードサンプルは絶対に避けてください。glPopMatrixが対応するglPushMatrixなしでそこに浮動することは確かにアンダーフローにつながります。最初のコードサンプルは問題ありません。コードの残りの部分に問題があるはずです。
TheBuzzSaw

エラーが含まれていたため、回答を削除しました。私は真実ではないものを想定しました。
Notabene

1
Stack'Flowでこれを聞いてみませんか?
Mateen Ulhaq、2011

回答:


9

追加のために編集:これは今でも問題なく機能し、OpenGLの学習を容易にしますが、OpenGL 3.x以降ではマトリックススタックシステム全体が非推奨になることに注意してください。1つの可能な置換はGLMです。

あなたのペーストビンのコードは私にとっても実行に失敗します。

特に、display関数のリストインデックスは範囲外です(リストには10​​個の要素があります:pythonリストは0から始まり、0 + 1から10 + 1までのインデックスです)。

マウス処理関数でいくつかのグローバルが欠落していると思いますが、少なくともPythonのように見せるためにコードを移動したことが原因である可能性があります;)

とにかく、これらの修正により、以下に示すコードは私のために機能し、GLマトリックススタックのアンダー/オーバーフローの兆候はありません!

import sys
from math import sin, cos
from random import randint
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
#angle of rotation
xpos= ypos= zpos= xrot= yrot= angle= lastx= lasty = 0

#positions of the cubes
positionz = []
positionx = []

def init():
    global positionz, positionx
    glEnable(GL_DEPTH_TEST) #enable the depth testing
    glEnable(GL_LIGHTING) #enable the lighting
    glEnable(GL_LIGHT0) #enable LIGHT0, our Diffuse Light
    glShadeModel(GL_SMOOTH) #set the shader to smooth shader

    positionx = [randint(0, 10) for x in xrange(10)]
    positionz = [randint(0, 10) for x in xrange(10)]

def camera():
    global xrot, yrot, xpos, ypos, zpos
    glRotatef(xrot,1.0,0.0,0.0)  #rotate our camera on teh x-axis (left and right)
    glRotatef(yrot,0.0,1.0,0.0)  #rotate our camera on the y-axis (up and down)
    glTranslated(-xpos,-ypos,-zpos) #translate the screen to the position of our camera

def display():
    global angle
    glClearColor(0.0,0.0,0.0,1.0) #clear the screen to black
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #clear the color buffer and the depth buffer
    glLoadIdentity()
    camera()
    for x in xrange(10):
        glPushMatrix()
        glTranslated(-positionx[x] * 10, 0, -positionz[x] * 10) #translate the cube
        glutSolidCube(2) #draw the cube
        glPopMatrix()
    glutSwapBuffers() #swap the buffers
    angle += angle #increase the angle

def reshape(w, h):
    glViewport(0, 0, w, h); #set the viewport to the current window specifications
    glMatrixMode(GL_PROJECTION); #set the matrix to projection

    glLoadIdentity();
    gluPerspective(60, w / h, 1.0, 1000.0)
    #set the perspective (angle of sight, width, height, , depth)
    glMatrixMode(GL_MODELVIEW); #set the matrix back to model

def keyboard (key, x, y):
    global xrot, xpos, ypos, zpos, xrot, yrot, angle, lastx, lasty, positionz, positionx
    if (key=='q'):
        xrot += 1
        if (xrot >360):
            xrot -= 360
    if (key=='z'):
        xrot -= 1;
        if (xrot < -360): xrot += 360
    if (key=='w'):
        yrotrad = (yrot / 180 * 3.141592654)
        xrotrad = (xrot / 180 * 3.141592654)
        xpos += float(sin(yrotrad))
        zpos -= float(cos(yrotrad))
        ypos -= float(sin(xrotrad))
    if (key=='s'):
        yrotrad = (yrot / 180 * 3.141592654)
        xrotrad = (xrot / 180 * 3.141592654)
        xpos -= float(sin(yrotrad))
        zpos += float(cos(yrotrad))
        ypos += float(sin(xrotrad))
    if (key=='d'):
        yrotrad = (yrot / 180 * 3.141592654)
        xpos += float(cos(yrotrad)) * 0.2
        zpos += float(sin(yrotrad)) * 0.2
    if (key=='a'):
        yrotrad = (yrot / 180 * 3.141592654)
        xpos -= float(cos(yrotrad)) * 0.2
        zpos -= float(sin(yrotrad)) * 0.2
    if (key==27):
        sys.exit(0)

def mouseMovement(x, y):
    global lastx, lasty, xrot, yrot
    diffx=x-lastx #check the difference between the current x and the last x position
    diffy=y-lasty #check the difference between the current y and the last y position
    lastx=x #set lastx to the current x position
    lasty=y #set lasty to the current y position
    xrot += float(diffy) #set the xrot to xrot with the addition of the difference in the y position
    yrot += float(diffx) #set the xrot to yrot with the addition of the difference in the x position

glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(500, 500)
glutInitWindowPosition (100, 100)
glutCreateWindow("A basic OpenGL Window")
init()
glutDisplayFunc(display)
glutIdleFunc(display)
glutReshapeFunc(reshape)
glutPassiveMotionFunc(mouseMovement)
#check for mouse movement
glutKeyboardFunc (keyboard)
glutMainLoop()

4
あなたは彼らの宿題をしました!彼らは何がうまくいかなかったか、そしてそれを修正する方法を学びますか、それとも単にコピーして貼り付けて次に進むでしょうか?
ウィル

1
だから、あまりにも役立つことは投票する理由ですか?そして、基本的に1つの間違いによって1回限りだったものを修正することは、「宿題をする」ことですか?あなたは完全なコードでペーストビン上のOPプットを見れば、あなたは...私はちょうどこれら二つの間違ったインデックスを、私はより簡単にそれを読むことができるようにコードを移動し、変更に注意しましょう
Bethor

1
これ実際に便利です-私の問題はありませんでした
ウェインワーナー

この返信実際に役立ちます。また、私の実際の宿題とはほとんど関係がありません。私が最初に投稿したように、私はカメラがどのように機能するかを理解することに興味があります。つまり、このコードをいじくります。Bethorは私の質問に回答し(これは1回限りのエラーであり、元のコード例に組み込まれています)、それを超えてコードをクリーンアップしました。したがって、受け入れられます。(私のコメントを自動投稿し、まともなコメントを下書きする前に時間を切ってくれたdrat SO)
Wayne Werner

たくさんのたくさんのコード:)
daemonfire300

1

OpenGLは使用してスタックに行列を保存し、復元することができますglPushMatrixし、glPopMatrix。各プッシュに対応するポップがあることが非常に重要です。ポップよりも多くプッシュすると、すべての描画が終了すると、スタックがオーバーフローしていることが通知されます。プッシュする以上にポップすると、スタックがアンダーフローしていることがすぐにわかります。これは、OpenGLでプログラミングエラーをローカライズする方法です。

そのため、あらゆる場所のすべてのプッシュに対応するポップがあることを確認してください。

プッシュするすべての場所で、そのコードブロックの出口に対応するポップがあることを確認します。

コードが例外をスローしている場合(つまり、配列の境界を超えて反復している場合など)、popを​​finallyブロックに配置する必要がある可能性があります。例:

def cube():
    for x in xrange(10):
        try:
            glPushMatrix()
            # draw something
        finally:
            glPopMatrix()
            # I'm trusting some code further out will catch and display your actual error now

あなたが投票したという私の回答で概説したように、あなたが指摘したように、問題は範囲外で繰り返されているので、これは問題を修正しません。また、これは彼が実際の答えを見ることを助けません。例外は捕捉されないため、スクリプトは引き続き終了します。だから、もし私が反対票を投じることができれば、-1、特に私の以前の答えを埋めようとする非常に悪い形に!
Bethor

アンバランスなスタックを検出するGLスタックからの例外は、根本原因の例外の表示を停止しているものです。彼がターミナルに不均衡なスタックがあるというレポートを見るのと同じように、彼は今彼は範囲外の例外を持っていることがわかります。
ウィル

けっこうだ; 彼がスタックオーバーフローをどのように見ているのかはまだわかりません。彼のペーストビンのコードは、Python 2.7と最新のPyOpenGLのインストールに適した場所でIndexErrorを発生させ、これが修正されると正しく実行されます。その上、彼のコードは、私がそれを読んでいることからわかる限り、ポップする以上にプッシュすることはありません。
Bethor

1
OpenGLの実装に依存します。彼のOpenGL実装が、例外の巻き戻しによってトリガーされる整理されたコードを積極的にカウントしていることは明らかです。
2011

いい視点ね !ただし、すべてをトリガーした例外はおそらくOPに表示されますが、彼は最後の例外を確認しただけで根本的な原因を検索しなかったと思います。
Bethor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.