如何像在搅拌机中一样用鼠标拖动相机
Posted
技术标签:
【中文标题】如何像在搅拌机中一样用鼠标拖动相机【英文标题】:how to drag camera with the mouse like in blender 【发布时间】:2022-01-20 16:53:50 【问题描述】:我找到了一个程序,你可以在 pyopengl 中用鼠标在相机周围移动,通过做一些我没有完全理解的事情
from pygame.locals import *
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
def cube():
vertices = (
(1,-1,-1),
(1,1,-1),
(-1,1,-1),
(-1,-1,-1),
(1,-1,1),
(1,1,1),
(-1,-1,1),
(-1,1,1)
)
edegs = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7),
)
glBegin(GL_LINES)
glColor3fv((1,1,1))
for edeg in edegs:
for vertex in edeg:
glVertex3fv(vertices[vertex])
glEnd()
pygame.init()
screen = (800,600)
pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (screen[0]/screen[1]), 0.1, 50.0)
glTranslate(0.0,0.0,-5)
glMatrixMode(GL_MODELVIEW)
modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
busy = True
button_down = False
zoom = -0.5
while True:
glPushMatrix()
glLoadIdentity()
for event in pygame.event.get():
if(event.type == pygame.QUIT):
pygame.quit()
busy = False
elif event.type == pygame.MOUSEMOTION:
if(button_down):
glRotatef(event.rel[1], 1, 0, 0)
glRotatef(event.rel[0], 0, 1, 0)
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 4:
zoom += 0.2
if event.button == 5:
zoom -= 0.2
if(not busy): break
for event in pygame.mouse.get_pressed():
if pygame.mouse.get_pressed()[0] == 1:
button_down = True
elif pygame.mouse.get_pressed()[0] == 0:
button_down = False
#mouse scroll
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glMultMatrixf(modelMatrix)
modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
glTranslatef(0.0,0.0,zoom)
glMultMatrixf(modelMatrix)
cube()
glPopMatrix()
pygame.display.flip()
pygame.time.wait(10)
但是当你在它周围拖动对象时,它开始失去从上到下的方向,这与 Blender 和 SketchUp 等程序不同,有没有办法解决这个问题或用其他方法来操纵相机?
【问题讨论】:
【参考方案1】:只需将绕 x 轴的旋转和绕 y 轴的旋转相加即可。先绕y轴旋转,再绕x轴旋转:
modelview = translate * rotateY * raotateX
完整示例:
from pygame.locals import *
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
def cube():
vertices = (
(1,-1,-1), (1,1,-1), (-1,1,-1), (-1,-1,-1),
(1,-1,1), (1,1,1), (-1,-1,1), (-1,1,1)
)
edegs = (
(0,1), (0,3), (0,4), (2,1), (2,3), (2,7),
(6,3), (6,4), (6,7), (5,1), (5,4), (5,7),
)
glBegin(GL_LINES)
glColor3fv((1,1,1))
for edeg in edegs:
for vertex in edeg:
glVertex3fv(vertices[vertex])
glColor3fv((1,0,0))
glVertex3f(0, -2, 0)
glVertex3f(0, 2, 0)
glEnd()
pygame.init()
screen = (400, 300)
pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (screen[0]/screen[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslate(0.0,0.0,-5)
rot_x, rot_y, zoom = 0, 0, -0.5
clock = pygame.time.Clock()
busy = True
while busy:
mouse_buttons = pygame.mouse.get_pressed()
button_down = mouse_buttons[0] == 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
busy = False
elif event.type == pygame.MOUSEMOTION:
if button_down:
rot_x += event.rel[1]
rot_y += event.rel[0]
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 4:
zoom += 0.2
if event.button == 5:
zoom -= 0.2
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glTranslatef(0.0,0.0, zoom)
glRotatef(rot_x, 1, 0, 0)
glRotatef(rot_y, 0, 1, 0)
cube()
glPopMatrix()
pygame.display.flip()
clock.tick(100)
pygame.quit()
另请参阅How to implement alt+MMB camera rotation like in 3ds max?、How to implement camera pan like in 3dsMax?、How to implement zoom towards mouse like in 3dsMax?。
【讨论】:
以上是关于如何像在搅拌机中一样用鼠标拖动相机的主要内容,如果未能解决你的问题,请参考以下文章