pyopengl - 在不使用 gluCylinder 函数的情况下创建一个圆柱体
pyopengl - creating a cylinder without using gluCylinder function
我正在尝试使用 pyopengl 创建一个圆柱体。圆柱体的顶部不是圆形,而底部如下图所示。我想知道如何解决这个问题,如果它是我编码的方式或者只是我完成它的方式不适用于 pyopengl。我正在使用 Pygame 1.9.2、Python 3.5 和 PyOpenGL-3.1.0。
https://i.stack.imgur.com/KYPLY.jpg
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
def securityCamera(radius,halflength,slices):
glBegin(GL_TRIANGLES)
for i in range(1,slices+1):
angleSize=(2*math.pi)/slices
theta=i*angleSize
nextTheta=(i+1)*angleSize
glColor3fv((0/256,0/256,0/256))
glVertex3f(radius*math.cos(nextTheta), halflength, radius*math.cos(nextTheta))
glVertex3f(radius*math.cos(theta), halflength, radius*math.sin(theta))
glVertex3f(0.0, halflength, 0.0)
glVertex3f(radius*math.cos(nextTheta), -halflength, radius*math.sin(nextTheta))
glVertex3f(radius*math.cos(theta), -halflength, radius*math.sin(theta))
glVertex3f(0.0, -halflength, 0.0)
glEnd()
glBegin(GL_QUADS)
for i in range(1,slices+1):
angleSize=(2*math.pi)/slices
theta=i*angleSize
nextTheta=(i+1)*angleSize
glColor3fv((256/256,256/256,256/256))
glVertex3f(radius*math.cos(theta), halflength, radius*math.sin(theta))
glVertex3f(radius*math.cos(nextTheta), halflength, radius*math.cos(nextTheta))
glVertex3f(radius*math.cos(theta), -halflength, radius*math.sin(theta))
glVertex3f(radius*math.cos(nextTheta), -halflength, radius*math.sin(nextTheta))
glEnd()
一个圆柱体可以分成两个圆圈和一个连接这两个圆圈的矩形tube/sheet。为了避免重复某些顶点,我使用 GL_TRIANGLE_FAN
(对于圆)和 GL_TRIANGLE_STRIP
(对于管)而不是 GL_TRIANGLE
和 GL_QUAD
。如果您想了解更多有关这些的信息,我建议您查看 this 答案。
下面是一个红端、蓝端、中间是绿管的旋转圆柱体演示(重要代码在draw_cylinder
函数中):
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
import sys
def draw_cylinder(radius, height, num_slices):
r = radius
h = height
n = float(num_slices)
circle_pts = []
for i in range(int(n) + 1):
angle = 2 * math.pi * (i/n)
x = r * math.cos(angle)
y = r * math.sin(angle)
pt = (x, y)
circle_pts.append(pt)
glBegin(GL_TRIANGLE_FAN)#drawing the back circle
glColor(1, 0, 0)
glVertex(0, 0, h/2.0)
for (x, y) in circle_pts:
z = h/2.0
glVertex(x, y, z)
glEnd()
glBegin(GL_TRIANGLE_FAN)#drawing the front circle
glColor(0, 0, 1)
glVertex(0, 0, h/2.0)
for (x, y) in circle_pts:
z = -h/2.0
glVertex(x, y, z)
glEnd()
glBegin(GL_TRIANGLE_STRIP)#draw the tube
glColor(0, 1, 0)
for (x, y) in circle_pts:
z = h/2.0
glVertex(x, y, z)
glVertex(x, y, -z)
glEnd()
pygame.init()
(width, height) = (800, 600)
screen = pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)
clock = pygame.time.Clock()
rotation = 0.0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
rotation += 1.0
glClear(GL_COLOR_BUFFER_BIT)
glClear(GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(30, float(width)/height, 1, 1000)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslate(0, 0, -50)#move back far enough to see this object
glRotate(rotation, 0, 1, 0)#NOTE: this is applied BEFORE the translation due to OpenGL multiply order
draw_cylinder(5, 10, 20)
pygame.display.flip()
clock.tick(60)
顺便说一句,您可能知道 fixed-function 方法,如 glBegin
和 glVertex
确实很古老 out-of-date,但我认为它不会伤害到提到。使用这种代码,您基本上是一次一个地向 GPU 发送一个顶点,效率不是很高。如果您以后 运行 遇到性能问题,您可能想看看 VBO。希望这对您有所帮助!
我正在尝试使用 pyopengl 创建一个圆柱体。圆柱体的顶部不是圆形,而底部如下图所示。我想知道如何解决这个问题,如果它是我编码的方式或者只是我完成它的方式不适用于 pyopengl。我正在使用 Pygame 1.9.2、Python 3.5 和 PyOpenGL-3.1.0。
https://i.stack.imgur.com/KYPLY.jpg
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
def securityCamera(radius,halflength,slices):
glBegin(GL_TRIANGLES)
for i in range(1,slices+1):
angleSize=(2*math.pi)/slices
theta=i*angleSize
nextTheta=(i+1)*angleSize
glColor3fv((0/256,0/256,0/256))
glVertex3f(radius*math.cos(nextTheta), halflength, radius*math.cos(nextTheta))
glVertex3f(radius*math.cos(theta), halflength, radius*math.sin(theta))
glVertex3f(0.0, halflength, 0.0)
glVertex3f(radius*math.cos(nextTheta), -halflength, radius*math.sin(nextTheta))
glVertex3f(radius*math.cos(theta), -halflength, radius*math.sin(theta))
glVertex3f(0.0, -halflength, 0.0)
glEnd()
glBegin(GL_QUADS)
for i in range(1,slices+1):
angleSize=(2*math.pi)/slices
theta=i*angleSize
nextTheta=(i+1)*angleSize
glColor3fv((256/256,256/256,256/256))
glVertex3f(radius*math.cos(theta), halflength, radius*math.sin(theta))
glVertex3f(radius*math.cos(nextTheta), halflength, radius*math.cos(nextTheta))
glVertex3f(radius*math.cos(theta), -halflength, radius*math.sin(theta))
glVertex3f(radius*math.cos(nextTheta), -halflength, radius*math.sin(nextTheta))
glEnd()
一个圆柱体可以分成两个圆圈和一个连接这两个圆圈的矩形tube/sheet。为了避免重复某些顶点,我使用 GL_TRIANGLE_FAN
(对于圆)和 GL_TRIANGLE_STRIP
(对于管)而不是 GL_TRIANGLE
和 GL_QUAD
。如果您想了解更多有关这些的信息,我建议您查看 this 答案。
下面是一个红端、蓝端、中间是绿管的旋转圆柱体演示(重要代码在draw_cylinder
函数中):
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
import sys
def draw_cylinder(radius, height, num_slices):
r = radius
h = height
n = float(num_slices)
circle_pts = []
for i in range(int(n) + 1):
angle = 2 * math.pi * (i/n)
x = r * math.cos(angle)
y = r * math.sin(angle)
pt = (x, y)
circle_pts.append(pt)
glBegin(GL_TRIANGLE_FAN)#drawing the back circle
glColor(1, 0, 0)
glVertex(0, 0, h/2.0)
for (x, y) in circle_pts:
z = h/2.0
glVertex(x, y, z)
glEnd()
glBegin(GL_TRIANGLE_FAN)#drawing the front circle
glColor(0, 0, 1)
glVertex(0, 0, h/2.0)
for (x, y) in circle_pts:
z = -h/2.0
glVertex(x, y, z)
glEnd()
glBegin(GL_TRIANGLE_STRIP)#draw the tube
glColor(0, 1, 0)
for (x, y) in circle_pts:
z = h/2.0
glVertex(x, y, z)
glVertex(x, y, -z)
glEnd()
pygame.init()
(width, height) = (800, 600)
screen = pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)
clock = pygame.time.Clock()
rotation = 0.0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
rotation += 1.0
glClear(GL_COLOR_BUFFER_BIT)
glClear(GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(30, float(width)/height, 1, 1000)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslate(0, 0, -50)#move back far enough to see this object
glRotate(rotation, 0, 1, 0)#NOTE: this is applied BEFORE the translation due to OpenGL multiply order
draw_cylinder(5, 10, 20)
pygame.display.flip()
clock.tick(60)
顺便说一句,您可能知道 fixed-function 方法,如 glBegin
和 glVertex
确实很古老 out-of-date,但我认为它不会伤害到提到。使用这种代码,您基本上是一次一个地向 GPU 发送一个顶点,效率不是很高。如果您以后 运行 遇到性能问题,您可能想看看 VBO。希望这对您有所帮助!