最 主要的是几个坐标系的变化矩阵的确定。网上很多资料的都是采用现场的矩阵库。此处使用numpy自定义矩阵。
几种坐标体系的直观图示及功能如下图,转自:https://learnopengl.com/Getting-started/Coordinate-Systems
此外使用python库,在调用opengl接口时,涉及到数据类型转换。例如
float_size = sizeof(c_float)
vertex_offset = c_void_p(0 * float_size)
等
# coding: utf-8
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import sys
from ctypes import sizeof, c_float, c_void_p, c_uint, string_at
from shader import *
import numpy, math
vertices=[
-0.5, -0.5, -0.5, 0.0, 0.0,0.3,
0.5, -0.5, -0.5, 1.0, 0.0,0.4,
0.5, 0.5, -0.5, 1.0, 1.0,0.5,
0.5, 0.5, -0.5, 1.0, 1.0,0.6,
-0.5, 0.5, -0.5, 0.0, 1.0,0.7,
-0.5, -0.5, -0.5, 0.0, 0.0,0.8,
-0.5, -0.5, 0.5, 0.0, 0.0,0.2,
0.5, -0.5, 0.5, 1.0, 0.0,0.4,
0.5, 0.5, 0.5, 1.0, 1.0,0.3,
0.5, 0.5, 0.5, 1.0, 1.0,0.6,
-0.5, 0.5, 0.5, 0.0, 1.0,0.8,
-0.5, -0.5, 0.5, 0.0, 0.0,1.0,
-0.5, 0.5, 0.5, 1.0, 0.0,1.0,
-0.5, 0.5, -0.5, 1.0, 1.0,0.3,
-0.5, -0.5, -0.5, 0.0, 1.0,0.4,
-0.5, -0.5, -0.5, 0.0, 1.0,0.7,
-0.5, -0.5, 0.5, 0.0, 0.0,0.7,
-0.5, 0.5, 0.5, 1.0, 0.0,0.7,
0.5, 0.5, 0.5, 1.0, 0.0,0.8,
0.5, 0.5, -0.5, 1.0, 1.0,0.8,
0.5, -0.5, -0.5, 0.0, 1.0,0.8,
0.5, -0.5, -0.5, 0.0, 1.0,0.8,
0.5, -0.5, 0.5, 0.0, 0.0,0.8,
0.5, 0.5, 0.5, 1.0, 0.0,0.8,
-0.5, -0.5, -0.5, 0.0, 1.0,0.9,
0.5, -0.5, -0.5, 1.0, 1.0,0.9,
0.5, -0.5, 0.5, 1.0, 0.0,0.9,
0.5, -0.5, 0.5, 1.0, 0.0,0.9,
-0.5, -0.5, 0.5, 0.0, 0.0,0.9,
-0.5, -0.5, -0.5, 0.0, 1.0,0.9,
-0.5, 0.5, -0.5, 0.0, 1.0,0.5,
0.5, 0.5, -0.5, 1.0, 1.0,0.5,
0.5, 0.5, 0.5, 1.0, 0.0,0.5,
0.5, 0.5, 0.5, 1.0, 0.0,0.5,
-0.5, 0.5, 0.5, 0.0, 0.0,0.5,
-0.5, 0.5, -0.5, 0.0, 1.0,0.5
]
screenWidth=512
screenHeight=512
cameraAngleX=218
cameraAngleY=10
zdistance=-0.2
mouseLeftDown=False
mouseRightDown=False
mouseX=0.0
mouseY=0.0
cameraDistance=1.7
def mydraw():
# clear
global cameraAngleX
global cameraAngleY
global zdistance
#cameraAngleX=-55+cameraAngleX
# zdistance=zdistance+0.1
# if (zdistance>0.9):
# zdistance=-0.9
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
sinx=math.sin(math.radians(cameraAngleX))
cosx=math.cos(math.radians(cameraAngleX))
siny=math.sin(math.radians(cameraAngleY))
cosy=math.cos(math.radians(cameraAngleY))
#model 变换,将各个顶点分别以Y轴和X轴进行旋转。将顶点左边由物体自身的坐标体系转变为世界坐标体系
modely = numpy.array([ cosy, 0.0, -siny,0.0,
0, 1.0, 0.0,0.0,
siny, 0, cosy, 0.0,
0.0, 0.0, 0.0, 1.0], numpy.float32)
modelx = numpy.array([ 1.0 ,0.0, -0.0,0.0,
0.0,cosx, -sinx, 0,
0.0, sinx, cosx, 0.0,
0.0, 0.0, 0.0, 1.0], numpy.float32)
project= numpy.array([ 1.0, 0.0,0.0, 0.0,
0.0, 1, 0, 0.0,
0.0, 0, -1/4, 0.0,
0.0, 0.0, 0.0, 1.0], numpy.float32)
#view 坐标转换,即物体离摄像机的远近。
view= numpy.array([ 1.0, 0.0,0.0, 0.0,
0.0, 1, 0, 0.0,
0.0, 0, 1, zdistance,
0.0, 0.0, 0.0, 1.0], numpy.float32)
project=project.reshape(4,4)
modelx=modelx.reshape(4,4)
modely=modely.reshape(4,4)
model=numpy.dot(modelx,modely)
view=view.reshape(4,4)
buffers = glGenBuffers(1)
float_size = sizeof(c_float)
vertex_offset = c_void_p(0 * float_size)
glBindBuffer(GL_ARRAY_BUFFER, buffers)
glBufferData(GL_ARRAY_BUFFER,
len(vertices)*4, # byte size
(ctypes.c_float*len(vertices))(*vertices),
GL_STATIC_DRAW)
glVertexAttribPointer(0,3,GL_FLOAT, False, 6 * float_size, vertex_offset)
glEnableVertexAttribArray(0)
color_offset = c_void_p(3 * float_size)
glVertexAttribPointer(1,3,GL_FLOAT, False, 6 * float_size, color_offset)
glEnableVertexAttribArray(1)
global shader
if shader==None:
shader=Shader()
shader.initShader('''
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 acolor;
out vec3 Color;
uniform mat4 matrix;
uniform mat4 view;
uniform mat4 project ;
void main()
{
gl_Position = project*view*matrix*vec4(aPos.x, aPos.y, aPos.z, 1);
Color=acolor;
}
''',
'''
out vec3 FragColor;
in vec3 Color;
void main()
{
FragColor =Color;
}
''')
shader.begin()
mvp_matrix_loc = glGetUniformLocation(shader.program, 'matrix' )
glUniformMatrix4fv(mvp_matrix_loc,1,GL_FALSE, model)
vp_matrix_loc = glGetUniformLocation(shader.program, 'view' )
glUniformMatrix4fv(vp_matrix_loc,1,GL_FALSE, view)
p_matrix_loc = glGetUniformLocation(shader.program, 'project' )
glUniformMatrix4fv(p_matrix_loc,1,GL_FALSE, project)
glDrawArrays(GL_TRIANGLES, 0,36)
shader.end()
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)
def disp_func():
mydraw()
glutSwapBuffers()
def timerCB(millisec):
glutTimerFunc(millisec, timerCB, millisec)
glutPostRedisplay()
# 鼠标事件的响应处理。获取光标的位置信息,并更新到model 变化矩阵中,借此更新顶点的世界坐标
def mouseCB( button, state, x, y):
global mouseX
global mouseY
mouseX = x
mouseY = y
global mouseLeftDown
if(button == GLUT_LEFT_BUTTON):
if(state == GLUT_DOWN):
mouseLeftDown = True
elif(state == GLUT_UP):
mouseLeftDown = False
elif(button == GLUT_RIGHT_BUTTON):
if(state == GLUT_DOWN):
mouseRightDown = True
elif(state == GLUT_UP):
mouseRightDown = False
def mouseMotionCB( x, y):
global cameraAngleX
global cameraAngleY
global mouseLeftDown
global mouseX
global mouseY
if(mouseLeftDown):
cameraAngleY += (x - mouseX)
cameraAngleX += (y - mouseY)
mouseX = x
mouseY = y
print(cameraAngleX)
if(mouseRightDown):
cameraDistance -= (y - mouseY) * 0.2
mouseY = y
if __name__=="__main__":
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH| GLUT_STENCIL)
glutInitWindowSize(screenWidth, screenHeight)
glutCreateWindow(b"vbo")
glutDisplayFunc(disp_func)
glutTimerFunc(330, timerCB, 330)
glutMouseFunc(mouseCB)
glutMotionFunc(mouseMotionCB)
glEnable(GL_DEPTH_TEST)
glutMainLoop()