模仿三维动画制作软件用PyOpenGL编写一个多视图切换的程序

三维动画软件编辑界面可以在多视图和单视图之间随意切换,方便设计用户观察和编辑三维物体或者动画。掌握了OpenGL初步知识后很容易实现此功能。下面就是我在deepseek帮助下写的一段程序,实现了用数字键切换1、2、3、4视图,也可以用空格键切换四视图和其它视图,视图中绘制了一个立方体线框,前面绿色后面红色,使用者还可以通过按下鼠标左键拖动鼠标实现立方体滚动,并通过观察立方体线框色彩变换,感知投影是否正确。

#基于pygame设计一个类似glut的流程initScense()、changeSize()、handleEvent()、mainloop()……
#在windows和英特尔集显平台上完美显示四个视图,在华为uos显示四个视图,但是三个正投影显示不正常可能还要调试
import pygame as pg
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np

nRange=5 #x的范围绝对值,y按照屏幕比例调整
vLayout=4
oLayout=1
#view=[]
translation=[0,0,0]
rotation=[0,0,0]
w,h=1024,768

def draw_cube():
    
    vertices = [
        [[1, 1, -1],[1,0,0]],
        [[1, -1, -1],[1,0,0]],
        [[-1, -1, -1],[1,0,0]],
        [[-1, 1, -1],[1,0,0]],
        [[1, 1, 1],[0,1,0]],
        [[1, -1, 1],[0,1,0]],
        [[-1, -1, 1],[0,1,0]],
        [[-1, 1, 1],[0,1,0]]
    ]# 立方体的含有颜色的点的数据,位置+颜色
    edges = [
        (0, 1), (1, 2), (2, 3), (3, 0),
        (4, 5), (5, 6), (6, 7), (7, 4),
        (0, 4), (1, 5), (2, 6), (3, 7)
    ]
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glColor3fv(vertices[vertex][1])
            glVertex3fv(vertices[vertex][0])
    glEnd()



def set_ortho(w, h,viewType):
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    #glMatrixMode(GL_MODELVIEW)
    if w<h:
        glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,0.1,100)
    else:
        glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,0.1,100)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    if viewType == 'top':
        gluLookAt(0, 10, 0, 0, 0, 0, 0, 0, -1)
    elif viewType == 'front':
        gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0)
    elif viewType == 'left':
        gluLookAt(-10, 0, 0, 0, 0, 0, 0, 1, 0)
    elif viewType == 'right':
        gluLookAt(10, 0, 0, 0, 0, 0, 0, 1, 0)
    
def set_perspective(width, height):
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, (width/height), 0.1, 45)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    gluLookAt(5, 5, 5, 0, 0, 0, 0, 1, 0)
    
def draw_grid(type):
    grid_size=10
    grid_step=1
    if type == 'top' or 'pespect':
        glBegin(GL_LINES)
        for i in range(-grid_size, grid_size+1, grid_step):
            glColor3f(0.5, 0.5, 0.5)
            glVertex3f(i, 0, -grid_size)
            glVertex3f(i, 0, grid_size)
            glVertex3f(-grid_size, 0, i)
            glVertex3f(grid_size, 0, i)
        glEnd()
    if type == 'left':
        glBegin(GL_LINES)
        for i in range(-grid_size, grid_size+1, grid_step):
            glColor3f(0.5, 0.5, 0.5)
            glVertex3f(0, i, -grid_size)
            glVertex3f(0, i, grid_size)
            glVertex3f(0,-grid_size, i)
            glVertex3f(0, grid_size, i)
        glEnd()
    if type == 'right':
        glBegin(GL_LINES)
        for i in range(-grid_size, grid_size+1, grid_step):
            glColor3f(0.5, 0.5, 0.5)
            glVertex3f(0, i, -grid_size)
            glVertex3f(0, i, grid_size)
            glVertex3f(0,-grid_size, i)
            glVertex3f(0, grid_size, i)
        glEnd()
    


