2015-11-03 7 views
17

QtとPyOpenGLを使用してリアルタイムプロットを行い、OpenGLについて少し学びたいが、私の初期テストデータが表示されるのに問題がある。PyOpenGLによるトラブルプロット

x座標とy座標を異なるバッファに格納するのは、y座標がほぼすべてのレンダリングを変更している間にx座標がほとんど変化しないためです。残念ながら、それらを別々のバッファに入れておくと、私に問題が生じます。

今のところエラーはなく、何も表示されないため、どこに行くのかわかりません。私もここにプログラムの完全に動作するバージョンを入れ

class GLWidget(QtOpenGL.QGLWidget): 
    def __init__(self, parent=None): 
     self.parent = parent 
     QtOpenGL.QGLWidget.__init__(self, parent) 
     self.current_position = 0 

    def initializeGL(self): 
     self.initGeometry() 

     self.vertex_code = """ 
      #version 120 
      attribute vec4 color; 
      attribute float x_position; 
      attribute float y_position; 
      varying vec4 v_color; 
      void main() 
      { 
       gl_Position = vec4(x_position, y_position, 0.0, 1.0); 
       v_color = color; 
      } """ 

     self.fragment_code = """ 
      #version 120 
      varying vec4 v_color; 
      void main() 
      { 
       //gl_FragColor = v_color; 
       gl_FragColor = vec4(1,1,1,1); 
      } """ 

     ## Build and activate program 
     # Request program and shader slots from GPU 
     self.program = GL.glCreateProgram() 
     self.vertex = GL.glCreateShader(GL.GL_VERTEX_SHADER) 
     self.fragment = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) 

     # Set shaders source 
     GL.glShaderSource(self.vertex, self.vertex_code) 
     GL.glShaderSource(self.fragment, self.fragment_code) 

     # Compile shaders 
     GL.glCompileShader(self.vertex) 
     GL.glCompileShader(self.fragment) 

     # Attach shader objects to the program 
     GL.glAttachShader(self.program, self.vertex) 
     GL.glAttachShader(self.program, self.fragment) 

     # Build program 
     GL.glLinkProgram(self.program) 

     # Get rid of shaders (not needed anymore) 
     GL.glDetachShader(self.program, self.vertex) 
     GL.glDetachShader(self.program, self.fragment) 

     # Make program the default program 
     GL.glUseProgram(self.program) 

     # Create array object 
     self.vao = GL.glGenVertexArrays(1) 
     GL.glBindVertexArray(self.vao) 

     # Request buffer slot from GPU 
     self.x_data_buffer = GL.glGenBuffers(1) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) 
     GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.x), self.x, GL.GL_DYNAMIC_DRAW) 

     self.y_data_buffer = GL.glGenBuffers(1) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) 
     GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.y), self.y, GL.GL_DYNAMIC_DRAW) 




     ## Bind attributes 
     #self.stride = self.x.strides[0] 
     #self.offset = ctypes.c_void_p(0) 
     self.loc = GL.glGetAttribLocation(self.program, "x_position".encode('utf-8')) 
     GL.glEnableVertexAttribArray(self.loc) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) 
     GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) 

     #self.stride = self.y.strides[0] 
     #self.offset = ctypes.c_void_p(0) 
     self.loc = GL.glGetAttribLocation(self.program, "y_position".encode('utf-8')) 
     GL.glEnableVertexAttribArray(self.loc) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) 
     GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) 


    def resizeGL(self, width, height): 
     if height == 0: height = 1 

     GL.glViewport(0, 0, width, height) 
     GL.glMatrixMode(GL.GL_PROJECTION) 
     GL.glLoadIdentity() 
     aspect = width/float(height) 

     GLU.gluPerspective(45.0, aspect, 1.0, 100.0) 
     GL.glMatrixMode(GL.GL_MODELVIEW) 

    def paintGL(self): 
     GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 

     GL.glDrawArrays(GL.GL_LINE_STRIP, 0, self.bins) 


    def initGeometry(self): 
     self.bins = 1000 

     self.x = np.linspace(-0.5,0.5,self.bins) 
     self.y = np.array([np.sin(val*2*np.pi) for val in self.x]) 
     self.color = np.array([(1,1,1,1) for x in np.arange(self.bins)]) 


    def addPoint(self, point): 
     #print('ADD POINT') 
     self.y[self.current_position] = point 
     if self.current_position < self.bins-1: 
      self.current_position += 1 
     else: 
      self.current_position = 0 

     return True 

    def render(self): 
     #print('RENDER') 
     self.updateGL() 
     return True 

:問題は最も可能性が高いの呼び出しである

