2017-09-14 8 views
1

WindowsとMacで正常に動作するPythonベースのOpenGLコードがかなり複雑ですが、Linux上では奇妙な帯球では失敗します。二つの角度からの再生回数:enter image description hereLinuxのOpenGLコードが失敗し、Mac&Windowsで動作する

問題だけではなく球であるが、これは表示する最も簡単なものである:ここでは enter image description hereenter image description here

は、Mac上の同じコードのプロットとは何か。この問題は、私よりもOpenGLの経験が豊富な人にとっては何かを示唆していますか?

ヒントやご提案ありがとうございます。ここで

はあなたがWX_GL_DEPTH_SIZEを設定することで、ハードウェアの条件に応じて、デプスバッファのためのビット数を指定する必要があり、この問題

'''Draws a sphere and axis triplet with openGL; rotates with mouse drag. 
This works fine on Windows and Mac, but sphere displays strangely on Linux 
''' 
import sys 
import math 
import numpy as np 
import numpy.linalg as nl 
import wx 
import wx.glcanvas 
import OpenGL.GL as GL 
import OpenGL.GLU as GLU 
drawingData = { 
    'oldxy' : [0, 0], 
    'Quaternion' : np.array([ 0.11783419, 0.87355958, 0.09141639, 0.4633053 ]), 
    'linecolors': [(np.array([[0, 0, 0], [1, 0, 0]]), [255, 0, 0]), 
        (np.array([[0, 0, 0], [0, 1, 0]]), [ 0, 255, 0]), 
        (np.array([[0, 0, 0], [0, 0, 1]]), [ 0, 0, 255])], 
} 

def Q2Mat(Q): 
    ''' make rotation matrix from quaternion 
    ''' 
    QN = Q/np.sqrt(np.sum(np.array(Q)**2)) 
    aa = QN[0]**2 
    ab = QN[0]*QN[1] 
    ac = QN[0]*QN[2] 
    ad = QN[0]*QN[3] 
    bb = QN[1]**2 
    bc = QN[1]*QN[2] 
    bd = QN[1]*QN[3] 
    cc = QN[2]**2 
    cd = QN[2]*QN[3] 
    dd = QN[3]**2 
    M = [[aa+bb-cc-dd, 2.*(bc-ad), 2.*(ac+bd)], 
     [2*(ad+bc), aa-bb+cc-dd, 2.*(cd-ab)], 
     [2*(bd-ac), 2.*(ab+cd), aa-bb-cc+dd]] 
    return np.array(M) 

def prodQVQ(Q,V): 
    """compute the quaternion vector rotation qvq-1 = v' 
    """ 
    T2 = Q[0]*Q[1] 
    T3 = Q[0]*Q[2] 
    T4 = Q[0]*Q[3] 
    T5 = -Q[1]*Q[1] 
    T6 = Q[1]*Q[2] 
    T7 = Q[1]*Q[3] 
    T8 = -Q[2]*Q[2] 
    T9 = Q[2]*Q[3] 
    T10 = -Q[3]*Q[3] 
    M = np.array([[T8+T10,T6-T4,T3+T7],[T4+T6,T5+T10,T9-T2],[T7-T3,T2+T9,T5+T8]]) 
    VP = 2.*np.inner(V,M) 
    return VP+V 

def invQ(Q): 
    '''get inverse of quaternion q=r+ai+bj+ck; q* = r-ai-bj-ck 
    ''' 
    return Q*np.array([1,-1,-1,-1]) 

def AVdeg2Q(A,V): 
    ''' convert angle (degrees) & vector to quaternion 
     q=r+ai+bj+ck 
    ''' 
    sind = lambda x: math.sin(x*math.pi/180.) 
    cosd = lambda x: math.cos(x*math.pi/180.) 
    Q = np.zeros(4) 
    d = nl.norm(np.array(V)) 
    if not A:  #== 0.! 
     A = 360. 
    if d: 
     V = V/d 
     p = A/2. 
     Q[0] = cosd(p) 
     Q[1:4] = V*sind(p) 
    else: 
     Q[3] = 1. 
    return Q 

def prodQQ(QA,QB): 
    ''' Grassman quaternion product, QA,QB quaternions; q=r+ai+bj+ck 
    ''' 
    D = np.zeros(4) 
    D[0] = QA[0]*QB[0]-QA[1]*QB[1]-QA[2]*QB[2]-QA[3]*QB[3] 
    D[1] = QA[0]*QB[1]+QA[1]*QB[0]+QA[2]*QB[3]-QA[3]*QB[2] 
    D[2] = QA[0]*QB[2]-QA[1]*QB[3]+QA[2]*QB[0]+QA[3]*QB[1] 
    D[3] = QA[0]*QB[3]+QA[1]*QB[2]-QA[2]*QB[1]+QA[3]*QB[0] 
    return D 

def RenderUnitVectors(x,y,z): 
    'Show the axes' 
    GL.glEnable(GL.GL_COLOR_MATERIAL) 
    GL.glLineWidth(2) 
    GL.glEnable(GL.GL_BLEND) 
    GL.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE_MINUS_SRC_ALPHA) 
    GL.glEnable(GL.GL_LINE_SMOOTH) 
    GL.glPushMatrix() 
    GL.glTranslate(x,y,z) 
    GL.glScalef(1,1,1) 
    GL.glBegin(GL.GL_LINES) 
    for line,color in drawingData['linecolors']: 
      GL.glColor3ubv(color) 
      GL.glVertex3fv(-line[1]/2.) 
      GL.glVertex3fv(line[1]/2.) 
    GL.glEnd() 
    GL.glPopMatrix() 
    GL.glColor4ubv([0,0,0,0]) 
    GL.glDisable(GL.GL_LINE_SMOOTH) 
    GL.glDisable(GL.GL_BLEND) 
    GL.glDisable(GL.GL_COLOR_MATERIAL) 

