Python 用PyOpenGL生成三维图形

Python 用PyOpenGL生成三维图形,python,opengl,3d,pyopengl,Python,Opengl,3d,Pyopengl,我正在使用PyOpenGL根据“二维波动方程”生成三维海面。主要目的是显示“二维波动方程”的动态图形。但它不断告诉我这个错误: E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\mytest>python seawave_2d_opengl.py Traceback (most recent call last): File "E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\lib\site-pack

我正在使用PyOpenGL根据“二维波动方程”生成三维海面。主要目的是显示“二维波动方程”的动态图形。但它不断告诉我这个错误:

E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\mytest>python seawave_2d_opengl.py
Traceback (most recent call last):
  File "E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\lib\site-packages\OpenGL\GLUT\
special.py", line 130, in safeCall
    return function( *args, **named )
  File "seawave_2d_opengl.py", line 106, in Draw
    glVertex3f(x,y,z)
  File "E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\lib\site-packages\OpenGL\p
latform\baseplatform.py", line 402, in __call__
    return self( *args, **named )
ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type
GLUT Display callback <function Draw at 0x0000000004086950> with (),{} failed: r
eturning None argument 3: <class 'TypeError'>: wrong type

E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\mytest>
E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\mytest>python-seave\u 2d\u opengl.py
回溯(最近一次呼叫最后一次):
文件“E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\lib\site packages\OpenGL\GLUT\
safeCall中的special.py“第130行
返回函数(*args,**已命名)
文件“seawave_2d_opengl.py”,第106行,在绘图中
glVertex3f(x,y,z)
文件“E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\lib\site packages\OpenGL\p
latform\baseplatform.py”,第402行,在调用中__
返回self(*args,**已命名)
ctypes.ArgumentError:参数3::错误类型
带(),{}的GLUT显示回调失败:r
eturning None参数3::类型错误
E:\WinPython-64bit-3.4.3.5\python-3.4.3.amd64\mytest>
代码如下:

from numpy import linspace,zeros,sin,pi,exp,sqrt
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import sys

def solver0(I, f, c, bc, Lx, Ly, nx, ny, dt, tstop, user_action=None):
    dx = Lx/float(nx)
    dy = Ly/float(ny)
    x = linspace(0, Lx, nx+1)  #grid points in x dir
    y = linspace(0, Ly, ny+1)  #grid points in y dir
    if dt <= 0:                #max time step?
        dt = (1/float(c))*(1/sqrt(1/dx**2 + 1/dy**2))
    Cx2 = (c*dt/dx)**2
    Cy2 = (c*dt/dy)**2  #help variables
    dt2 = dt**2

    up = zeros((nx+1,ny+1))  #solution array
    u = up.copy()            #solution at t-dt
    um = up.copy()           #solution at t-2*dt

    #set initial condition:
    t =0.0
    for i in range(0,nx):
        for j in range(0,ny):
            u[i,j] = I(x[i], y[j])
    for i in range(1,nx-1):
        for j in range(1,ny-1):
            um[i,j] = u[i,j] + \
                      0.5*Cx2*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \
                      0.5*Cy2*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) + \
                      dt2*f(x[i], y[j], t)
    #boundary values of um (equals t=dt when du/dt=0)
    i = 0
    for j in range(0,ny): um[i,j] = bc(x[i], y[j], t+dt)
    j = 0
    for i in range(0,nx): um[i,j] = bc(x[i], y[j], t+dt)
    i = nx
    for j in range(0,ny): um[i,j] = bc(x[i], y[j], t+dt)
    j = ny
    for i in range(0,nx): um[i,j] = bc(x[i], y[j], t+dt)

    if user_action is not None:
        user_action(u, x, y, t)   #allow user to plot etc.

    while t <= tstop:
        t_old = t
        t += dt

        #update all inner points:
        for i in range(1,nx-1):
            for j in range(1,ny-1):
                up[i,j] = -um[i,j] + 2*u[i,j] + \
                          Cx2*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \
                          Cy2*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) + \
                          dt2*f(x[i], y[j], t_old)

        #insert boundary conditions:
        i = 0
        for j in range(0,ny): up[i,j] = bc(x[i], y[j], t)
        j = 0
        for i in range(0,nx): up[i,j] = bc(x[i], y[j], t)
        i = nx
        for j in range(0,ny): up[i,j] = bc(x[i], y[j], t)
        j = ny
        for i in range(0,nx): up[i,j] = bc(x[i], y[j], t)

        if user_action is not None:
            user_action(up, x, y, t)

        um, u, up = u, up, um  #update data structures
    return u  #dt might be computed in this function
#Actually,the book wrote `return dt`,but I changed `dt` to `u`
def I(x, y):
    return exp(-(x-Lx/2.0)**2/2.0 -(y-Ly/2.0)**2/2.0)
def f(x, y, t):
    return sin(2*x*y*pi*t/Lx)  #defined by myself
def bc(x, y, t):
    return 0.0
#These three functions are some basic functions related to the first function "solver0"

Lx = 10
Ly = 10
c = 1.0
dt = 0
nx = 40
ny = 40
tstop = 20

#The following part is to generate 3D graphics,where I must make mistakes:
def init():
    glClearColor(1.0,1.0,1.0,0.0)  