import sys 
from PyQt5.QtWidgets import QDesktopWidget, QMainWindow, QWidget, QAction, qApp, QApplication, QHBoxLayout, QVBoxLayout, QPushButton 
from PyQt5.QtCore import QTimer 
from PyQt5.QtGui import QIcon 
from PyQt5 import QtOpenGL 

from OpenGL import GL 
from OpenGL import GLU 
from OpenGL.arrays.arraydatatype import ArrayDatatype 

import ctypes 
import numpy as np 
from threading import Timer, Thread, Event 

class OxySensor(QMainWindow): 
    def __init__(self): 
     super().__init__() 
     self.initUI() 
     self.initActions() 
     self.initMenuBar() 
     self.initRenderTimer() 
     self.start() 

    def initUI(self): 
     self.resize(800,600) 
     self.center() 
     self.setWindowTitle('OxySensor') 

     okButton = QPushButton("OK") 
     cancelButton = QPushButton("Cancel") 


     hbox = QHBoxLayout() 
     hbox.addStretch(1) 
     hbox.addWidget(okButton) 
     hbox.addWidget(cancelButton) 

     vbox = QVBoxLayout() 
     #vbox.addStretch(1) 
     self.gl_widget = GLWidget() 
     vbox.addWidget(self.gl_widget) 
     vbox.addLayout(hbox) 

     mainWidget = QWidget(self) 
     mainWidget.setLayout(vbox) 

     self.setCentralWidget(mainWidget) 


     self.show() 

    def initActions(self): 
     self.exitAction = QAction(QIcon('images/close20.png'), '&Exit', self) 
     self.exitAction.setShortcut('Ctrl+W') 
     self.exitAction.setStatusTip('Exit application') 
     self.exitAction.triggered.connect(self.onExit) 

    def initMenuBar(self): 
     menubar = self.menuBar() 
     fileMenu = menubar.addMenu('&File') 
     fileMenu.addAction(self.exitAction) 
     return True 

    def initRenderTimer(self): 
     self.timer = QTimer() 
     self.timer.timeout.connect(self.gl_widget.render) 
     self.timer.start(100) 
     return True 

    def start(self): 
     self.stop_flag = Event() 
     self.thread = SerialPort(self.onTimerExpired, self.stop_flag) 
     self.thread.start() 
     self.statusBar().showMessage('Ready') 

    def center(self): 
     qr = self.frameGeometry() 
     cp = QDesktopWidget().availableGeometry().center() 
     qr.moveCenter(cp) 
     self.move(qr.topLeft()) 
     return True 

    def onTimerExpired(self): 
     data = np.random.uniform(-1,1) 
     self.gl_widget.addPoint(data) 
     return True 

    def onExit(self): 
     self.close() 
     return None 

    def closeEvent(self,event): 
     self.stop_flag.set() 
     event.accept() 
     return None 

class GLWidget(QtOpenGL.QGLWidget): 
    def __init__(self, parent=None): 
     self.parent = parent 
     QtOpenGL.QGLWidget.__init__(self, parent) 
     self.yRotDeg = 0.0 
     self.current_position = 0 

    def initializeGL(self): 
     self.initGeometry() 

     self.vertex_code = """ 
      #version 120 
      attribute vec4 color; 
      attribute float x_position; 
      attribute float y_position; 
      varying vec4 v_color; 
      void main() 
      { 
       gl_Position = vec4(x_position, y_position, 0.0, 1.0); 
       v_color = color; 
      } """ 

     self.fragment_code = """ 
      #version 120 
      varying vec4 v_color; 
      void main() 
      { 
       //gl_FragColor = v_color; 
       gl_FragColor = vec4(1,1,1,1); 
      } """ 

     ## Build and activate program 
     # Request program and shader slots from GPU 
     self.program = GL.glCreateProgram() 
     self.vertex = GL.glCreateShader(GL.GL_VERTEX_SHADER) 
     self.fragment = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) 

     # Set shaders source 
     GL.glShaderSource(self.vertex, self.vertex_code) 
     GL.glShaderSource(self.fragment, self.fragment_code) 

     # Compile shaders 
     GL.glCompileShader(self.vertex) 
     GL.glCompileShader(self.fragment) 

     # Attach shader objects to the program 
     GL.glAttachShader(self.program, self.vertex) 
     GL.glAttachShader(self.program, self.fragment) 

     # Build program 
     GL.glLinkProgram(self.program) 

     # Get rid of shaders (not needed anymore) 
     GL.glDetachShader(self.program, self.vertex) 
     GL.glDetachShader(self.program, self.fragment) 

     # Make program the default program 
     GL.glUseProgram(self.program) 

     # Create array object 
     self.vao = GL.glGenVertexArrays(1) 
     GL.glBindVertexArray(self.vao) 

     # Request buffer slot from GPU 
     self.x_data_buffer = GL.glGenBuffers(1) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) 
     GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.x), self.x, GL.GL_DYNAMIC_DRAW) 

     self.y_data_buffer = GL.glGenBuffers(1) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) 
     GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.y), self.y, GL.GL_DYNAMIC_DRAW) 




     ## Bind attributes 
     #self.stride = self.x.strides[0] 
     #self.offset = ctypes.c_void_p(0) 
     self.loc = GL.glGetAttribLocation(self.program, "x_position".encode('utf-8')) 
     GL.glEnableVertexAttribArray(self.loc) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) 
     GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) 

     #self.stride = self.y.strides[0] 
     #self.offset = ctypes.c_void_p(0) 
     self.loc = GL.glGetAttribLocation(self.program, "y_position".encode('utf-8')) 
     GL.glEnableVertexAttribArray(self.loc) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) 
     GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) 


    def resizeGL(self, width, height): 
     if height == 0: height = 1 

     GL.glViewport(0, 0, width, height) 
     GL.glMatrixMode(GL.GL_PROJECTION) 
     GL.glLoadIdentity() 
     aspect = width/float(height) 

     GLU.gluPerspective(45.0, aspect, 1.0, 100.0) 
     GL.glMatrixMode(GL.GL_MODELVIEW) 

    def paintGL(self): 
     GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 

     GL.glDrawArrays(GL.GL_LINE_STRIP, 0, self.bins) 


    def initGeometry(self): 
     self.bins = 1000 

     self.x = np.linspace(-0.5,0.5,self.bins) 
     self.y = np.array([np.sin(val*2*np.pi) for val in self.x]) 
     self.color = np.array([(1,1,1,1) for x in np.arange(self.bins)]) 


    def addPoint(self, point): 
     #print('ADD POINT') 
     self.y[self.current_position] = point 
     if self.current_position < self.bins-1: 
      self.current_position += 1 
     else: 
      self.current_position = 0 

     return True 

    def render(self): 
     #print('RENDER') 
     self.updateGL() 
     return True 