def renderViewport(x,y,w,h,view_type):
    glViewport(x, y, w, h)
    glScissor(x, y, w, h)
    glEnable(GL_SCISSOR_TEST)
    glClear(GL_DEPTH_BUFFER_BIT)
    if view_type == 'perspective':
        set_perspective(w,h)
    else:
        set_ortho(w,h,view_type)
    draw_grid(view_type)
    glPushMatrix()
    glTranslatef(*translation)
    glRotatef(rotation[0], 1, 0, 0)
    glRotatef(rotation[1], 0, 1, 0)
       
    # draw_grid(view_type)
    draw_cube()
        
    glPopMatrix()
    glDisable(GL_SCISSOR_TEST)

def showLayout(w,h):
    global vLayout
    print(vLayout,w,h)
    if vLayout==1:
        renderViewport(0, 0, w, h, 'perspective')
    if vLayout == 4:
        # 四视图布局
        w, h = w//2, h//2
        renderViewport(0, h, w, h, 'top')
        renderViewport(w, h, w, h, 'front')
        renderViewport(0, 0, w, h, 'left')
        renderViewport(w, 0, w, h, 'perspective')
    if vLayout == 2:
        if w >= h:
            w = w//2
            renderViewport(0, 0, w, h, 'perspective')
            renderViewport(w, 0, w, h, 'front')
        else:
            h=h//2
            renderViewport(0, h, w, h, 'perspective')
            renderViewport(0, 0, w, h, 'front')
    if vLayout == 3:
        if w >= h:
            if w >= 1.5*h:
                renderViewport(0, 0, h, h, 'perspective')
                renderViewport(h, 0, w-h, h//2, 'front')
                renderViewport(h, h, w-h, h//2, 'top')
            else:
                renderViewport(0, 0, h//2, h, 'perspective')
                renderViewport(h//2, 0, w-h//2, h//2, 'front')
                renderViewport(h//2, h//2, w-h//2, h//2, 'top')
        if w < h:
            if h >= 1.5*w:
                renderViewport(0, h//2, w, h//2, 'perspective')
                renderViewport(0, 0, h-w, h//2, 'front')
                renderViewport(w//2, 0, h-w, w//2, 'top')
            else:
                renderViewport(0, 0, w, w//2, 'perspective')
                renderViewport(h//2, 0, w//2, w-h//2, 'front')
                renderViewport(0, w//2, w//2, w-h//2, 'top')

def initScense():
    global nRange,w,h,screen
    pg.init()
    display=(w,h)
    aspectratio=display[0]/display[1]
    screen=pg.display.set_mode(display,DOUBLEBUF|OPENGL|RESIZABLE)
    pg.display.set_caption('多视图切换')
    nRange=5
    # 初始化OpenGL参数
    glEnable(GL_DEPTH_TEST)
    # glEnable(GL_LIGHTING)
    # glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glClearColor(0.2, 0.2, 0.2, 1.0)
    
def changeSize(w,h):
    global nRange
    display=(w,h)
    aspectratio=display[0]/display[1]
    pg.display.set_mode(display,DOUBLEBUF|OPENGL|RESIZABLE)
 
def handleEvent():
    global oLayout,vLayout,w,h
    for event in pg.event.get():
        if event.type==pg.QUIT:
            pg.quit()
            quit()
        elif event.type==pg.VIDEORESIZE:
            w,h=event.size
            changeSize(event.w,event.h)
        elif event.type == pg.MOUSEMOTION:
            if event.buttons[0]:
                dx,dy=event.rel
                rotation[0]+=dy*0.5
                rotation[1]+=dx*0.5

        elif event.type == pg.KEYDOWN:
            if event.key == K_SPACE:
                if vLayout != 4:
                    oLayout=vLayout
                    vLayout=4
                else:
                    vLayout=oLayout
            elif event.key == K_1:
                vLayout=1
                oLayout=1
            elif event.key == K_2:
                vLayout=2
                oLayout=2
            elif event.key == K_3:
                vLayout=3
                oLayout=3
            elif event.key == K_4:
                if vLayout != 4:
                    oLayout=vLayout
                    vLayout=4
                

def mainloop():
    global w,h
    while True:
        handleEvent()
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        showLayout(w,h)
        pg.display.flip()
        pg.time.wait(20)

#main            
initScense()
mainloop()





在此基础上可以添加选择、拖曳、修改、保存等功能,完成一个简单的三维物体制作软件。如果添加高精度渲染和动画功能,就能做一个比较完善的三维动画软件,有兴趣的朋友可以试一试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值