def Draw():
    glClear(GL_COLOR_BUFFER_BIT)
    glColor3f(0,0,1.0)
    glBegin(GL_LINES)   
    for t in range(0,20,1):
        z = solver0(I, f, c, bc, Lx, Ly, nx, ny, dt, t, user_action=None)
        glVertex3f(x,y,z) 
 #x and y cannot be used here because they are not defined as global variables.
    glEnd()
    glFlush  

def Update():
    global t
    t += 0.1
    glutPostRedisplay() 

def main():    
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA)
    glutInitWindowSize(800,600)
    glutInitWindowPosition(100,50)
    glutCreateWindow("2D Wave Equations".encode("cp932"))
    init()
    glutDisplayFunc(Draw)
    glutIdleFunc(Update)
    glutMainLoop()   

main()
从numpy导入linspace、零、sin、pi、exp、sqrt
从OpenGL.GL导入*
从OpenGL.GLU导入*
从OpenGL.GLUT导入*
导入系统
def解算器0(I、f、c、bc、Lx、Ly、nx、ny、dt、tstop、user_action=None):
dx=Lx/浮点数(nx)
dy=Ly/float(纽约)
x=linspace(0,Lx,nx+1)#x方向上的栅格点
y=linspace(0,Ly,ny+1)#y方向上的栅格点

如果从stacktrace中可以猜到dt,
glVertex3f(x,y,z)
中的一个参数(第三个?!?)的类型错误。评论中的讨论清楚地表明,
z
是一个二维
ndarray
,而
glVertex3f()
需要标量。它看起来像是
solver0()
计算一个
z
值数组,而不是每次调用一个z值

编辑 我现在大致了解了
solver0()
的功能。该功能应记录在其印刷所在的书中。虽然Stackoverflow并不是要解释复制和粘贴代码,但我将简要介绍一下我认为该函数的功能:

  • Lx和Ly给出所有x和y的范围
  • nx和ny给出了在0和Lx之间使用的x和y值的数量
  • 该函数在计算z值(
    up
    )的位置计算x和y值数组
  • 它以步长
    dt
    计算从0到
    tstop
    的多个时间值的
    up
  • 如果给定了用户函数
    user\u action
    ,则在计算
    up
    后调用该函数。调用userfunction时使用
    up,x,y,t
    作为参数

  • 总而言之:一次调用
    solver0
    计算给定x和y值范围内的所有x、y和z值,以及具有给定分辨率的给定时间跨度。

    听起来变量
    z
    的类型不正确。检查
    解算器0(…)
    的输出。也许你没有返回结果。@jochen我确实返回了结果。所以
    z
    不能这样定义?我认为
    z
    是一种类型
    array
    …stacktrace指向
    glVertex3f(x,y,z)
    ,并告诉您其中一个参数的类型是错误的。只需再次检查所有三个参数的类型(例如,使用
    打印类型(x)、类型(y)、类型(z)
    )。@jochen你是对的。
    z
    的类型是错误的。它显示x和y的类型为
    numpy.float64
    ,z的类型为
    numpy.ndarry
    。我怎样才能解决这个问题?我试图通过
    float(z)
    转换z的类型,但没有成功,并且说
    只有length-1数组可以转换为Python标量
    您应该打印z的形状
    print z.shape
    。它将显示
    z
    有多个元素。问题可能是
    solver0
    计算的是
    z
    数组,而不是要绘制的特定
    x
    y
    z
    。我的猜测是基于这样一个事实,
    x
    y
    没有出现在对
    solver0()
    的调用中。对不起,我不太明白你的意思。正如您所知,
    z
    是一个二维的
    ndarry
    ,如何使用PyOpenGL解决这个问题?我只想使用
    glvertex
    绘制每个
    x
    y
    z
    以生成一个三维曲线图形。请原谅我对这方面知之甚少……不要担心问问题。我不知道
    solver0()
    是如何工作的。你必须先解决这个问题。应该有一些文档,或者你应该联系开发人员。仅仅因为x和y是全局的,并不意味着它们是
    I
    f
    的参数。在
    I(4,5)
    行中,
    I
    的参数将是
    (4,5)
    ,而不是全局
    (x,y)
    。不管怎么说,与全球人合作通常不是个好主意。另外,对x中的x使用
    :是个坏主意,因为这样你就用它的一个元素覆盖了全局
    x
    。哦,我明白了
    x
    y
    未传递到
    I
    f
    …我已将代码粘贴到
    solver0
    。它来自一本书,我做了一些修改。实际上,
    x
    y
    已经在
    solver0
    中定义,但是我不能在这个函数之外使用它,所以我自己在主体中定义了
    x
    y
    ,显然我做了一件错误的事情。所以我现在应该做的是找出如何绘制曲线…我又困惑了…我绘制曲线的方法是否错误?以前我用这种方法画了一条二维曲线。所以我自然也用这种方法来绘制3D曲线。但似乎有很多问题。实际上,我希望曲线随着
    t
    移动,以便显示动画。我想我必须修改
    Draw
    函数,但我不知道如何修改…非常感谢您向我解释这些。那么我是否可以将
    solver0
    OpenGL
    结合起来。看来