我正在尝试编写一个程序,该程序接受蛋白质中一组原子的x,y,z坐标,这些原子都被标准化为[0,1]范围。然而,在这样做时,我在绘制点时非常困难,因此它们看起来是“三维的”。也就是说,我可以使用glVertex3fv为每个点提供所有三个坐标而没有太多麻烦来绘制点,但我尝试使用gluPerspective和gluLookAt来适当地构图相机已经令人沮丧,我一直无法找到任何资源在线解释原因。
我已经为gluPerspective指定了使用50.0视角的参数,以及1:1的宽高比。我已经将minZ和maxZ参数指定为-1和1,它应该包含我的数据点的宽度,因为它们是从[0,1]标准化的,如上所述。评论gluPerspective显示了在“2d”空间中绘制的点 - 尽管如果我的理解是正确的,它们是三维绘制的。取消注释gluPerspective会使窗口变为空白。
gluLookAt似乎绝对没有做任何事,无论我传递什么参数。
我正在使用PyOpenGL,它只是OpenGL for Python的包装器。这允许我使用OpenGL和一些特定于python的库 - 在本例中是ProDy(用于解析/获取/操作蛋白质数据文件的库)。
我正在使用Python 2.7和OpenGL 3.1 build 9.17.10.3517。
我的程序从PDB中获取蛋白质文件,解析它,获取蛋白质中每个原子的坐标,对它们进行标准化,并将坐标绘制到屏幕上。
这是我的代码:
import OpenGL
from prody import *
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
#create initial window parameters
width = 500
height = 500
#fetch PDB data
id = "1cwa"
filename = fetchPDB(id)
atoms = parsePDB(filename)
coords = atoms.getCoords()
#max/mins
class Stats(object):
maxX = coords[0][0]
maxY = coords[0][1]
maxZ = coords[0][2]
minX = maxX-1
minY = maxY-1
minZ = maxZ-1
meanX = 0
meanY = 0
meanZ = 0
def Scale():
#find max and min for each range
for a in coords:
#print(a[2])
if(a[0] < Stats.minX):
Stats.minX = a[0]
elif(a[0] > Stats.maxX):
Stats.maxX = a[0]
if(a[1] < Stats.minY):
Stats.minY = a[1]
elif(a[1] > Stats.maxY):
Stats.maxY = a[1]
if(a[2] < Stats.minZ):
Stats.minZ = a[2]
elif(a[2] > Stats.maxZ):
Stats.maxZ = a[2]
#multiply projection matrix
quoX = Stats.maxX - Stats.minX
quoY = Stats.maxY - Stats.minY
quoZ = Stats.maxZ - Stats.minZ
quoN = max(quoZ,max(quoX,quoY))
Stats.meanX = (Stats.maxX + Stats.minX)/2
Stats.meanY = (Stats.maxY + Stats.minY)/2
Stats.meanZ = (Stats.maxZ + Stats.minZ)/2
for a in coords:
a[0] = (a[0]-Stats.minX)/(quoN)
print(a[0])
a[1] = (a[1]-Stats.minY)/(quoN)
print(a[1])
a[2] = (a[2]-Stats.minZ)/(quoN)
print(a[2])
def drawAtom(atom):
x = atom[0]
y = atom[1]
z = atom[2]
glBegin(GL_POINTS)
#glVertex2f(x,y)
glVertex3fv(atom)
glEnd()
def draw():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glEnable(GL_DEPTH_TEST)
glPointSize(7)
for atom in coords:
drawAtom(atom)
glutSwapBuffers()
def init():
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowPosition(0, 0)
glutInitWindowSize(width,height)
glutCreateWindow(b"CycloVis")
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
Scale()
#gluPerspective(50.0,1.0,-1,1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(1,1,5,Stats.minZ,Stats.meanZ,Stats.maxZ,9999999,1,1)
glColor3d(1.0, 0.0, 1.0)
glutDisplayFunc(draw)
if __name__ == '__main__':
#initialize
init()
if "-vers" in sys.argv:
print ("GL_VERSION = ", glGetString(GL_VERSION))
glutMainLoop()
答案 0 :(得分:0)
gluLookAt
不会重新调整您的观看量。它将平移和旋转您的所有点,但要扩展所需的一切投影矩阵。当您将对gluPerspective
的通话注释掉时,观看音量会在所有方向上从[ -1 , 1 ]延伸(因为投影矩阵是一个单位矩阵)。我想你已经发现当你将gluPerspective
和 gluLookAt
注释掉你的一组规范化数据点时([ 0 < / strong>, 1 ])填充大约1/4的视口(右上角)?
现在,至于gluLookAt
搞砸了,这也很容易解释。您在问题中显示的代码使用上述[ -1 , 1 ]查看量(标准化设备坐标)。 gluLookAt
将旋转并转换您的点,但它们仍然必须位于您的“视点”(前三个坐标传递到gluLookAt
)的+/- 1个单位内才能看到。当您使用 1 , 1 , 5 作为您的观点时,绝对不是这种情况。您的规范化数据点均不在z = [ 4 , 6 ]范围内。
gluLookAt(0.5,0.5,0.0, 0.5,0.5,1.0, 0.0,1.0,0.0)
将相机置于[ 0 , 1 ] X,Y范围中间,并将最近的点定位在近剪裁平面上。它向下看正Z轴并且Y轴朝上。