Vertex/fragment 用于 OpenGL 第一人称射击游戏视图的着色器?
Vertex/fragment shaders for a OpenGL firsrt-person shooter view?
我的 objective 是导入地形图,更具体地说是 GeoTIFF 文件,并为地形指定颜色或纹理。我还希望能够使用按键输入和鼠标移动在地形中飞行。
输入数据:
self.vertices = numpy.array(顶点, dtype = 'f'): 顶点 = (x, y, z, r, g, b, tc1, tc2)
self.indices = numpy.array(三角形,dtype = numpy.int32):三角形=(顶点索引)
我为所有顶点颜色分配了 (1, 0, 0) 并为纹理坐标分配了 (0, 1)。这只是为了看颜色是否变红。
我做了什么:
我已经设法使用顶点数组对象 (VAO) 创建地形,其中包含顶点缓冲区对象 (VBO) 以及为顶点位置、颜色和纹理分配的属性(尚未分配)。我还设法设置了环境,以便能够使用按键输入和鼠标移动在地形中飞行。通过 运行 下面的代码应该能够看到一个带有黑色三角形轮廓的灰色小网格并在其周围飞行。
from pygame.constants import *
from OpenGL.GLU import *
import pygame
import numpy
numpy.set_printoptions(suppress=True)
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
class Meshi():
def __init__(self):
#Gert vertices and triangles
if not pygame.init():
raise TypeError('Unable to initalize pygame')
#Get vertices and triangles
vertices, triangles = self.getVertTri()
z_scale = 0.00005
#change z-scale
for i in range(0, len(vertices)):
if vertices[i][2] < 0:
vertices[i][2] = 0
else:
vertices[i][2] = vertices[i][2] * z_scale
#Add colour and texture coordinates to mesh
vert = []
color_in = [1.0, 0.0, 0.0, 0.0, 1.0]
for ver in vertices:
vert.append(ver + color_in)
vertices = vert
self.vertices = numpy.array(vertices, dtype = 'f')
self.indices = numpy.array(triangles,dtype = numpy.int32)
#Run pygame
self.pygame_view()
# Function that keeps all the vertices and triangle sides
def getVertTri(self):
vert_str=[[18.427083,-34.104583,14.097592],[18.427917,-34.104583,13.813885],[18.42875,-34.104583,11.798318],[18.429583,-34.104583,12.170123],[18.430417,-34.104583,13.23494],[18.43125,-34.104583,12.263627],[18.432083,-34.104583,10.543183],[18.432917,-34.104583,9.150859],[18.43375,-34.104583,7.531989],[18.434583,-34.104583,5.370541],[18.435417,-34.104583,4.947286],
[18.43625,-34.104583,4.369431],[18.437083,-34.104583,9.29184],[18.437917,-34.104583,11.300546],[18.43875,-34.104583,9.590596],[18.439583,-34.104583,7.006906],[18.427083,-34.105417,17.277378],[18.427917,-34.105417,12.070671],[18.42875,-34.105417,9.0447],[18.429583,-34.105417,7.853086],[18.430417,-34.105417,7.927739],[18.43125,-34.105417,8.325415],
[18.432083,-34.105417,8.505657],[18.432917,-34.105417,7.904904],[18.43375,-34.105417,7.7015],[18.434583,-34.105417,7.362363],[18.435417,-34.105417,7.08594],[18.43625,-34.105417,6.692467],[18.437083,-34.105417,1.177889],[18.437917,-34.105417,6.393278],[18.43875,-34.105417,8.610809],[18.439583,-34.105417,9.748986],[18.427083,-34.10625,29.354589],
[18.427917,-34.10625,24.616703],[18.42875,-34.10625,18.529903],[18.429583,-34.10625,13.677365],[18.430417,-34.10625,10.466432],[18.43125,-34.10625,9.469019],[18.432083,-34.10625,7.960031],[18.432917,-34.10625,7.115651],[18.43375,-34.10625,6.465553],[18.434583,-34.10625,5.50102],[18.435417,-34.10625,5.712739],[18.43625,-34.10625,6.946383],
[18.437083,-34.10625,4.263526],[18.437917,-34.10625,2.732419],[18.43875,-34.10625,5.488115],[18.439583,-34.10625,6.902328],[18.427083,-34.107083,30.979712],[18.427917,-34.107083,30.684374],[18.42875,-34.107083,26.90592],[18.429583,-34.107083,22.378777],[18.430417,-34.107083,19.191908],[18.43125,-34.107083,16.608807],[18.432083,-34.107083,13.171669],
[18.432917,-34.107083,10.77886],[18.43375,-34.107083,11.478356],[18.434583,-34.107083,11.300546],[18.435417,-34.107083,9.737173],[18.43625,-34.107083,6.484625],[18.437083,-34.107083,5.185645],[18.437917,-34.107083,3.770918],[18.43875,-34.107083,4.11032],[18.439583,-34.107083,4.947286],[18.427083,-34.107917,30.013678],[18.427917,-34.107917,32.894321],
[18.42875,-34.107917,31.857147],[18.429583,-34.107917,26.9683],[18.430417,-34.107917,21.895006],[18.43125,-34.107917,16.907623],[18.432083,-34.107917,12.721774],[18.432917,-34.107917,11.510896],[18.43375,-34.107917,14.044291],[18.434583,-34.107917,13.438006],[18.435417,-34.107917,12.538547],[18.43625,-34.107917,11.562454],[18.437083,-34.107917,9.263826],
[18.437917,-34.107917,6.071107],[18.43875,-34.107917,4.289905],[18.439583,-34.107917,4.057948],[18.427083,-34.10875,25.226519],[18.427917,-34.10875,26.609413],[18.42875,-34.10875,29.121534],[18.429583,-34.10875,27.900227],[18.430417,-34.10875,24.414494],[18.43125,-34.10875,20.20229],[18.432083,-34.10875,14.686948],[18.432917,-34.10875,10.620943],
[18.43375,-34.10875,11.136961],[18.434583,-34.10875,9.067697],[18.435417,-34.10875,9.031256],[18.43625,-34.10875,11.842289],[18.437083,-34.10875,14.412585],[18.437917,-34.10875,14.026602],[18.43875,-34.10875,10.77886],[18.439583,-34.10875,7.479022],[18.427083,-34.109583,24.316551],[18.427917,-34.109583,4.027079],[18.42875,-34.109583,13.726677],
[18.429583,-34.109583,23.883642],[18.430417,-34.109583,28.826719],[18.43125,-34.109583,29.248907],[18.432083,-34.109583,24.62047],[18.432917,-34.109583,14.576126],[18.43375,-34.109583,10.270979],[18.434583,-34.109583,9.1116],[18.435417,-34.109583,8.978557],[18.43625,-34.109583,10.877857],[18.437083,-34.109583,13.952817],[18.437917,-34.109583,17.318939],
[18.43875,-34.109583,18.3776],[18.439583,-34.109583,16.823097],[18.427083,-34.110417,31.066404],[18.427917,-34.110417,27.124994],[18.42875,-34.110417,14.584773],[18.429583,-34.110417,6.256494],[18.430417,-34.110417,14.902382],[18.43125,-34.110417,23.147758],[18.432083,-34.110417,26.993055],[18.432917,-34.110417,22.765322],[18.43375,-34.110417,17.905703],
[18.434583,-34.110417,13.544991],[18.435417,-34.110417,11.899844],[18.43625,-34.110417,14.348012],[18.437083,-34.110417,16.262051],[18.437917,-34.110417,17.542927],[18.43875,-34.110417,21.157032],[18.439583,-34.110417,23.491091],[18.427083,-34.11125,12.909849],[18.427917,-34.11125,20.651325],[18.42875,-34.11125,24.733046],[18.429583,-34.11125,22.71829],
[18.430417,-34.11125,12.409415],[18.43125,-34.11125,4.794024],[18.432083,-34.11125,14.560322],[18.432917,-34.11125,19.986332],[18.43375,-34.11125,21.261787],[18.434583,-34.11125,18.94504],[18.435417,-34.11125,17.467054],[18.43625,-34.11125,17.029078],[18.437083,-34.11125,15.266393],[18.437917,-34.11125,14.918492],[18.43875,-34.11125,16.444849],
[18.439583,-34.11125,18.332243],[18.427083,-34.112083,14.870467],[18.427917,-34.112083,10.946778],[18.42875,-34.112083,9.536969],[18.429583,-34.112083,17.428055],[18.430417,-34.112083,20.116079],[18.43125,-34.112083,14.013614],[18.432083,-34.112083,4.487359],[18.432917,-34.112083,4.302343],[18.43375,-34.112083,9.771387],[18.434583,-34.112083,11.65025],
[18.435417,-34.112083,11.8523],[18.43625,-34.112083,10.677254],[18.437083,-34.112083,8.148099],[18.437917,-34.112083,7.58765],[18.43875,-34.112083,5.033905],[18.439583,-34.112083,3.151809],[18.427083,-34.112917,4.697855],[18.427917,-34.112917,5.462211],[18.42875,-34.112917,6.136745],[18.429583,-34.112917,6.001783],[18.430417,-34.112917,9.035099],
[18.43125,-34.112917,13.059889],[18.432083,-34.112917,13.085486],[18.432917,-34.112917,11.08321],[18.43375,-34.112917,6.319217],[18.434583,-34.112917,4.270484],[18.435417,-34.112917,4.372147],[18.43625,-34.112917,4.910031],[18.437083,-34.112917,4.54907],[18.437917,-34.112917,3.606416],[18.43875,-34.112917,6.188358],[18.439583,-34.112917,10.144054],
[18.427083,-34.11375,8.589212],[18.427917,-34.11375,8.18161],[18.42875,-34.11375,7.444539],[18.429583,-34.11375,6.263077],[18.430417,-34.11375,5.025665],[18.43125,-34.11375,4.281593],[18.432083,-34.11375,4.90037],[18.432917,-34.11375,9.216936],[18.43375,-34.11375,10.723666],[18.434583,-34.11375,11.447696],[18.435417,-34.11375,11.056483],
[18.43625,-34.11375,10.136135],[18.437083,-34.11375,6.79003],[18.437917,-34.11375,2.968766],[18.43875,-34.11375,1.72892],[18.439583,-34.11375,6.459183]]
tri_str = [[0,16,17],[0,17,1],[1,17,18],[1,18,2],[2,18,19],[2,19,3],[3,19,20],[3,20,4],[4,20,21],[4,21,5],[5,21,22],
[5,22,6],[6,22,23],[6,23,7],[7,23,24],[7,24,8],[8,24,25],[8,25,9],[9,25,26],[9,26,10],[10,26,27],[10,27,11],
[11,27,28],[11,28,12],[12,28,29],[12,29,13],[13,29,30],[13,30,14],[14,30,31],[14,31,15],[16,32,33],[16,33,17],[17,33,34],
[17,34,18],[18,34,35],[18,35,19],[19,35,36],[19,36,20],[20,36,37],[20,37,21],[21,37,38],[21,38,22],[22,38,39],[22,39,23],
[23,39,40],[23,40,24],[24,40,41],[24,41,25],[25,41,42],[25,42,26],[26,42,43],[26,43,27],[27,43,44],[27,44,28],[28,44,45],
[28,45,29],[29,45,46],[29,46,30],[30,46,47],[30,47,31],[32,48,49],[32,49,33],[33,49,50],[33,50,34],[34,50,51],[34,51,35],
[35,51,52],[35,52,36],[36,52,53],[36,53,37],[37,53,54],[37,54,38],[38,54,55],[38,55,39],[39,55,56],[39,56,40],[40,56,57],
[40,57,41],[41,57,58],[41,58,42],[42,58,59],[42,59,43],[43,59,60],[43,60,44],[44,60,61],[44,61,45],[45,61,62],[45,62,46],
[46,62,63],[46,63,47],[48,64,65],[48,65,49],[49,65,66],[49,66,50],[50,66,67],[50,67,51],[51,67,68],[51,68,52],[52,68,69],
[52,69,53],[53,69,70],[53,70,54],[54,70,71],[54,71,55],[55,71,72],[55,72,56],[56,72,73],[56,73,57],[57,73,74],[57,74,58],
[58,74,75],[58,75,59],[59,75,76],[59,76,60],[60,76,77],[60,77,61],[61,77,78],[61,78,62],[62,78,79],[62,79,63],[64,80,81],
[64,81,65],[65,81,82],[65,82,66],[66,82,83],[66,83,67],[67,83,84],[67,84,68],[68,84,85],[68,85,69],[69,85,86],[69,86,70],
[70,86,87],[70,87,71],[71,87,88],[71,88,72],[72,88,89],[72,89,73],[73,89,90],[73,90,74],[74,90,91],[74,91,75],[75,91,92],
[75,92,76],[76,92,93],[76,93,77],[77,93,94],[77,94,78],[78,94,95],[78,95,79],[80,96,97],[80,97,81],[81,97,98],[81,98,82],
[82,98,99],[82,99,83],[83,99,100],[83,100,84],[84,100,101],[84,101,85],[85,101,102],[85,102,86],[86,102,103],[86,103,87],[87,103,104],
[87,104,88],[88,104,105],[88,105,89],[89,105,106],[89,106,90],[90,106,107],[90,107,91],[91,107,108],[91,108,92],[92,108,109],[92,109,93],
[93,109,110],[93,110,94],[94,110,111],[94,111,95],[96,112,113],[96,113,97],[97,113,114],[97,114,98],[98,114,115],[98,115,99],[99,115,116],
[99,116,100],[100,116,117],[100,117,101],[101,117,118],[101,118,102],[102,118,119],[102,119,103],[103,119,120],[103,120,104],[104,120,121],[104,121,105],
[105,121,122],[105,122,106],[106,122,123],[106,123,107],[107,123,124],[107,124,108],[108,124,125],[108,125,109],[109,125,126],[109,126,110],[110,126,127],
[110,127,111],[112,128,129],[112,129,113],[113,129,130],[113,130,114],[114,130,131],[114,131,115],[115,131,132],[115,132,116],[116,132,133],[116,133,117],
[117,133,134],[117,134,118],[118,134,135],[118,135,119],[119,135,136],[119,136,120],[120,136,137],[120,137,121],[121,137,138],[121,138,122],[122,138,139],
[122,139,123],[123,139,140],[123,140,124],[124,140,141],[124,141,125],[125,141,142],[125,142,126],[126,142,143],[126,143,127],[128,144,145],[128,145,129],
[129,145,146],[129,146,130],[130,146,147],[130,147,131],[131,147,148],[131,148,132],[132,148,149],[132,149,133],[133,149,150],[133,150,134],[134,150,151],
[134,151,135],[135,151,152],[135,152,136],[136,152,153],[136,153,137],[137,153,154],[137,154,138],[138,154,155],[138,155,139],[139,155,156],[139,156,140],
[140,156,157],[140,157,141],[141,157,158],[141,158,142],[142,158,159],[142,159,143],[144,160,161],[144,161,145],[145,161,162],[145,162,146],[146,162,163],
[146,163,147],[147,163,164],[147,164,148],[148,164,165],[148,165,149],[149,165,166],[149,166,150],[150,166,167],[150,167,151],[151,167,168],[151,168,152],
[152,168,169],[152,169,153],[153,169,170],[153,170,154],[154,170,171],[154,171,155],[155,171,172],[155,172,156],[156,172,173],[156,173,157],[157,173,174],
[157,174,158],[158,174,175],[158,175,159],[160,176,177],[160,177,161],[161,177,178],[161,178,162],[162,178,179],[162,179,163],[163,179,180],[163,180,164],
[164,180,181],[164,181,165],[165,181,182],[165,182,166],[166,182,183],[166,183,167],[167,183,184],[167,184,168],[168,184,185],[168,185,169],[169,185,186],
[169,186,170],[170,186,187],[170,187,171],[171,187,188],[171,188,172],[172,188,189],[172,189,173],[173,189,190],[173,190,174],[174,190,191],[174,191,175]]
return vert_str, tri_str
# Game movement
def key_pressed(self, keypress):
if keypress[pygame.K_w]:
glTranslatef(0, 0, 0.001)
if keypress[pygame.K_s]:
glTranslatef(0, 0, -0.001)
if keypress[pygame.K_d]:
glTranslatef(-0.00025, 0, 0)
if keypress[pygame.K_a]:
glTranslatef(0.00025, 0, 0)
if keypress[pygame.K_e]:
glTranslatef(0, 0.0004, 0)
if keypress[pygame.K_q]:
glTranslatef(0, -0.0004, 0)
def draw_mesh_vbo(self):
vertex_src = """
# version 330
in layout(location = 0) vec3 a_position;
in layout(location = 1) vec3 a_color;
out vec3 v_color;
void main()
{
gl_Position = vec4(a_position, 1.0);
v_color = a_color;
}
"""
fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
self.ter_vao = glGenVertexArrays(1)
glBindVertexArray(self.ter_vao)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.itemsize * len(self.vertices) * 8, self.vertices, GL_STATIC_DRAW)
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.itemsize * len(self.indices) * 3, self.indices, GL_STATIC_DRAW)
#pos = glGetAttribLocation(shader, "a_position")
# position
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(0))
# color
#col = glGetAttribLocation(shader, "a_color")
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(12))
# texture
#textr = glGetAttribLocation(shader, "a_text")
# glEnableVertexAttribArray(2)
# glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(24))
glBindVertexArray(0)
self.shady = shader
glClearColor(0, 0.3, 0.1, 1)
def pygame_loop(self, run, paused, displayCenter, up_down_angle, viewMatrix):
clock = pygame.time.Clock()
self.draw_mesh_vbo()
#glUseProgram(self.shader)
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
run = False
if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
paused = not paused
pygame.mouse.set_pos(displayCenter)
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
if not paused:
# get keys
keypress = pygame.key.get_pressed()
# init model view matrix
glLoadIdentity()
# apply the look up and down
up_down_angle += mouseMove[1] * 0.1
glRotatef(up_down_angle, 1.0, 0.0, 0.0)
# init the view matrix
glPushMatrix()
glLoadIdentity()
# apply the movment
self.key_pressed(keypress)
# apply the left and right rotation
glRotatef(mouseMove[0] * 0.02, 0.0, 1.0, 0.0)
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glPopMatrix()
# Close init the view matrix
# Update current view
glMultMatrixf(viewMatrix)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBindVertexArray(self.ter_vao)
#glUseProgram(self.shady)
glColor3f(0,0,0)
glDrawElements(GL_LINES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glColor4f(0.8, 0.8, 0.8, 0.0)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
#glUseProgram(0)
glBindVertexArray(0)
pygame.display.set_caption("FPS: %.2f" % clock.get_fps())
pygame.display.flip()
pygame.time.wait(20)
def pygame_view(self):
#Pygame Start
pygame.init()
#Create a "first person" environment
display = (1000, 600)
scree = pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1])
sphere = gluNewQuadric()
glMatrixMode(GL_PROJECTION)
gluPerspective(15, (1 * display[0] / display[1]), 0.001, 3000.0)
glMatrixMode(GL_MODELVIEW)
gluLookAt(self.vertices[50][0], self.vertices[50][1], 0, 0, -180, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)
up_down_angle = 0.0
paused = False
run = True
self.aspectratio = (1 * display[0] / display[1])
#Run Pygame
self.pygame_loop(run, paused, displayCenter, up_down_angle, viewMatrix)
pygame.quit()
if __name__ == '__main__':
mesh_dem = Meshi()
下一步:
在尝试实现纹理之前,我首先想了解着色器如何通过显示分配给每个顶点的颜色来工作。此示例中的预期结果是看到红色网格。
我尝试过的:
着色器设置:
vertex_src = """
# version 330
in layout(location = 0) vec3 a_position;
in layout(location = 1) vec3 a_color;
out vec3 v_color;
void main()
{
gl_Position = vec4(a_position, 1.0);
v_color = a_color;
}
"""
fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
self.shady = shader
在 while 循环中实现着色器:
glBindVertexArray(self.ter_vao)
glUseProgram(self.shady)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glUseProgram(0)
glBindVertexArray(0)
当我使用 glUseProgram(shader) 时,我只看到背景颜色。我怀疑这是因为 glUseProgram 禁用了模型视图、投影等。我是否必须更改着色器以包含投影、将 glUseProgram 放在其他地方或者我偏离了吗?
更新:
感谢 Python Youtube 系列中的 Rabbid76 和 Atilla Toth 的 OpenGL,我创建了一个可行的可编程管道示例(请参阅下面的答案)。我还没有实现 GLM 的矩阵转换,但现在 pyrr 工作正常。该示例根据坐标创建网格并根据高度显示不同的颜色。
如果您使用着色器程序,则矩阵变换必须在顶点着色器中完成。
Legacy OpenGL 矩阵堆栈已弃用。如果您使用着色器程序和遗留矩阵,那么您有
退回到 OpenGL Shading Language 1.20 (#version 120
) 着色器。
在此版本中,可以使用 gl_ModelViewProjectionMatrix
等内置制服。参见 Lighthouse3d.com - Hello World in GLSL。
例如:
# version 120
attribute vec3 a_position;
attribute vec3 a_color;
varying vec3 v_color;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_position, 1.0);
v_color = a_color;
}
但这不是 "modern" OpenGL。
在最先进的实现中,使用矩阵 Uniform 变量:
# version 330
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_color;
out vec3 v_color;
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
v_color = a_color;
}
位置索引glGetUniformLocation
of the uniform can be get by and the value of the matrix uniform can be set by glUniformMatrix4fv
。
使用像 PyGLM (this is a python wrapper for OpenGL Mathematics (GLM)) 这样的库来计算矩阵。
当然也可以使用 numpy.matrix
来计算矩阵。但这有点棘手。
感谢 Python Youtube 系列中的 Rabbid76 和 Atilla Toth 的 OpenGL,我创建了一个可行的可编程管道示例。我还没有实现 GLM 的矩阵转换,但现在 pyrr 工作正常。该示例根据坐标创建网格并根据高度显示不同的颜色。您还可以使用鼠标、w、s a、d、q、e 键四处飞行。
import numpy
import pandas
import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import pyrr
import glm
from pyrr import matrix44
from math import sin, cos, radians
class threeD_viewer():
def __init__(self, indi, tria, z_scale, x_st, y_st):
self.cam = Camera(x_st, y_st)
self.WIDTH, self.HEIGHT = 1280, 720
self.lastX, self.LastY = self.WIDTH / 2, self.HEIGHT / 2
self.first_mouse = True
self.forward, self.backward, self.right, self.left, self.up, self.down = False, False, False, False, False, False
self.x_start, self.y_start = x_st, y_st
vertices = indi
triangles = tria
z_values = []
for i in range(0, len(vertices)):
if vertices[i][2] < 0:
vertices[i][2] = 0
z_values.append(vertices[i][2])
else:
vertices[i][2] = vertices[i][2] * z_scale
z_values.append(vertices[i][2])
temp_z = vertices[i][2]
vertices[i][2] = vertices[i][1]
vertices[i][1] = temp_z
# Create a colour scheme to be based on height of the z axis
self.color_theme_1 = [[0.000, 0.000, 0.804], [0.678, 1.000, 0.184], [0.000, 1.000, 0.000],
[0.196, 0.804, 0.196], [1.000, 0.843, 0.000], [0.000, 0.392, 0.000]
, [0.804, 0.361, 0.361], [0.333, 0.420, 0.184]]
# Create heigth groups based on height quantiles
z_df = pandas.DataFrame(z_values, columns=["z_value"])
z_quant = z_df[z_df.z_value != 0].z_value.quantile([0.1, 0.3, 0.5, 0.75, 0.85, 0.9, 0.95, 0.98])
z_quant = z_quant.tolist()
# Add colour and texture to vertices
vert = []
for ver in vertices:
if ver[1] == 0:
color_in = self.color_theme_1[0] + [1.0, 0.0]
elif ver[1] < z_quant[0]:
color_in = self.color_theme_1[1] + [1.0, 0.0]
elif ver[1] < z_quant[1]:
color_in = self.color_theme_1[2] + [1.0, 0.0]
elif ver[1] < z_quant[2]:
color_in = self.color_theme_1[3] + [1.0, 0.0]
elif ver[1] < z_quant[3]:
color_in = self.color_theme_1[4] + [1.0, 0.0]
elif ver[1] < z_quant[4]:
color_in = self.color_theme_1[5] + [1.0, 0.0]
elif ver[1] < z_quant[5]:
color_in = self.color_theme_1[6] + [1.0, 0.0]
elif ver[1] < z_quant[6]:
color_in = self.color_theme_1[7] + [1.0, 0.0]
else:
vertices[i][1] = z_quant[6]
color_in = [0.502, 0.000, 0.000, 0.0, 0.1]
vert.append(ver + color_in)
# print(vert)
vertices = vert
self.vertices = numpy.array(vertices, dtype='f')
self.indices = numpy.array(triangles, dtype=numpy.int32)
self.vertex_src = """
# version 330
in vec3 a_position;
in vec3 a_color;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec3 v_color;
void main()
{
gl_Position = projection* view* vec4(a_position, 1.0);
v_color = a_color;
}
"""
self.fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
self.main()
# the keyboard input callback
def key_input_clb(self, window, key, scancode, action, mode):
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.set_window_should_close(window, True)
if key == glfw.KEY_W and action == glfw.PRESS:
self.forward = True
elif key == glfw.KEY_W and action == glfw.RELEASE:
self.forward = False
if key == glfw.KEY_S and action == glfw.PRESS:
self.backward = True
elif key == glfw.KEY_S and action == glfw.RELEASE:
self.backward = False
if key == glfw.KEY_A and action == glfw.PRESS:
self.left = True
elif key == glfw.KEY_A and action == glfw.RELEASE:
self.left = False
if key == glfw.KEY_D and action == glfw.PRESS:
self.right = True
elif key == glfw.KEY_D and action == glfw.RELEASE:
self.right = False
if key == glfw.KEY_Q and action == glfw.PRESS:
self.up = True
elif key == glfw.KEY_Q and action == glfw.RELEASE:
self.up = False
if key == glfw.KEY_E and action == glfw.PRESS:
self.down = True
elif key == glfw.KEY_E and action == glfw.RELEASE:
self.down = False
def do_movement(self):
if self.forward:
self.cam.process_keyboard("FORWARD", 0.000008)
if self.backward:
self.cam.process_keyboard("BACKWARD", 0.000008)
if self.right:
self.cam.process_keyboard("RIGHT", 0.000008)
if self.left:
self.cam.process_keyboard("LEFT", 0.000008)
if self.up:
self.cam.process_keyboard("UP", 0.000008)
if self.down:
self.cam.process_keyboard("DOWN", 0.000008)
def mmouse_look_clb(self, window, xpos, ypos):
if self.first_mouse:
self.lastX = xpos
self.lastY = ypos
self.first_mouse = False
xoffset = xpos - self.lastX
yoffset = self.lastY - ypos
self.lastX = xpos
self.lastY = ypos
self.cam.process_mouse_movement(xoffset, yoffset)
def window_resize(self, window, width, height):
glViewport(0, 0, width, height)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, width / height, 0.0001, 100)
proj_loc = glGetUniformLocation(self.shader, "projection")
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
def main(self):
# initializing glfw library
if not glfw.init():
raise Exception("glfw can not be initialized!")
# creating the window
window = glfw.create_window(self.WIDTH, self.HEIGHT, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
# set window's position
glfw.set_window_pos(window, 400, 200)
# set the callback function for window resize
glfw.set_window_size_callback(window, self.window_resize)
glfw.set_cursor_pos_callback(window, self.mmouse_look_clb)
glfw.set_input_mode(window, glfw.CURSOR, glfw.CURSOR_DISABLED)
glfw.set_key_callback(window, self.key_input_clb)
#glfw.set_cursor_enter_callback(window, self.mouse_enter_clb)
# make the context current
glfw.make_context_current(window)
self.shader = compileProgram(compileShader(self.vertex_src, GL_VERTEX_SHADER),
compileShader(self.fragment_src, GL_FRAGMENT_SHADER))
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
# Vertex Buffer Object
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
# Element Buffer Object
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(0))
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(24))
glBindVertexArray(0)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
projection_2 = glm.perspective(45, self.WIDTH / self.HEIGHT, 0.001, 3000)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, self.WIDTH / self.HEIGHT, 0.0001, 100)
# print(projection_2)
# print(projection)
glUseProgram(self.shader)
model_loc = glGetUniformLocation(self.shader, "model")
proj_loc = glGetUniformLocation(self.shader, "projection")
view_loc = glGetUniformLocation(self.shader, "view")
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
# the main application loop
while not glfw.window_should_close(window):
glfw.poll_events()
self.do_movement()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
view = self.cam.get_view_matrix()
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glBindVertexArray(VAO)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glBindVertexArray(0)
glfw.swap_buffers(window)
# terminate glfw, free up allocated resources
glfw.terminate()
class Camera:
def __init__(self, xstart, ystart):
self.camera_pos = glm.vec3(xstart+0.005, 0.002, ystart+0.01)
self.camera_front = glm.vec3(0.0, 0.0, -200.0)
self.camera_up = glm.vec3(0.0, 1.0, 0.0)
self.camera_right = glm.vec3(1.0, 0.0, 0.0)
self.mouse_sensitivity = 0.25
self.jaw = -90.0
self.pitch = 0.0
def get_view_matrix(self):
return matrix44.create_look_at(self.camera_pos, self.camera_pos + self.camera_front, self.camera_up)
def process_mouse_movement(self, xoffset, yoffset, constrain_pitch=True):
xoffset *= self.mouse_sensitivity
yoffset *= self.mouse_sensitivity
self.jaw += xoffset
self.pitch += yoffset
if constrain_pitch:
if self.pitch > 45:
self.pitch = 45
if self.pitch < -45:
self.pitch = -45
self.update_camera_vectors()
def update_camera_vectors(self):
front = glm.vec3(0.0, 0.0, 0.0)
front.x = cos(radians(self.jaw)) * cos(radians(self.pitch))
front.y = sin(radians(self.pitch))
front.z = sin(radians(self.jaw)) * cos(radians(self.pitch))
self.camera_front = glm.normalize(front)
self.camera_right = glm.normalize(glm.cross(self.camera_front, glm.vec3(0.0, 1.0, 0.0)))
#self.camera_up = glm.normalize(glm.cross(self.camera_right, self.camera_front))
# Camera method for the WASD movement
def process_keyboard(self, direction, velocity):
if direction == "FORWARD":
self.camera_pos += self.camera_front * velocity
if direction == "BACKWARD":
self.camera_pos -= self.camera_front * velocity
if direction == "LEFT":
self.camera_pos -= self.camera_right * velocity
if direction == "RIGHT":
self.camera_pos += self.camera_right * velocity
if direction == "UP":
self.camera_pos += self.camera_up * velocity
if direction == "DOWN":
self.camera_pos -= self.camera_up * velocity
vertices = [[18.427083, -34.104583, 14.097592], [18.427917, -34.104583, 13.813885],
[18.42875, -34.104583, 11.798318], [18.429583, -34.104583, 12.170123],
[18.430417, -34.104583, 13.23494], [18.43125, -34.104583, 12.263627],
[18.432083, -34.104583, 10.543183], [18.432917, -34.104583, 9.150859],
[18.43375, -34.104583, 7.531989], [18.434583, -34.104583, 5.370541],
[18.435417, -34.104583, 4.947286],
[18.43625, -34.104583, 4.369431], [18.437083, -34.104583, 9.29184],
[18.437917, -34.104583, 11.300546], [18.43875, -34.104583, 9.590596],
[18.439583, -34.104583, 7.006906], [18.427083, -34.105417, 17.277378],
[18.427917, -34.105417, 12.070671], [18.42875, -34.105417, 9.0447],
[18.429583, -34.105417, 7.853086], [18.430417, -34.105417, 7.927739],
[18.43125, -34.105417, 8.325415],
[18.432083, -34.105417, 8.505657], [18.432917, -34.105417, 7.904904],
[18.43375, -34.105417, 7.7015], [18.434583, -34.105417, 7.362363], [18.435417, -34.105417, 7.08594],
[18.43625, -34.105417, 6.692467], [18.437083, -34.105417, 1.177889],
[18.437917, -34.105417, 6.393278], [18.43875, -34.105417, 8.610809],
[18.439583, -34.105417, 9.748986], [18.427083, -34.10625, 29.354589],
[18.427917, -34.10625, 24.616703], [18.42875, -34.10625, 18.529903],
[18.429583, -34.10625, 13.677365], [18.430417, -34.10625, 10.466432],
[18.43125, -34.10625, 9.469019], [18.432083, -34.10625, 7.960031], [18.432917, -34.10625, 7.115651],
[18.43375, -34.10625, 6.465553], [18.434583, -34.10625, 5.50102], [18.435417, -34.10625, 5.712739],
[18.43625, -34.10625, 6.946383],
[18.437083, -34.10625, 4.263526], [18.437917, -34.10625, 2.732419], [18.43875, -34.10625, 5.488115],
[18.439583, -34.10625, 6.902328], [18.427083, -34.107083, 30.979712],
[18.427917, -34.107083, 30.684374], [18.42875, -34.107083, 26.90592],
[18.429583, -34.107083, 22.378777], [18.430417, -34.107083, 19.191908],
[18.43125, -34.107083, 16.608807], [18.432083, -34.107083, 13.171669],
[18.432917, -34.107083, 10.77886], [18.43375, -34.107083, 11.478356],
[18.434583, -34.107083, 11.300546], [18.435417, -34.107083, 9.737173],
[18.43625, -34.107083, 6.484625], [18.437083, -34.107083, 5.185645],
[18.437917, -34.107083, 3.770918], [18.43875, -34.107083, 4.11032],
[18.439583, -34.107083, 4.947286], [18.427083, -34.107917, 30.013678],
[18.427917, -34.107917, 32.894321],
[18.42875, -34.107917, 31.857147], [18.429583, -34.107917, 26.9683],
[18.430417, -34.107917, 21.895006], [18.43125, -34.107917, 16.907623],
[18.432083, -34.107917, 12.721774], [18.432917, -34.107917, 11.510896],
[18.43375, -34.107917, 14.044291], [18.434583, -34.107917, 13.438006],
[18.435417, -34.107917, 12.538547], [18.43625, -34.107917, 11.562454],
[18.437083, -34.107917, 9.263826],
[18.437917, -34.107917, 6.071107], [18.43875, -34.107917, 4.289905],
[18.439583, -34.107917, 4.057948], [18.427083, -34.10875, 25.226519],
[18.427917, -34.10875, 26.609413], [18.42875, -34.10875, 29.121534],
[18.429583, -34.10875, 27.900227], [18.430417, -34.10875, 24.414494],
[18.43125, -34.10875, 20.20229], [18.432083, -34.10875, 14.686948],
[18.432917, -34.10875, 10.620943],
[18.43375, -34.10875, 11.136961], [18.434583, -34.10875, 9.067697],
[18.435417, -34.10875, 9.031256], [18.43625, -34.10875, 11.842289],
[18.437083, -34.10875, 14.412585], [18.437917, -34.10875, 14.026602],
[18.43875, -34.10875, 10.77886], [18.439583, -34.10875, 7.479022],
[18.427083, -34.109583, 24.316551], [18.427917, -34.109583, 4.027079],
[18.42875, -34.109583, 13.726677],
[18.429583, -34.109583, 23.883642], [18.430417, -34.109583, 28.826719],
[18.43125, -34.109583, 29.248907], [18.432083, -34.109583, 24.62047],
[18.432917, -34.109583, 14.576126], [18.43375, -34.109583, 10.270979],
[18.434583, -34.109583, 9.1116], [18.435417, -34.109583, 8.978557],
[18.43625, -34.109583, 10.877857], [18.437083, -34.109583, 13.952817],
[18.437917, -34.109583, 17.318939],
[18.43875, -34.109583, 18.3776], [18.439583, -34.109583, 16.823097],
[18.427083, -34.110417, 31.066404], [18.427917, -34.110417, 27.124994],
[18.42875, -34.110417, 14.584773], [18.429583, -34.110417, 6.256494],
[18.430417, -34.110417, 14.902382], [18.43125, -34.110417, 23.147758],
[18.432083, -34.110417, 26.993055], [18.432917, -34.110417, 22.765322],
[18.43375, -34.110417, 17.905703],
[18.434583, -34.110417, 13.544991], [18.435417, -34.110417, 11.899844],
[18.43625, -34.110417, 14.348012], [18.437083, -34.110417, 16.262051],
[18.437917, -34.110417, 17.542927], [18.43875, -34.110417, 21.157032],
[18.439583, -34.110417, 23.491091], [18.427083, -34.11125, 12.909849],
[18.427917, -34.11125, 20.651325], [18.42875, -34.11125, 24.733046],
[18.429583, -34.11125, 22.71829],
[18.430417, -34.11125, 12.409415], [18.43125, -34.11125, 4.794024],
[18.432083, -34.11125, 14.560322], [18.432917, -34.11125, 19.986332],
[18.43375, -34.11125, 21.261787], [18.434583, -34.11125, 18.94504],
[18.435417, -34.11125, 17.467054], [18.43625, -34.11125, 17.029078],
[18.437083, -34.11125, 15.266393], [18.437917, -34.11125, 14.918492],
[18.43875, -34.11125, 16.444849],
[18.439583, -34.11125, 18.332243], [18.427083, -34.112083, 14.870467],
[18.427917, -34.112083, 10.946778], [18.42875, -34.112083, 9.536969],
[18.429583, -34.112083, 17.428055], [18.430417, -34.112083, 20.116079],
[18.43125, -34.112083, 14.013614], [18.432083, -34.112083, 4.487359],
[18.432917, -34.112083, 4.302343], [18.43375, -34.112083, 9.771387],
[18.434583, -34.112083, 11.65025],
[18.435417, -34.112083, 11.8523], [18.43625, -34.112083, 10.677254],
[18.437083, -34.112083, 8.148099], [18.437917, -34.112083, 7.58765],
[18.43875, -34.112083, 5.033905], [18.439583, -34.112083, 3.151809],
[18.427083, -34.112917, 4.697855], [18.427917, -34.112917, 5.462211],
[18.42875, -34.112917, 6.136745], [18.429583, -34.112917, 6.001783],
[18.430417, -34.112917, 9.035099],
[18.43125, -34.112917, 13.059889], [18.432083, -34.112917, 13.085486],
[18.432917, -34.112917, 11.08321], [18.43375, -34.112917, 6.319217],
[18.434583, -34.112917, 4.270484], [18.435417, -34.112917, 4.372147],
[18.43625, -34.112917, 4.910031], [18.437083, -34.112917, 4.54907],
[18.437917, -34.112917, 3.606416], [18.43875, -34.112917, 6.188358],
[18.439583, -34.112917, 10.144054],
[18.427083, -34.11375, 8.589212], [18.427917, -34.11375, 8.18161], [18.42875, -34.11375, 7.444539],
[18.429583, -34.11375, 6.263077], [18.430417, -34.11375, 5.025665], [18.43125, -34.11375, 4.281593],
[18.432083, -34.11375, 4.90037], [18.432917, -34.11375, 9.216936], [18.43375, -34.11375, 10.723666],
[18.434583, -34.11375, 11.447696], [18.435417, -34.11375, 11.056483],
[18.43625, -34.11375, 10.136135], [18.437083, -34.11375, 6.79003], [18.437917, -34.11375, 2.968766],
[18.43875, -34.11375, 1.72892], [18.439583, -34.11375, 6.459183]]
triangles = [[0, 16, 17], [0, 17, 1], [1, 17, 18], [1, 18, 2], [2, 18, 19], [2, 19, 3], [3, 19, 20], [3, 20, 4],
[4, 20, 21], [4, 21, 5], [5, 21, 22],
[5, 22, 6], [6, 22, 23], [6, 23, 7], [7, 23, 24], [7, 24, 8], [8, 24, 25], [8, 25, 9], [9, 25, 26],
[9, 26, 10], [10, 26, 27], [10, 27, 11],
[11, 27, 28], [11, 28, 12], [12, 28, 29], [12, 29, 13], [13, 29, 30], [13, 30, 14], [14, 30, 31],
[14, 31, 15], [16, 32, 33], [16, 33, 17], [17, 33, 34],
[17, 34, 18], [18, 34, 35], [18, 35, 19], [19, 35, 36], [19, 36, 20], [20, 36, 37], [20, 37, 21],
[21, 37, 38], [21, 38, 22], [22, 38, 39], [22, 39, 23],
[23, 39, 40], [23, 40, 24], [24, 40, 41], [24, 41, 25], [25, 41, 42], [25, 42, 26], [26, 42, 43],
[26, 43, 27], [27, 43, 44], [27, 44, 28], [28, 44, 45],
[28, 45, 29], [29, 45, 46], [29, 46, 30], [30, 46, 47], [30, 47, 31], [32, 48, 49], [32, 49, 33],
[33, 49, 50], [33, 50, 34], [34, 50, 51], [34, 51, 35],
[35, 51, 52], [35, 52, 36], [36, 52, 53], [36, 53, 37], [37, 53, 54], [37, 54, 38], [38, 54, 55],
[38, 55, 39], [39, 55, 56], [39, 56, 40], [40, 56, 57],
[40, 57, 41], [41, 57, 58], [41, 58, 42], [42, 58, 59], [42, 59, 43], [43, 59, 60], [43, 60, 44],
[44, 60, 61], [44, 61, 45], [45, 61, 62], [45, 62, 46],
[46, 62, 63], [46, 63, 47], [48, 64, 65], [48, 65, 49], [49, 65, 66], [49, 66, 50], [50, 66, 67],
[50, 67, 51], [51, 67, 68], [51, 68, 52], [52, 68, 69],
[52, 69, 53], [53, 69, 70], [53, 70, 54], [54, 70, 71], [54, 71, 55], [55, 71, 72], [55, 72, 56],
[56, 72, 73], [56, 73, 57], [57, 73, 74], [57, 74, 58],
[58, 74, 75], [58, 75, 59], [59, 75, 76], [59, 76, 60], [60, 76, 77], [60, 77, 61], [61, 77, 78],
[61, 78, 62], [62, 78, 79], [62, 79, 63], [64, 80, 81],
[64, 81, 65], [65, 81, 82], [65, 82, 66], [66, 82, 83], [66, 83, 67], [67, 83, 84], [67, 84, 68],
[68, 84, 85], [68, 85, 69], [69, 85, 86], [69, 86, 70],
[70, 86, 87], [70, 87, 71], [71, 87, 88], [71, 88, 72], [72, 88, 89], [72, 89, 73], [73, 89, 90],
[73, 90, 74], [74, 90, 91], [74, 91, 75], [75, 91, 92],
[75, 92, 76], [76, 92, 93], [76, 93, 77], [77, 93, 94], [77, 94, 78], [78, 94, 95], [78, 95, 79],
[80, 96, 97], [80, 97, 81], [81, 97, 98], [81, 98, 82],
[82, 98, 99], [82, 99, 83], [83, 99, 100], [83, 100, 84], [84, 100, 101], [84, 101, 85],
[85, 101, 102], [85, 102, 86], [86, 102, 103], [86, 103, 87], [87, 103, 104],
[87, 104, 88], [88, 104, 105], [88, 105, 89], [89, 105, 106], [89, 106, 90], [90, 106, 107],
[90, 107, 91], [91, 107, 108], [91, 108, 92], [92, 108, 109], [92, 109, 93],
[93, 109, 110], [93, 110, 94], [94, 110, 111], [94, 111, 95], [96, 112, 113], [96, 113, 97],
[97, 113, 114], [97, 114, 98], [98, 114, 115], [98, 115, 99], [99, 115, 116],
[99, 116, 100], [100, 116, 117], [100, 117, 101], [101, 117, 118], [101, 118, 102], [102, 118, 119],
[102, 119, 103], [103, 119, 120], [103, 120, 104], [104, 120, 121], [104, 121, 105],
[105, 121, 122], [105, 122, 106], [106, 122, 123], [106, 123, 107], [107, 123, 124], [107, 124, 108],
[108, 124, 125], [108, 125, 109], [109, 125, 126], [109, 126, 110], [110, 126, 127],
[110, 127, 111], [112, 128, 129], [112, 129, 113], [113, 129, 130], [113, 130, 114], [114, 130, 131],
[114, 131, 115], [115, 131, 132], [115, 132, 116], [116, 132, 133], [116, 133, 117],
[117, 133, 134], [117, 134, 118], [118, 134, 135], [118, 135, 119], [119, 135, 136], [119, 136, 120],
[120, 136, 137], [120, 137, 121], [121, 137, 138], [121, 138, 122], [122, 138, 139],
[122, 139, 123], [123, 139, 140], [123, 140, 124], [124, 140, 141], [124, 141, 125], [125, 141, 142],
[125, 142, 126], [126, 142, 143], [126, 143, 127], [128, 144, 145], [128, 145, 129],
[129, 145, 146], [129, 146, 130], [130, 146, 147], [130, 147, 131], [131, 147, 148], [131, 148, 132],
[132, 148, 149], [132, 149, 133], [133, 149, 150], [133, 150, 134], [134, 150, 151],
[134, 151, 135], [135, 151, 152], [135, 152, 136], [136, 152, 153], [136, 153, 137], [137, 153, 154],
[137, 154, 138], [138, 154, 155], [138, 155, 139], [139, 155, 156], [139, 156, 140],
[140, 156, 157], [140, 157, 141], [141, 157, 158], [141, 158, 142], [142, 158, 159], [142, 159, 143],
[144, 160, 161], [144, 161, 145], [145, 161, 162], [145, 162, 146], [146, 162, 163],
[146, 163, 147], [147, 163, 164], [147, 164, 148], [148, 164, 165], [148, 165, 149], [149, 165, 166],
[149, 166, 150], [150, 166, 167], [150, 167, 151], [151, 167, 168], [151, 168, 152],
[152, 168, 169], [152, 169, 153], [153, 169, 170], [153, 170, 154], [154, 170, 171], [154, 171, 155],
[155, 171, 172], [155, 172, 156], [156, 172, 173], [156, 173, 157], [157, 173, 174],
[157, 174, 158], [158, 174, 175], [158, 175, 159], [160, 176, 177], [160, 177, 161], [161, 177, 178],
[161, 178, 162], [162, 178, 179], [162, 179, 163], [163, 179, 180], [163, 180, 164],
[164, 180, 181], [164, 181, 165], [165, 181, 182], [165, 182, 166], [166, 182, 183], [166, 183, 167],
[167, 183, 184], [167, 184, 168], [168, 184, 185], [168, 185, 169], [169, 185, 186],
[169, 186, 170], [170, 186, 187], [170, 187, 171], [171, 187, 188], [171, 188, 172], [172, 188, 189],
[172, 189, 173], [173, 189, 190], [173, 190, 174], [174, 190, 191], [174, 191, 175]]
Z_scale = 0.00005
xStart = vertices[0][0]
yStart = vertices[0][1]
threeD_viewer(vertices, triangles, Z_scale, xStart, yStart)
我的 objective 是导入地形图,更具体地说是 GeoTIFF 文件,并为地形指定颜色或纹理。我还希望能够使用按键输入和鼠标移动在地形中飞行。
输入数据:
self.vertices = numpy.array(顶点, dtype = 'f'): 顶点 = (x, y, z, r, g, b, tc1, tc2)
self.indices = numpy.array(三角形,dtype = numpy.int32):三角形=(顶点索引)
我为所有顶点颜色分配了 (1, 0, 0) 并为纹理坐标分配了 (0, 1)。这只是为了看颜色是否变红。
我做了什么:
我已经设法使用顶点数组对象 (VAO) 创建地形,其中包含顶点缓冲区对象 (VBO) 以及为顶点位置、颜色和纹理分配的属性(尚未分配)。我还设法设置了环境,以便能够使用按键输入和鼠标移动在地形中飞行。通过 运行 下面的代码应该能够看到一个带有黑色三角形轮廓的灰色小网格并在其周围飞行。
from pygame.constants import *
from OpenGL.GLU import *
import pygame
import numpy
numpy.set_printoptions(suppress=True)
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
class Meshi():
def __init__(self):
#Gert vertices and triangles
if not pygame.init():
raise TypeError('Unable to initalize pygame')
#Get vertices and triangles
vertices, triangles = self.getVertTri()
z_scale = 0.00005
#change z-scale
for i in range(0, len(vertices)):
if vertices[i][2] < 0:
vertices[i][2] = 0
else:
vertices[i][2] = vertices[i][2] * z_scale
#Add colour and texture coordinates to mesh
vert = []
color_in = [1.0, 0.0, 0.0, 0.0, 1.0]
for ver in vertices:
vert.append(ver + color_in)
vertices = vert
self.vertices = numpy.array(vertices, dtype = 'f')
self.indices = numpy.array(triangles,dtype = numpy.int32)
#Run pygame
self.pygame_view()
# Function that keeps all the vertices and triangle sides
def getVertTri(self):
vert_str=[[18.427083,-34.104583,14.097592],[18.427917,-34.104583,13.813885],[18.42875,-34.104583,11.798318],[18.429583,-34.104583,12.170123],[18.430417,-34.104583,13.23494],[18.43125,-34.104583,12.263627],[18.432083,-34.104583,10.543183],[18.432917,-34.104583,9.150859],[18.43375,-34.104583,7.531989],[18.434583,-34.104583,5.370541],[18.435417,-34.104583,4.947286],
[18.43625,-34.104583,4.369431],[18.437083,-34.104583,9.29184],[18.437917,-34.104583,11.300546],[18.43875,-34.104583,9.590596],[18.439583,-34.104583,7.006906],[18.427083,-34.105417,17.277378],[18.427917,-34.105417,12.070671],[18.42875,-34.105417,9.0447],[18.429583,-34.105417,7.853086],[18.430417,-34.105417,7.927739],[18.43125,-34.105417,8.325415],
[18.432083,-34.105417,8.505657],[18.432917,-34.105417,7.904904],[18.43375,-34.105417,7.7015],[18.434583,-34.105417,7.362363],[18.435417,-34.105417,7.08594],[18.43625,-34.105417,6.692467],[18.437083,-34.105417,1.177889],[18.437917,-34.105417,6.393278],[18.43875,-34.105417,8.610809],[18.439583,-34.105417,9.748986],[18.427083,-34.10625,29.354589],
[18.427917,-34.10625,24.616703],[18.42875,-34.10625,18.529903],[18.429583,-34.10625,13.677365],[18.430417,-34.10625,10.466432],[18.43125,-34.10625,9.469019],[18.432083,-34.10625,7.960031],[18.432917,-34.10625,7.115651],[18.43375,-34.10625,6.465553],[18.434583,-34.10625,5.50102],[18.435417,-34.10625,5.712739],[18.43625,-34.10625,6.946383],
[18.437083,-34.10625,4.263526],[18.437917,-34.10625,2.732419],[18.43875,-34.10625,5.488115],[18.439583,-34.10625,6.902328],[18.427083,-34.107083,30.979712],[18.427917,-34.107083,30.684374],[18.42875,-34.107083,26.90592],[18.429583,-34.107083,22.378777],[18.430417,-34.107083,19.191908],[18.43125,-34.107083,16.608807],[18.432083,-34.107083,13.171669],
[18.432917,-34.107083,10.77886],[18.43375,-34.107083,11.478356],[18.434583,-34.107083,11.300546],[18.435417,-34.107083,9.737173],[18.43625,-34.107083,6.484625],[18.437083,-34.107083,5.185645],[18.437917,-34.107083,3.770918],[18.43875,-34.107083,4.11032],[18.439583,-34.107083,4.947286],[18.427083,-34.107917,30.013678],[18.427917,-34.107917,32.894321],
[18.42875,-34.107917,31.857147],[18.429583,-34.107917,26.9683],[18.430417,-34.107917,21.895006],[18.43125,-34.107917,16.907623],[18.432083,-34.107917,12.721774],[18.432917,-34.107917,11.510896],[18.43375,-34.107917,14.044291],[18.434583,-34.107917,13.438006],[18.435417,-34.107917,12.538547],[18.43625,-34.107917,11.562454],[18.437083,-34.107917,9.263826],
[18.437917,-34.107917,6.071107],[18.43875,-34.107917,4.289905],[18.439583,-34.107917,4.057948],[18.427083,-34.10875,25.226519],[18.427917,-34.10875,26.609413],[18.42875,-34.10875,29.121534],[18.429583,-34.10875,27.900227],[18.430417,-34.10875,24.414494],[18.43125,-34.10875,20.20229],[18.432083,-34.10875,14.686948],[18.432917,-34.10875,10.620943],
[18.43375,-34.10875,11.136961],[18.434583,-34.10875,9.067697],[18.435417,-34.10875,9.031256],[18.43625,-34.10875,11.842289],[18.437083,-34.10875,14.412585],[18.437917,-34.10875,14.026602],[18.43875,-34.10875,10.77886],[18.439583,-34.10875,7.479022],[18.427083,-34.109583,24.316551],[18.427917,-34.109583,4.027079],[18.42875,-34.109583,13.726677],
[18.429583,-34.109583,23.883642],[18.430417,-34.109583,28.826719],[18.43125,-34.109583,29.248907],[18.432083,-34.109583,24.62047],[18.432917,-34.109583,14.576126],[18.43375,-34.109583,10.270979],[18.434583,-34.109583,9.1116],[18.435417,-34.109583,8.978557],[18.43625,-34.109583,10.877857],[18.437083,-34.109583,13.952817],[18.437917,-34.109583,17.318939],
[18.43875,-34.109583,18.3776],[18.439583,-34.109583,16.823097],[18.427083,-34.110417,31.066404],[18.427917,-34.110417,27.124994],[18.42875,-34.110417,14.584773],[18.429583,-34.110417,6.256494],[18.430417,-34.110417,14.902382],[18.43125,-34.110417,23.147758],[18.432083,-34.110417,26.993055],[18.432917,-34.110417,22.765322],[18.43375,-34.110417,17.905703],
[18.434583,-34.110417,13.544991],[18.435417,-34.110417,11.899844],[18.43625,-34.110417,14.348012],[18.437083,-34.110417,16.262051],[18.437917,-34.110417,17.542927],[18.43875,-34.110417,21.157032],[18.439583,-34.110417,23.491091],[18.427083,-34.11125,12.909849],[18.427917,-34.11125,20.651325],[18.42875,-34.11125,24.733046],[18.429583,-34.11125,22.71829],
[18.430417,-34.11125,12.409415],[18.43125,-34.11125,4.794024],[18.432083,-34.11125,14.560322],[18.432917,-34.11125,19.986332],[18.43375,-34.11125,21.261787],[18.434583,-34.11125,18.94504],[18.435417,-34.11125,17.467054],[18.43625,-34.11125,17.029078],[18.437083,-34.11125,15.266393],[18.437917,-34.11125,14.918492],[18.43875,-34.11125,16.444849],
[18.439583,-34.11125,18.332243],[18.427083,-34.112083,14.870467],[18.427917,-34.112083,10.946778],[18.42875,-34.112083,9.536969],[18.429583,-34.112083,17.428055],[18.430417,-34.112083,20.116079],[18.43125,-34.112083,14.013614],[18.432083,-34.112083,4.487359],[18.432917,-34.112083,4.302343],[18.43375,-34.112083,9.771387],[18.434583,-34.112083,11.65025],
[18.435417,-34.112083,11.8523],[18.43625,-34.112083,10.677254],[18.437083,-34.112083,8.148099],[18.437917,-34.112083,7.58765],[18.43875,-34.112083,5.033905],[18.439583,-34.112083,3.151809],[18.427083,-34.112917,4.697855],[18.427917,-34.112917,5.462211],[18.42875,-34.112917,6.136745],[18.429583,-34.112917,6.001783],[18.430417,-34.112917,9.035099],
[18.43125,-34.112917,13.059889],[18.432083,-34.112917,13.085486],[18.432917,-34.112917,11.08321],[18.43375,-34.112917,6.319217],[18.434583,-34.112917,4.270484],[18.435417,-34.112917,4.372147],[18.43625,-34.112917,4.910031],[18.437083,-34.112917,4.54907],[18.437917,-34.112917,3.606416],[18.43875,-34.112917,6.188358],[18.439583,-34.112917,10.144054],
[18.427083,-34.11375,8.589212],[18.427917,-34.11375,8.18161],[18.42875,-34.11375,7.444539],[18.429583,-34.11375,6.263077],[18.430417,-34.11375,5.025665],[18.43125,-34.11375,4.281593],[18.432083,-34.11375,4.90037],[18.432917,-34.11375,9.216936],[18.43375,-34.11375,10.723666],[18.434583,-34.11375,11.447696],[18.435417,-34.11375,11.056483],
[18.43625,-34.11375,10.136135],[18.437083,-34.11375,6.79003],[18.437917,-34.11375,2.968766],[18.43875,-34.11375,1.72892],[18.439583,-34.11375,6.459183]]
tri_str = [[0,16,17],[0,17,1],[1,17,18],[1,18,2],[2,18,19],[2,19,3],[3,19,20],[3,20,4],[4,20,21],[4,21,5],[5,21,22],
[5,22,6],[6,22,23],[6,23,7],[7,23,24],[7,24,8],[8,24,25],[8,25,9],[9,25,26],[9,26,10],[10,26,27],[10,27,11],
[11,27,28],[11,28,12],[12,28,29],[12,29,13],[13,29,30],[13,30,14],[14,30,31],[14,31,15],[16,32,33],[16,33,17],[17,33,34],
[17,34,18],[18,34,35],[18,35,19],[19,35,36],[19,36,20],[20,36,37],[20,37,21],[21,37,38],[21,38,22],[22,38,39],[22,39,23],
[23,39,40],[23,40,24],[24,40,41],[24,41,25],[25,41,42],[25,42,26],[26,42,43],[26,43,27],[27,43,44],[27,44,28],[28,44,45],
[28,45,29],[29,45,46],[29,46,30],[30,46,47],[30,47,31],[32,48,49],[32,49,33],[33,49,50],[33,50,34],[34,50,51],[34,51,35],
[35,51,52],[35,52,36],[36,52,53],[36,53,37],[37,53,54],[37,54,38],[38,54,55],[38,55,39],[39,55,56],[39,56,40],[40,56,57],
[40,57,41],[41,57,58],[41,58,42],[42,58,59],[42,59,43],[43,59,60],[43,60,44],[44,60,61],[44,61,45],[45,61,62],[45,62,46],
[46,62,63],[46,63,47],[48,64,65],[48,65,49],[49,65,66],[49,66,50],[50,66,67],[50,67,51],[51,67,68],[51,68,52],[52,68,69],
[52,69,53],[53,69,70],[53,70,54],[54,70,71],[54,71,55],[55,71,72],[55,72,56],[56,72,73],[56,73,57],[57,73,74],[57,74,58],
[58,74,75],[58,75,59],[59,75,76],[59,76,60],[60,76,77],[60,77,61],[61,77,78],[61,78,62],[62,78,79],[62,79,63],[64,80,81],
[64,81,65],[65,81,82],[65,82,66],[66,82,83],[66,83,67],[67,83,84],[67,84,68],[68,84,85],[68,85,69],[69,85,86],[69,86,70],
[70,86,87],[70,87,71],[71,87,88],[71,88,72],[72,88,89],[72,89,73],[73,89,90],[73,90,74],[74,90,91],[74,91,75],[75,91,92],
[75,92,76],[76,92,93],[76,93,77],[77,93,94],[77,94,78],[78,94,95],[78,95,79],[80,96,97],[80,97,81],[81,97,98],[81,98,82],
[82,98,99],[82,99,83],[83,99,100],[83,100,84],[84,100,101],[84,101,85],[85,101,102],[85,102,86],[86,102,103],[86,103,87],[87,103,104],
[87,104,88],[88,104,105],[88,105,89],[89,105,106],[89,106,90],[90,106,107],[90,107,91],[91,107,108],[91,108,92],[92,108,109],[92,109,93],
[93,109,110],[93,110,94],[94,110,111],[94,111,95],[96,112,113],[96,113,97],[97,113,114],[97,114,98],[98,114,115],[98,115,99],[99,115,116],
[99,116,100],[100,116,117],[100,117,101],[101,117,118],[101,118,102],[102,118,119],[102,119,103],[103,119,120],[103,120,104],[104,120,121],[104,121,105],
[105,121,122],[105,122,106],[106,122,123],[106,123,107],[107,123,124],[107,124,108],[108,124,125],[108,125,109],[109,125,126],[109,126,110],[110,126,127],
[110,127,111],[112,128,129],[112,129,113],[113,129,130],[113,130,114],[114,130,131],[114,131,115],[115,131,132],[115,132,116],[116,132,133],[116,133,117],
[117,133,134],[117,134,118],[118,134,135],[118,135,119],[119,135,136],[119,136,120],[120,136,137],[120,137,121],[121,137,138],[121,138,122],[122,138,139],
[122,139,123],[123,139,140],[123,140,124],[124,140,141],[124,141,125],[125,141,142],[125,142,126],[126,142,143],[126,143,127],[128,144,145],[128,145,129],
[129,145,146],[129,146,130],[130,146,147],[130,147,131],[131,147,148],[131,148,132],[132,148,149],[132,149,133],[133,149,150],[133,150,134],[134,150,151],
[134,151,135],[135,151,152],[135,152,136],[136,152,153],[136,153,137],[137,153,154],[137,154,138],[138,154,155],[138,155,139],[139,155,156],[139,156,140],
[140,156,157],[140,157,141],[141,157,158],[141,158,142],[142,158,159],[142,159,143],[144,160,161],[144,161,145],[145,161,162],[145,162,146],[146,162,163],
[146,163,147],[147,163,164],[147,164,148],[148,164,165],[148,165,149],[149,165,166],[149,166,150],[150,166,167],[150,167,151],[151,167,168],[151,168,152],
[152,168,169],[152,169,153],[153,169,170],[153,170,154],[154,170,171],[154,171,155],[155,171,172],[155,172,156],[156,172,173],[156,173,157],[157,173,174],
[157,174,158],[158,174,175],[158,175,159],[160,176,177],[160,177,161],[161,177,178],[161,178,162],[162,178,179],[162,179,163],[163,179,180],[163,180,164],
[164,180,181],[164,181,165],[165,181,182],[165,182,166],[166,182,183],[166,183,167],[167,183,184],[167,184,168],[168,184,185],[168,185,169],[169,185,186],
[169,186,170],[170,186,187],[170,187,171],[171,187,188],[171,188,172],[172,188,189],[172,189,173],[173,189,190],[173,190,174],[174,190,191],[174,191,175]]
return vert_str, tri_str
# Game movement
def key_pressed(self, keypress):
if keypress[pygame.K_w]:
glTranslatef(0, 0, 0.001)
if keypress[pygame.K_s]:
glTranslatef(0, 0, -0.001)
if keypress[pygame.K_d]:
glTranslatef(-0.00025, 0, 0)
if keypress[pygame.K_a]:
glTranslatef(0.00025, 0, 0)
if keypress[pygame.K_e]:
glTranslatef(0, 0.0004, 0)
if keypress[pygame.K_q]:
glTranslatef(0, -0.0004, 0)
def draw_mesh_vbo(self):
vertex_src = """
# version 330
in layout(location = 0) vec3 a_position;
in layout(location = 1) vec3 a_color;
out vec3 v_color;
void main()
{
gl_Position = vec4(a_position, 1.0);
v_color = a_color;
}
"""
fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
self.ter_vao = glGenVertexArrays(1)
glBindVertexArray(self.ter_vao)
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.itemsize * len(self.vertices) * 8, self.vertices, GL_STATIC_DRAW)
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.itemsize * len(self.indices) * 3, self.indices, GL_STATIC_DRAW)
#pos = glGetAttribLocation(shader, "a_position")
# position
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(0))
# color
#col = glGetAttribLocation(shader, "a_color")
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(12))
# texture
#textr = glGetAttribLocation(shader, "a_text")
# glEnableVertexAttribArray(2)
# glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(24))
glBindVertexArray(0)
self.shady = shader
glClearColor(0, 0.3, 0.1, 1)
def pygame_loop(self, run, paused, displayCenter, up_down_angle, viewMatrix):
clock = pygame.time.Clock()
self.draw_mesh_vbo()
#glUseProgram(self.shader)
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
run = False
if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
paused = not paused
pygame.mouse.set_pos(displayCenter)
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
if not paused:
# get keys
keypress = pygame.key.get_pressed()
# init model view matrix
glLoadIdentity()
# apply the look up and down
up_down_angle += mouseMove[1] * 0.1
glRotatef(up_down_angle, 1.0, 0.0, 0.0)
# init the view matrix
glPushMatrix()
glLoadIdentity()
# apply the movment
self.key_pressed(keypress)
# apply the left and right rotation
glRotatef(mouseMove[0] * 0.02, 0.0, 1.0, 0.0)
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glPopMatrix()
# Close init the view matrix
# Update current view
glMultMatrixf(viewMatrix)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBindVertexArray(self.ter_vao)
#glUseProgram(self.shady)
glColor3f(0,0,0)
glDrawElements(GL_LINES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glColor4f(0.8, 0.8, 0.8, 0.0)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
#glUseProgram(0)
glBindVertexArray(0)
pygame.display.set_caption("FPS: %.2f" % clock.get_fps())
pygame.display.flip()
pygame.time.wait(20)
def pygame_view(self):
#Pygame Start
pygame.init()
#Create a "first person" environment
display = (1000, 600)
scree = pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1])
sphere = gluNewQuadric()
glMatrixMode(GL_PROJECTION)
gluPerspective(15, (1 * display[0] / display[1]), 0.001, 3000.0)
glMatrixMode(GL_MODELVIEW)
gluLookAt(self.vertices[50][0], self.vertices[50][1], 0, 0, -180, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)
up_down_angle = 0.0
paused = False
run = True
self.aspectratio = (1 * display[0] / display[1])
#Run Pygame
self.pygame_loop(run, paused, displayCenter, up_down_angle, viewMatrix)
pygame.quit()
if __name__ == '__main__':
mesh_dem = Meshi()
下一步:
在尝试实现纹理之前,我首先想了解着色器如何通过显示分配给每个顶点的颜色来工作。此示例中的预期结果是看到红色网格。
我尝试过的:
着色器设置:
vertex_src = """
# version 330
in layout(location = 0) vec3 a_position;
in layout(location = 1) vec3 a_color;
out vec3 v_color;
void main()
{
gl_Position = vec4(a_position, 1.0);
v_color = a_color;
}
"""
fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
self.shady = shader
在 while 循环中实现着色器:
glBindVertexArray(self.ter_vao)
glUseProgram(self.shady)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glUseProgram(0)
glBindVertexArray(0)
当我使用 glUseProgram(shader) 时,我只看到背景颜色。我怀疑这是因为 glUseProgram 禁用了模型视图、投影等。我是否必须更改着色器以包含投影、将 glUseProgram 放在其他地方或者我偏离了吗?
更新: 感谢 Python Youtube 系列中的 Rabbid76 和 Atilla Toth 的 OpenGL,我创建了一个可行的可编程管道示例(请参阅下面的答案)。我还没有实现 GLM 的矩阵转换,但现在 pyrr 工作正常。该示例根据坐标创建网格并根据高度显示不同的颜色。
如果您使用着色器程序,则矩阵变换必须在顶点着色器中完成。
Legacy OpenGL 矩阵堆栈已弃用。如果您使用着色器程序和遗留矩阵,那么您有
退回到 OpenGL Shading Language 1.20 (#version 120
) 着色器。
在此版本中,可以使用 gl_ModelViewProjectionMatrix
等内置制服。参见 Lighthouse3d.com - Hello World in GLSL。
例如:
# version 120
attribute vec3 a_position;
attribute vec3 a_color;
varying vec3 v_color;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_position, 1.0);
v_color = a_color;
}
但这不是 "modern" OpenGL。
在最先进的实现中,使用矩阵 Uniform 变量:
# version 330
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_color;
out vec3 v_color;
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
v_color = a_color;
}
位置索引glGetUniformLocation
of the uniform can be get by and the value of the matrix uniform can be set by glUniformMatrix4fv
。
使用像 PyGLM (this is a python wrapper for OpenGL Mathematics (GLM)) 这样的库来计算矩阵。
当然也可以使用 numpy.matrix
来计算矩阵。但这有点棘手。
感谢 Python Youtube 系列中的 Rabbid76 和 Atilla Toth 的 OpenGL,我创建了一个可行的可编程管道示例。我还没有实现 GLM 的矩阵转换,但现在 pyrr 工作正常。该示例根据坐标创建网格并根据高度显示不同的颜色。您还可以使用鼠标、w、s a、d、q、e 键四处飞行。
import numpy
import pandas
import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import pyrr
import glm
from pyrr import matrix44
from math import sin, cos, radians
class threeD_viewer():
def __init__(self, indi, tria, z_scale, x_st, y_st):
self.cam = Camera(x_st, y_st)
self.WIDTH, self.HEIGHT = 1280, 720
self.lastX, self.LastY = self.WIDTH / 2, self.HEIGHT / 2
self.first_mouse = True
self.forward, self.backward, self.right, self.left, self.up, self.down = False, False, False, False, False, False
self.x_start, self.y_start = x_st, y_st
vertices = indi
triangles = tria
z_values = []
for i in range(0, len(vertices)):
if vertices[i][2] < 0:
vertices[i][2] = 0
z_values.append(vertices[i][2])
else:
vertices[i][2] = vertices[i][2] * z_scale
z_values.append(vertices[i][2])
temp_z = vertices[i][2]
vertices[i][2] = vertices[i][1]
vertices[i][1] = temp_z
# Create a colour scheme to be based on height of the z axis
self.color_theme_1 = [[0.000, 0.000, 0.804], [0.678, 1.000, 0.184], [0.000, 1.000, 0.000],
[0.196, 0.804, 0.196], [1.000, 0.843, 0.000], [0.000, 0.392, 0.000]
, [0.804, 0.361, 0.361], [0.333, 0.420, 0.184]]
# Create heigth groups based on height quantiles
z_df = pandas.DataFrame(z_values, columns=["z_value"])
z_quant = z_df[z_df.z_value != 0].z_value.quantile([0.1, 0.3, 0.5, 0.75, 0.85, 0.9, 0.95, 0.98])
z_quant = z_quant.tolist()
# Add colour and texture to vertices
vert = []
for ver in vertices:
if ver[1] == 0:
color_in = self.color_theme_1[0] + [1.0, 0.0]
elif ver[1] < z_quant[0]:
color_in = self.color_theme_1[1] + [1.0, 0.0]
elif ver[1] < z_quant[1]:
color_in = self.color_theme_1[2] + [1.0, 0.0]
elif ver[1] < z_quant[2]:
color_in = self.color_theme_1[3] + [1.0, 0.0]
elif ver[1] < z_quant[3]:
color_in = self.color_theme_1[4] + [1.0, 0.0]
elif ver[1] < z_quant[4]:
color_in = self.color_theme_1[5] + [1.0, 0.0]
elif ver[1] < z_quant[5]:
color_in = self.color_theme_1[6] + [1.0, 0.0]
elif ver[1] < z_quant[6]:
color_in = self.color_theme_1[7] + [1.0, 0.0]
else:
vertices[i][1] = z_quant[6]
color_in = [0.502, 0.000, 0.000, 0.0, 0.1]
vert.append(ver + color_in)
# print(vert)
vertices = vert
self.vertices = numpy.array(vertices, dtype='f')
self.indices = numpy.array(triangles, dtype=numpy.int32)
self.vertex_src = """
# version 330
in vec3 a_position;
in vec3 a_color;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec3 v_color;
void main()
{
gl_Position = projection* view* vec4(a_position, 1.0);
v_color = a_color;
}
"""
self.fragment_src = """
# version 330
in vec3 v_color;
out vec4 out_color;
void main()
{
out_color = vec4(v_color, 1.0);
}
"""
self.main()
# the keyboard input callback
def key_input_clb(self, window, key, scancode, action, mode):
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.set_window_should_close(window, True)
if key == glfw.KEY_W and action == glfw.PRESS:
self.forward = True
elif key == glfw.KEY_W and action == glfw.RELEASE:
self.forward = False
if key == glfw.KEY_S and action == glfw.PRESS:
self.backward = True
elif key == glfw.KEY_S and action == glfw.RELEASE:
self.backward = False
if key == glfw.KEY_A and action == glfw.PRESS:
self.left = True
elif key == glfw.KEY_A and action == glfw.RELEASE:
self.left = False
if key == glfw.KEY_D and action == glfw.PRESS:
self.right = True
elif key == glfw.KEY_D and action == glfw.RELEASE:
self.right = False
if key == glfw.KEY_Q and action == glfw.PRESS:
self.up = True
elif key == glfw.KEY_Q and action == glfw.RELEASE:
self.up = False
if key == glfw.KEY_E and action == glfw.PRESS:
self.down = True
elif key == glfw.KEY_E and action == glfw.RELEASE:
self.down = False
def do_movement(self):
if self.forward:
self.cam.process_keyboard("FORWARD", 0.000008)
if self.backward:
self.cam.process_keyboard("BACKWARD", 0.000008)
if self.right:
self.cam.process_keyboard("RIGHT", 0.000008)
if self.left:
self.cam.process_keyboard("LEFT", 0.000008)
if self.up:
self.cam.process_keyboard("UP", 0.000008)
if self.down:
self.cam.process_keyboard("DOWN", 0.000008)
def mmouse_look_clb(self, window, xpos, ypos):
if self.first_mouse:
self.lastX = xpos
self.lastY = ypos
self.first_mouse = False
xoffset = xpos - self.lastX
yoffset = self.lastY - ypos
self.lastX = xpos
self.lastY = ypos
self.cam.process_mouse_movement(xoffset, yoffset)
def window_resize(self, window, width, height):
glViewport(0, 0, width, height)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, width / height, 0.0001, 100)
proj_loc = glGetUniformLocation(self.shader, "projection")
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
def main(self):
# initializing glfw library
if not glfw.init():
raise Exception("glfw can not be initialized!")
# creating the window
window = glfw.create_window(self.WIDTH, self.HEIGHT, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
# set window's position
glfw.set_window_pos(window, 400, 200)
# set the callback function for window resize
glfw.set_window_size_callback(window, self.window_resize)
glfw.set_cursor_pos_callback(window, self.mmouse_look_clb)
glfw.set_input_mode(window, glfw.CURSOR, glfw.CURSOR_DISABLED)
glfw.set_key_callback(window, self.key_input_clb)
#glfw.set_cursor_enter_callback(window, self.mouse_enter_clb)
# make the context current
glfw.make_context_current(window)
self.shader = compileProgram(compileShader(self.vertex_src, GL_VERTEX_SHADER),
compileShader(self.fragment_src, GL_FRAGMENT_SHADER))
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO)
# Vertex Buffer Object
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
# Element Buffer Object
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(0))
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, self.vertices.itemsize * 8, ctypes.c_void_p(24))
glBindVertexArray(0)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
projection_2 = glm.perspective(45, self.WIDTH / self.HEIGHT, 0.001, 3000)
projection = pyrr.matrix44.create_perspective_projection_matrix(45, self.WIDTH / self.HEIGHT, 0.0001, 100)
# print(projection_2)
# print(projection)
glUseProgram(self.shader)
model_loc = glGetUniformLocation(self.shader, "model")
proj_loc = glGetUniformLocation(self.shader, "projection")
view_loc = glGetUniformLocation(self.shader, "view")
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
# the main application loop
while not glfw.window_should_close(window):
glfw.poll_events()
self.do_movement()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
view = self.cam.get_view_matrix()
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glBindVertexArray(VAO)
glDrawElements(GL_TRIANGLES, len(self.indices) * 3, GL_UNSIGNED_INT, None)
glBindVertexArray(0)
glfw.swap_buffers(window)
# terminate glfw, free up allocated resources
glfw.terminate()
class Camera:
def __init__(self, xstart, ystart):
self.camera_pos = glm.vec3(xstart+0.005, 0.002, ystart+0.01)
self.camera_front = glm.vec3(0.0, 0.0, -200.0)
self.camera_up = glm.vec3(0.0, 1.0, 0.0)
self.camera_right = glm.vec3(1.0, 0.0, 0.0)
self.mouse_sensitivity = 0.25
self.jaw = -90.0
self.pitch = 0.0
def get_view_matrix(self):
return matrix44.create_look_at(self.camera_pos, self.camera_pos + self.camera_front, self.camera_up)
def process_mouse_movement(self, xoffset, yoffset, constrain_pitch=True):
xoffset *= self.mouse_sensitivity
yoffset *= self.mouse_sensitivity
self.jaw += xoffset
self.pitch += yoffset
if constrain_pitch:
if self.pitch > 45:
self.pitch = 45
if self.pitch < -45:
self.pitch = -45
self.update_camera_vectors()
def update_camera_vectors(self):
front = glm.vec3(0.0, 0.0, 0.0)
front.x = cos(radians(self.jaw)) * cos(radians(self.pitch))
front.y = sin(radians(self.pitch))
front.z = sin(radians(self.jaw)) * cos(radians(self.pitch))
self.camera_front = glm.normalize(front)
self.camera_right = glm.normalize(glm.cross(self.camera_front, glm.vec3(0.0, 1.0, 0.0)))
#self.camera_up = glm.normalize(glm.cross(self.camera_right, self.camera_front))
# Camera method for the WASD movement
def process_keyboard(self, direction, velocity):
if direction == "FORWARD":
self.camera_pos += self.camera_front * velocity
if direction == "BACKWARD":
self.camera_pos -= self.camera_front * velocity
if direction == "LEFT":
self.camera_pos -= self.camera_right * velocity
if direction == "RIGHT":
self.camera_pos += self.camera_right * velocity
if direction == "UP":
self.camera_pos += self.camera_up * velocity
if direction == "DOWN":
self.camera_pos -= self.camera_up * velocity
vertices = [[18.427083, -34.104583, 14.097592], [18.427917, -34.104583, 13.813885],
[18.42875, -34.104583, 11.798318], [18.429583, -34.104583, 12.170123],
[18.430417, -34.104583, 13.23494], [18.43125, -34.104583, 12.263627],
[18.432083, -34.104583, 10.543183], [18.432917, -34.104583, 9.150859],
[18.43375, -34.104583, 7.531989], [18.434583, -34.104583, 5.370541],
[18.435417, -34.104583, 4.947286],
[18.43625, -34.104583, 4.369431], [18.437083, -34.104583, 9.29184],
[18.437917, -34.104583, 11.300546], [18.43875, -34.104583, 9.590596],
[18.439583, -34.104583, 7.006906], [18.427083, -34.105417, 17.277378],
[18.427917, -34.105417, 12.070671], [18.42875, -34.105417, 9.0447],
[18.429583, -34.105417, 7.853086], [18.430417, -34.105417, 7.927739],
[18.43125, -34.105417, 8.325415],
[18.432083, -34.105417, 8.505657], [18.432917, -34.105417, 7.904904],
[18.43375, -34.105417, 7.7015], [18.434583, -34.105417, 7.362363], [18.435417, -34.105417, 7.08594],
[18.43625, -34.105417, 6.692467], [18.437083, -34.105417, 1.177889],
[18.437917, -34.105417, 6.393278], [18.43875, -34.105417, 8.610809],
[18.439583, -34.105417, 9.748986], [18.427083, -34.10625, 29.354589],
[18.427917, -34.10625, 24.616703], [18.42875, -34.10625, 18.529903],
[18.429583, -34.10625, 13.677365], [18.430417, -34.10625, 10.466432],
[18.43125, -34.10625, 9.469019], [18.432083, -34.10625, 7.960031], [18.432917, -34.10625, 7.115651],
[18.43375, -34.10625, 6.465553], [18.434583, -34.10625, 5.50102], [18.435417, -34.10625, 5.712739],
[18.43625, -34.10625, 6.946383],
[18.437083, -34.10625, 4.263526], [18.437917, -34.10625, 2.732419], [18.43875, -34.10625, 5.488115],
[18.439583, -34.10625, 6.902328], [18.427083, -34.107083, 30.979712],
[18.427917, -34.107083, 30.684374], [18.42875, -34.107083, 26.90592],
[18.429583, -34.107083, 22.378777], [18.430417, -34.107083, 19.191908],
[18.43125, -34.107083, 16.608807], [18.432083, -34.107083, 13.171669],
[18.432917, -34.107083, 10.77886], [18.43375, -34.107083, 11.478356],
[18.434583, -34.107083, 11.300546], [18.435417, -34.107083, 9.737173],
[18.43625, -34.107083, 6.484625], [18.437083, -34.107083, 5.185645],
[18.437917, -34.107083, 3.770918], [18.43875, -34.107083, 4.11032],
[18.439583, -34.107083, 4.947286], [18.427083, -34.107917, 30.013678],
[18.427917, -34.107917, 32.894321],
[18.42875, -34.107917, 31.857147], [18.429583, -34.107917, 26.9683],
[18.430417, -34.107917, 21.895006], [18.43125, -34.107917, 16.907623],
[18.432083, -34.107917, 12.721774], [18.432917, -34.107917, 11.510896],
[18.43375, -34.107917, 14.044291], [18.434583, -34.107917, 13.438006],
[18.435417, -34.107917, 12.538547], [18.43625, -34.107917, 11.562454],
[18.437083, -34.107917, 9.263826],
[18.437917, -34.107917, 6.071107], [18.43875, -34.107917, 4.289905],
[18.439583, -34.107917, 4.057948], [18.427083, -34.10875, 25.226519],
[18.427917, -34.10875, 26.609413], [18.42875, -34.10875, 29.121534],
[18.429583, -34.10875, 27.900227], [18.430417, -34.10875, 24.414494],
[18.43125, -34.10875, 20.20229], [18.432083, -34.10875, 14.686948],
[18.432917, -34.10875, 10.620943],
[18.43375, -34.10875, 11.136961], [18.434583, -34.10875, 9.067697],
[18.435417, -34.10875, 9.031256], [18.43625, -34.10875, 11.842289],
[18.437083, -34.10875, 14.412585], [18.437917, -34.10875, 14.026602],
[18.43875, -34.10875, 10.77886], [18.439583, -34.10875, 7.479022],
[18.427083, -34.109583, 24.316551], [18.427917, -34.109583, 4.027079],
[18.42875, -34.109583, 13.726677],
[18.429583, -34.109583, 23.883642], [18.430417, -34.109583, 28.826719],
[18.43125, -34.109583, 29.248907], [18.432083, -34.109583, 24.62047],
[18.432917, -34.109583, 14.576126], [18.43375, -34.109583, 10.270979],
[18.434583, -34.109583, 9.1116], [18.435417, -34.109583, 8.978557],
[18.43625, -34.109583, 10.877857], [18.437083, -34.109583, 13.952817],
[18.437917, -34.109583, 17.318939],
[18.43875, -34.109583, 18.3776], [18.439583, -34.109583, 16.823097],
[18.427083, -34.110417, 31.066404], [18.427917, -34.110417, 27.124994],
[18.42875, -34.110417, 14.584773], [18.429583, -34.110417, 6.256494],
[18.430417, -34.110417, 14.902382], [18.43125, -34.110417, 23.147758],
[18.432083, -34.110417, 26.993055], [18.432917, -34.110417, 22.765322],
[18.43375, -34.110417, 17.905703],
[18.434583, -34.110417, 13.544991], [18.435417, -34.110417, 11.899844],
[18.43625, -34.110417, 14.348012], [18.437083, -34.110417, 16.262051],
[18.437917, -34.110417, 17.542927], [18.43875, -34.110417, 21.157032],
[18.439583, -34.110417, 23.491091], [18.427083, -34.11125, 12.909849],
[18.427917, -34.11125, 20.651325], [18.42875, -34.11125, 24.733046],
[18.429583, -34.11125, 22.71829],
[18.430417, -34.11125, 12.409415], [18.43125, -34.11125, 4.794024],
[18.432083, -34.11125, 14.560322], [18.432917, -34.11125, 19.986332],
[18.43375, -34.11125, 21.261787], [18.434583, -34.11125, 18.94504],
[18.435417, -34.11125, 17.467054], [18.43625, -34.11125, 17.029078],
[18.437083, -34.11125, 15.266393], [18.437917, -34.11125, 14.918492],
[18.43875, -34.11125, 16.444849],
[18.439583, -34.11125, 18.332243], [18.427083, -34.112083, 14.870467],
[18.427917, -34.112083, 10.946778], [18.42875, -34.112083, 9.536969],
[18.429583, -34.112083, 17.428055], [18.430417, -34.112083, 20.116079],
[18.43125, -34.112083, 14.013614], [18.432083, -34.112083, 4.487359],
[18.432917, -34.112083, 4.302343], [18.43375, -34.112083, 9.771387],
[18.434583, -34.112083, 11.65025],
[18.435417, -34.112083, 11.8523], [18.43625, -34.112083, 10.677254],
[18.437083, -34.112083, 8.148099], [18.437917, -34.112083, 7.58765],
[18.43875, -34.112083, 5.033905], [18.439583, -34.112083, 3.151809],
[18.427083, -34.112917, 4.697855], [18.427917, -34.112917, 5.462211],
[18.42875, -34.112917, 6.136745], [18.429583, -34.112917, 6.001783],
[18.430417, -34.112917, 9.035099],
[18.43125, -34.112917, 13.059889], [18.432083, -34.112917, 13.085486],
[18.432917, -34.112917, 11.08321], [18.43375, -34.112917, 6.319217],
[18.434583, -34.112917, 4.270484], [18.435417, -34.112917, 4.372147],
[18.43625, -34.112917, 4.910031], [18.437083, -34.112917, 4.54907],
[18.437917, -34.112917, 3.606416], [18.43875, -34.112917, 6.188358],
[18.439583, -34.112917, 10.144054],
[18.427083, -34.11375, 8.589212], [18.427917, -34.11375, 8.18161], [18.42875, -34.11375, 7.444539],
[18.429583, -34.11375, 6.263077], [18.430417, -34.11375, 5.025665], [18.43125, -34.11375, 4.281593],
[18.432083, -34.11375, 4.90037], [18.432917, -34.11375, 9.216936], [18.43375, -34.11375, 10.723666],
[18.434583, -34.11375, 11.447696], [18.435417, -34.11375, 11.056483],
[18.43625, -34.11375, 10.136135], [18.437083, -34.11375, 6.79003], [18.437917, -34.11375, 2.968766],
[18.43875, -34.11375, 1.72892], [18.439583, -34.11375, 6.459183]]
triangles = [[0, 16, 17], [0, 17, 1], [1, 17, 18], [1, 18, 2], [2, 18, 19], [2, 19, 3], [3, 19, 20], [3, 20, 4],
[4, 20, 21], [4, 21, 5], [5, 21, 22],
[5, 22, 6], [6, 22, 23], [6, 23, 7], [7, 23, 24], [7, 24, 8], [8, 24, 25], [8, 25, 9], [9, 25, 26],
[9, 26, 10], [10, 26, 27], [10, 27, 11],
[11, 27, 28], [11, 28, 12], [12, 28, 29], [12, 29, 13], [13, 29, 30], [13, 30, 14], [14, 30, 31],
[14, 31, 15], [16, 32, 33], [16, 33, 17], [17, 33, 34],
[17, 34, 18], [18, 34, 35], [18, 35, 19], [19, 35, 36], [19, 36, 20], [20, 36, 37], [20, 37, 21],
[21, 37, 38], [21, 38, 22], [22, 38, 39], [22, 39, 23],
[23, 39, 40], [23, 40, 24], [24, 40, 41], [24, 41, 25], [25, 41, 42], [25, 42, 26], [26, 42, 43],
[26, 43, 27], [27, 43, 44], [27, 44, 28], [28, 44, 45],
[28, 45, 29], [29, 45, 46], [29, 46, 30], [30, 46, 47], [30, 47, 31], [32, 48, 49], [32, 49, 33],
[33, 49, 50], [33, 50, 34], [34, 50, 51], [34, 51, 35],
[35, 51, 52], [35, 52, 36], [36, 52, 53], [36, 53, 37], [37, 53, 54], [37, 54, 38], [38, 54, 55],
[38, 55, 39], [39, 55, 56], [39, 56, 40], [40, 56, 57],
[40, 57, 41], [41, 57, 58], [41, 58, 42], [42, 58, 59], [42, 59, 43], [43, 59, 60], [43, 60, 44],
[44, 60, 61], [44, 61, 45], [45, 61, 62], [45, 62, 46],
[46, 62, 63], [46, 63, 47], [48, 64, 65], [48, 65, 49], [49, 65, 66], [49, 66, 50], [50, 66, 67],
[50, 67, 51], [51, 67, 68], [51, 68, 52], [52, 68, 69],
[52, 69, 53], [53, 69, 70], [53, 70, 54], [54, 70, 71], [54, 71, 55], [55, 71, 72], [55, 72, 56],
[56, 72, 73], [56, 73, 57], [57, 73, 74], [57, 74, 58],
[58, 74, 75], [58, 75, 59], [59, 75, 76], [59, 76, 60], [60, 76, 77], [60, 77, 61], [61, 77, 78],
[61, 78, 62], [62, 78, 79], [62, 79, 63], [64, 80, 81],
[64, 81, 65], [65, 81, 82], [65, 82, 66], [66, 82, 83], [66, 83, 67], [67, 83, 84], [67, 84, 68],
[68, 84, 85], [68, 85, 69], [69, 85, 86], [69, 86, 70],
[70, 86, 87], [70, 87, 71], [71, 87, 88], [71, 88, 72], [72, 88, 89], [72, 89, 73], [73, 89, 90],
[73, 90, 74], [74, 90, 91], [74, 91, 75], [75, 91, 92],
[75, 92, 76], [76, 92, 93], [76, 93, 77], [77, 93, 94], [77, 94, 78], [78, 94, 95], [78, 95, 79],
[80, 96, 97], [80, 97, 81], [81, 97, 98], [81, 98, 82],
[82, 98, 99], [82, 99, 83], [83, 99, 100], [83, 100, 84], [84, 100, 101], [84, 101, 85],
[85, 101, 102], [85, 102, 86], [86, 102, 103], [86, 103, 87], [87, 103, 104],
[87, 104, 88], [88, 104, 105], [88, 105, 89], [89, 105, 106], [89, 106, 90], [90, 106, 107],
[90, 107, 91], [91, 107, 108], [91, 108, 92], [92, 108, 109], [92, 109, 93],
[93, 109, 110], [93, 110, 94], [94, 110, 111], [94, 111, 95], [96, 112, 113], [96, 113, 97],
[97, 113, 114], [97, 114, 98], [98, 114, 115], [98, 115, 99], [99, 115, 116],
[99, 116, 100], [100, 116, 117], [100, 117, 101], [101, 117, 118], [101, 118, 102], [102, 118, 119],
[102, 119, 103], [103, 119, 120], [103, 120, 104], [104, 120, 121], [104, 121, 105],
[105, 121, 122], [105, 122, 106], [106, 122, 123], [106, 123, 107], [107, 123, 124], [107, 124, 108],
[108, 124, 125], [108, 125, 109], [109, 125, 126], [109, 126, 110], [110, 126, 127],
[110, 127, 111], [112, 128, 129], [112, 129, 113], [113, 129, 130], [113, 130, 114], [114, 130, 131],
[114, 131, 115], [115, 131, 132], [115, 132, 116], [116, 132, 133], [116, 133, 117],
[117, 133, 134], [117, 134, 118], [118, 134, 135], [118, 135, 119], [119, 135, 136], [119, 136, 120],
[120, 136, 137], [120, 137, 121], [121, 137, 138], [121, 138, 122], [122, 138, 139],
[122, 139, 123], [123, 139, 140], [123, 140, 124], [124, 140, 141], [124, 141, 125], [125, 141, 142],
[125, 142, 126], [126, 142, 143], [126, 143, 127], [128, 144, 145], [128, 145, 129],
[129, 145, 146], [129, 146, 130], [130, 146, 147], [130, 147, 131], [131, 147, 148], [131, 148, 132],
[132, 148, 149], [132, 149, 133], [133, 149, 150], [133, 150, 134], [134, 150, 151],
[134, 151, 135], [135, 151, 152], [135, 152, 136], [136, 152, 153], [136, 153, 137], [137, 153, 154],
[137, 154, 138], [138, 154, 155], [138, 155, 139], [139, 155, 156], [139, 156, 140],
[140, 156, 157], [140, 157, 141], [141, 157, 158], [141, 158, 142], [142, 158, 159], [142, 159, 143],
[144, 160, 161], [144, 161, 145], [145, 161, 162], [145, 162, 146], [146, 162, 163],
[146, 163, 147], [147, 163, 164], [147, 164, 148], [148, 164, 165], [148, 165, 149], [149, 165, 166],
[149, 166, 150], [150, 166, 167], [150, 167, 151], [151, 167, 168], [151, 168, 152],
[152, 168, 169], [152, 169, 153], [153, 169, 170], [153, 170, 154], [154, 170, 171], [154, 171, 155],
[155, 171, 172], [155, 172, 156], [156, 172, 173], [156, 173, 157], [157, 173, 174],
[157, 174, 158], [158, 174, 175], [158, 175, 159], [160, 176, 177], [160, 177, 161], [161, 177, 178],
[161, 178, 162], [162, 178, 179], [162, 179, 163], [163, 179, 180], [163, 180, 164],
[164, 180, 181], [164, 181, 165], [165, 181, 182], [165, 182, 166], [166, 182, 183], [166, 183, 167],
[167, 183, 184], [167, 184, 168], [168, 184, 185], [168, 185, 169], [169, 185, 186],
[169, 186, 170], [170, 186, 187], [170, 187, 171], [171, 187, 188], [171, 188, 172], [172, 188, 189],
[172, 189, 173], [173, 189, 190], [173, 190, 174], [174, 190, 191], [174, 191, 175]]
Z_scale = 0.00005
xStart = vertices[0][0]
yStart = vertices[0][1]
threeD_viewer(vertices, triangles, Z_scale, xStart, yStart)