class SerialPort(Thread): 
    def __init__(self, callback, event): 
     Thread.__init__(self) 
     self.callback = callback 
     self.stopped = event 
     return None 

    def SetInterval(self, time_in_seconds): 
     self.delay_period = time_in_seconds 
     return True 

    def run(self): 
     while not self.stopped.wait(0.1): 
      self.callback() 
     return True 

if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    oxy_sensor = OxySensor() 
    sys.exit(app.exec_()) 
+0

どこ 'updateGL()'メソッドはありますか?これまでに投稿されたコードは、最初に作成した後はVBOの内容を実際に更新することはありません。 – derhass

+0

は 'updateGLは()' 'レンダリング()'メソッドである – user2027202827

+0

まあ、私はそれが_called_があることがわかります。たぶん私は何かを誤解しているかもしれません。この 'updateGL'はpthon OpenGLウィジェットのいくつかのメソッドです。もしそうなら、私のコメントはさらに多くのものに当てはまります。あなたは実際にそれらのVBOを更新することは決してありません(私は 'updateGL'でやったと思います)。 – derhass

答えて

3

ここ

は私がプロットクラスのために、これまで持っているものです「OpenGL.GL」関数:

GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) 

注最後の値が、残念ながら、トランスません0(あります(void *)0より遅く、C++ APIにありますが、代わりに高いアドレスになります)。あなたは、 "0オブジェクトのアドレス"とは対照的に "オフセット0"を意味する可能性が最も高いです。 I. ((void *)0に変換した)代わりにNoneを使用します。

GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, None) 

はい、それはちょっと直感に反するです。それが私のコードで出力を黒にしたのは、半日でした。

はまた、代わりにOpenGL.GL機能のあなたは(あなたがgl = self.context().versionFunctions()経由で取得すること)のQtのものを使用している場合、彼らはわずかに異なるAPIを提供し、そこにあなたが実際にあなたが意味するとき0が「0オフセット」を渡すことに注意してください。

+0

ちょっと、私はこのサイトにいませんでしたが、 'GL.glVertexAttribPointer()'に 'None'を渡してくださった素晴らしいキャッチについて感謝したいと思います。 – user2027202827

-1

あなたはプログラムのOpenGLの機能に基づいていますアボガドロ
http://avogadro.cc/wiki/Main_Page を見てみる必要があります。

ソースコードは自由であり、それは有用であり得ます。

+1

潜在的なソリューションへのリンクは常に歓迎しますが、リンクの周りにコンテキストを追加して、仲間のユーザーには何か、なぜそれがあるのか​​を理解させてください。ターゲットサイトに到達できない場合や、永続的にオフラインになる場合は、常に重要なリンクの最も関連性の高い部分を引用してください。 – Exaqt

+0

...リンクが壊れているので特に! – uhoh

関連する問題