def RenderSphere(x,y,z,radius,color): 
    'show a sphere' 
    GL.glMaterialfv(GL.GL_FRONT_AND_BACK,GL.GL_DIFFUSE,color) 
    GL.glPushMatrix() 
    GL.glTranslate(x,y,z)   
    GL.glMultMatrixf(np.eye(4).T) 
    GLU.gluSphere(GLU.gluNewQuadric(),radius,20,10) 
    GL.glPopMatrix() 

class myGLCanvas(wx.Panel): 
    def __init__(self, parent, id=-1,dpi=None,**kwargs): 
     wx.Panel.__init__(self,parent,id=id,**kwargs) 
     if 'win' in sys.platform:   # for Windows (& darwin==Mac) -- already double buffered 
      attribs = None 
     else:        # Linux 
      attribs = [wx.glcanvas.WX_GL_DOUBLEBUFFER,] 
     self.canvas = wx.glcanvas.GLCanvas(self,-1,attribList=attribs,**kwargs) 
     self.context = wx.glcanvas.GLContext(self.canvas) 
     self.canvas.SetCurrent(self.context) 
     sizer=wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.canvas,1,wx.EXPAND) 
     self.SetSizer(sizer) 
     self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMove) 
     self.Draw() 
     self.Draw() 
     return 

    def OnMouseMove(self,event): 
     if not event.Dragging(): 
      drawingData['oldxy'] = list(event.GetPosition()) 
      return 
     # Perform a rotation in x-y space 
     oldxy = drawingData['oldxy'] 
     if not len(oldxy): oldxy = list(event.GetPosition()) 
     dxy = event.GetPosition()-oldxy 
     drawingData['oldxy'] = list(event.GetPosition()) 
     V = np.array([dxy[1],dxy[0],0.]) 
     A = 0.25*np.sqrt(dxy[0]**2+dxy[1]**2) 
     if not A: return 
     # next transform vector back to xtal coordinates via inverse quaternion & make new quaternion 
     Q = drawingData['Quaternion'] 
     V = prodQVQ(invQ(Q),np.inner(np.eye(3),V)) 
     Q = prodQQ(Q,AVdeg2Q(A,V)) 
     drawingData['Quaternion'] = Q 
     self.Draw() 

    def Draw(self): 
     GL.glClearColor(0.,0.,0.,0.) 
     GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 
     GL.glInitNames() 
     GL.glPushName(0) 

     GL.glMatrixMode(GL.GL_PROJECTION) 
     GL.glLoadIdentity() 
     GL.glViewport(0,0,*self.canvas.GetSize()) 
     GLU.gluPerspective(20.,self.canvas.GetSize()[0]*1./self.canvas.GetSize()[1],7.5,12.5) 
     GLU.gluLookAt(0,0,10,0,0,0,0,1,0) 

     # Set Lighting    
     GL.glEnable(GL.GL_DEPTH_TEST) 
     GL.glEnable(GL.GL_LIGHTING) 
     GL.glEnable(GL.GL_LIGHT0) 
     GL.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE,0) 
     GL.glLightfv(GL.GL_LIGHT0,GL.GL_AMBIENT,[1,1,1,1]) 
     GL.glLightfv(GL.GL_LIGHT0,GL.GL_DIFFUSE,[1,1,1,1]) 

     GL.glMatrixMode(GL.GL_MODELVIEW) 
     GL.glLoadIdentity() 
     matRot = Q2Mat(drawingData['Quaternion']) 
     matRot = np.concatenate((np.concatenate((matRot,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0) 
     GL.glMultMatrixf(matRot.T) 
     GL.glMultMatrixf(np.eye(4).T) 
     Tx,Ty,Tz = (0.20045985394544949, 0.44135342324377724, 0.40844172594191536) 
     GL.glTranslate(-Tx,-Ty,-Tz) 
     RenderUnitVectors(Tx,Ty,Tz) 
     RenderSphere(0, 0, 0, 0.804, [1., 1., 1.]) 
     self.canvas.SetCurrent(self.context) 
     self.canvas.SwapBuffers() 

class GUI(wx.App): 
    def OnInit(self): 
     frame = wx.Frame(None,-1,'ball rendering',wx.DefaultPosition,wx.Size(400,400)) 
     frame.Show() 
     wx.CallAfter(myGLCanvas,frame,size=wx.Size(400,400)) # wait for frame to be displayed 
     self.MainLoop() 
     return True 

if __name__ == '__main__': 
    GUI() 
+0

お読みください[作り方最小、完全、および検証可能な例](https://stackoverflow.com/help/mcve)をご覧ください。 – Rabbid76

+0

深度バッファの問題のようですが、より具体的にする必要があります。フレームバッファを使用していますか?どのようにシーン(ソースコード)を描くのですか? – Rabbid76

+0

問題を説明するコードが大幅に短縮されました。まだ完全にLinuxでテストされていません(私は回転をデバッグする前に問題を示していました)。 FWIW、私はMacのWX_GL_DOUBLEBUFFERをオンにすることで、Linuxの問題に似た何かを見ることができます。 – bht

答えて

1

を示したいくつかのサンプルコードです。デプスバッファのサイズは、16、24または32

attribs = [ 
    wx.glcanvas.WX_GL_RGBA, 
    wx.glcanvas.WX_GL_DOUBLEBUFFER, 
    wx.glcanvas.WX_GL_DEPTH_SIZE, 16] 

参照してくださいする必要があります。

+1

これは本当に問題でした! wx.glcanvas.GLCanvasとwx.glcanvas.GLContext呼び出しをtry/exceptブロック内のループに入れ、連続して32,24,16ビットを試してみましょう。 – bht

関連する問題