Python pyglet 自制3D引擎入门(二) -- 绘制立体心形,动画和相机控制

这篇具有很好参考价值的文章主要介绍了Python pyglet 自制3D引擎入门(二) -- 绘制立体心形,动画和相机控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Python作为目前较广泛的编程语言, 用于制作3D游戏可谓得心应手。本文讲解使用Python pyglet库自制简易3D引擎的方法技巧。

上篇:Python pyglet 自制3D引擎入门(一) – 绘制几何体、创建3D场景

先放效果图:
python立体爱心,Python,3D图形绘制,python,3d,图形渲染,游戏引擎,OpenGL

导入pyglet及初始化

pyglet.window部分用于实现窗口操作, pyglet.gl以及pyglet.gl.glu模块包含了OpenGL的绘图函数, 也是3D引擎中的关键部分。
pyglet模块可通过pip安装: pip install pyglet

import pyglet
from pyglet.gl import *
from pyglet.gl.glu import *
from pyglet.window import key
import math
from random import random, randint

定义常量和数据:

WIDTH=400;HEIGHT=400
angle_xy = math.pi / 2 # X-Y平面内的相机角度, 弧度制(0-360°变为0-2π)
angle_z = 0 # 相机绕Z轴旋转的角度
distance = 20
centerx,centery,centerz = 38,9, -11 # 中心点位置, 相机绕中心点旋转
data = [(3.2045, 50.7902), (1.5227, 49.5507), (0.2268, 47.9115), (-0.6292, 46.0584), (-0.9964, 44.1779), (-0.8378, 42.4295), (-0.5548, 41.6411), (-0.1348, 40.9221),
        (0.4219, 40.2782), (1.9425, 39.2276), (2.9045, 38.8233), (4.0, 38.5), (2.9045, 38.1766), (1.9424, 37.7722), (0.4218, 36.7216), (-0.1349, 36.0778), (-0.5548, 35.3589), (-0.8378, 34.5706), (-0.9964, 32.8226),
        (-0.6291, 30.9425), (0.227, 29.09), (1.5229, 27.4513), (3.2048, 26.2122), (5.2203, 25.5298), (7.5231, 25.5104), (10.0749, 26.2121), (12.8454, 27.6578), (15.812, 29.848),
        (18.9593, 32.7712), (22.2779, 36.4131), (24.0, 38.5), (22.2778, 40.5874), (18.9591, 44.2302), (15.8118, 47.1541), (12.8451, 49.3448), (10.0746, 50.7907),
        (7.5228, 51.4924), (5.22, 51.4729)]# 心形的矢量图数据
z1=8; z2=10 # 心形两个面的z坐标

初始化pygletWindow对象, 用于绘制图形、接收事件。

# sample_buffers为抗锯齿,depth_size为启用z排序
conf = pyglet.gl.Config(sample_buffers=1, samples=4, depth_size=1)
window = pyglet.window.Window(height=HEIGHT, width=WIDTH,
                              config=conf)

相机控制

类似于一些3D游戏,我们这里的相机需要实现360°无死角的旋转。

convert_pos()用于转换相机的坐标。其中:
相机绕着一个中心点, 2个方向旋转。
想象相机和中心点距离不变, 中心点是球心, 相机就相当于在一个球体表面自由移动。程序中angle_xy类似于球体的“经度”, angle_z类似“纬度”。通过“经度”和“纬度”, 就能控制相机移动。
另外, 一些3D游戏除了使用以上的“经度”和“纬度”, 还使用了第三根轴控制相机的旋转。
像下面这样:
python立体爱心,Python,3D图形绘制,python,3d,图形渲染,游戏引擎,OpenGL

def convert_pos():
    # 将相机角度转换为相机的X,Y,Z坐标
    if math.pi/2 < angle_z < math.pi * 1.5:
        flag = -1 # 相机朝下
    else:
        flag = 1 # 相机朝上
    cam_x=math.cos(angle_xy)*distance *math.cos(angle_z) + centerx
    cam_y=math.sin(angle_xy)*distance *math.cos(angle_z) + centery
    cam_z=math.sin(angle_z)*distance + centerz
    return cam_x,cam_y,cam_z,flag

这是绑定pyglet窗口的事件
按↑,↓,←,→键或拖动鼠标切换查看角度,按Page Up / Page Down键或滚动鼠标,调整远近。

@window.event
def on_key_press(k,_):
    global angle_xy,angle_z,distance
    if k==key.DOWN: # 下
        angle_z -= math.pi * 1/18 # 10°
    elif k==key.UP:# 上
        angle_z += math.pi * 1/18
    elif k==key.LEFT: # 左
        angle_xy -= math.pi * 1/18
    elif k==key.RIGHT: # 右
        angle_xy += math.pi * 1/18
    elif k==key.PAGEUP: # page up
        distance/=1.15
    elif k==key.PAGEDOWN: # page down
        distance*=1.15
    angle_z %= math.pi*2
    on_draw()

@window.event
def on_mouse_drag(x,y,dx,dy,btn,_): # 拖动鼠标, dx和dy为鼠标位置变化的多少
    global angle_xy, angle_z
    angle_xy -= dx / 100
    angle_z -= dy / 100
    angle_z %= math.pi * 2
    on_draw()

@window.event
def on_mouse_scroll(x,y, _, d): # 滚动鼠标, d为滚动的多少
    global distance
    distance /= 1.1**d
    on_draw()

3D图形绘制

这是window对象的on_draw事件,调用openGL绘图的代码都应该放在这个函数里面。
如果代码看不懂,可以看上篇中关于openGL 3D绘图的介绍。

@window.event  # 表示绑定 window 对象的事件
def on_draw(): # 注意函数名, 必须是on_draw才能绑定绘制的事件

    glMatrixMode(GL_PROJECTION)  # 设置当前矩阵为投影矩阵
    glLoadIdentity()

    # 透视投影, 前4个参数类似游戏中的FOV(视角大小), 
    # 后2个参数分别是物体与相机的最近、最远距离
    glFrustum(-5, 5, -5, 5, 2, 1000)  # 透视投影

    glMatrixMode(GL_MODELVIEW)  # 模型视图矩阵
    glLoadIdentity()

    glViewport(0, 0, WIDTH, HEIGHT)

    window.clear() # 或 glClear(GL_COLOR_BUFFER_BIT)
    glClear(GL_DEPTH_BUFFER_BIT) # 清除深度(z排序)缓冲区
 
    # 改变相机位置和角度
    cam_x,cam_y,cam_z,flag = convert_pos()
    gluLookAt(cam_x,cam_y,cam_z,centerx,centery,centerz,0,0,flag) # 0,0,flag为相机朝上方向

    for dx,dy,dz in lst_pos: # 绘制列表中的各个心形
        draw_heart(dx,dy,dz)

    glFlush() # 刷新绘图缓冲区

下面的draw_heart()函数用于在不同位置绘制3D心形, 根据二维的心形矢量图数据, 绘制正面和侧面, 形成三维的形状。glVertex3f函数定义心形每个顶点的坐标。

def draw_heart(dx,dy,dz): # 绘制心形
    # dx, dy, dz为心形从中心点向X, Y, Z轴正方向平移多少
    # 绘制顶、底面
    glBegin(GL_POLYGON)
    glColor3f(random()*0.5+0.5, 0, random()*0.5+0.5) # 随机生成颜色
    for x, y in data:
        glVertex3f(y+dx, z1+dy, -x+dz) # 使用y,z和-x, 旋转心形, 使心形更易于查看
    glEnd()
    glBegin(GL_POLYGON)
    for x, y in data:
        glVertex3f(y+dx, z2+dy, -x+dz)
    glEnd()
    # 绘制透明侧面
    glColor4f(0.5, 0, 0.5, 0.5)
    for i in range(len(data)):
        if i + 1 == len(data):  # 到达列表末尾
            next_point = data[0]
        else:
            next_point = data[i + 1]
        point = data[i]
        glBegin(GL_POLYGON)
        glVertex3f(point[1]+dx, z1+dy, -point[0]+dz)
        glVertex3f(next_point[1]+dx, z1+dy, -next_point[0]+dz)
        glVertex3f(next_point[1]+dx, z2+dy, -next_point[0]+dz)
        glVertex3f(point[1]+dx, z2+dy, -point[0]+dz)
        glEnd()

用计时器实现动画效果

pyglet库自带了计时器功能。首先,导入pyglet.clock模块 (有点像pygame)。

from pyglet import clock

通过clock模块中的schedule_interval函数,可以设定计时器间隔。这里程序每隔0.02秒,调用一次animate函数。在animate函数中再加入实现动画的代码。

def animate(event):
    global centerx
    centerx+=1
    xpos=lst_pos[0][0]
    lst_pos[0]=(xpos+1,0,0)
    on_draw() # 重新绘制

# 每隔0.02秒,调用一次animate函数
clock.schedule_interval(animate, 0.02)

主程序实现

主程序随机生成多个心形, 类似游戏中使用的过程生成技术。

# 随机生成多个心形
lst_pos = [(0,0,0)] # 中心的心形
for i in range(20):
    lst_pos.append((randint(-200,200),randint(-200,200),randint(-200,200)))
glClearColor(0.8, 1, 1, 1)
glEnable(GL_DEPTH_TEST) # 开启深度(z排序), 使程序支持近的物体遮挡远的物体
glEnable(GL_BLEND) # 开启透明支持
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
pyglet.app.run()

学习了这么多, 应该可以编写自己的简易3D游戏了吧! 欢迎点赞、收藏。

源代码见作者的gitcode:gitcode.net/qfcy_/python/-/tree/master/opengl。
其中还有作者的其他3D程序,下面是星空程序(space.py)的截图:
python立体爱心,Python,3D图形绘制,python,3d,图形渲染,游戏引擎,OpenGL文章来源地址https://www.toymoban.com/news/detail-692686.html

到了这里,关于Python pyglet 自制3D引擎入门(二) -- 绘制立体心形,动画和相机控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Python从零到壹] 七十二.图像识别及经典案例篇之OpenGL入门及绘制基本图形和3D图

    十月太忙,还是写一篇吧!祝大家1024节日快乐O(∩_∩)O 欢迎大家来到“Python从零到壹”,在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解,真心想把自己近十年的编程经验分享给大家

    2024年02月06日
    浏览(38)
  • 3D科研绘图与学术图表绘制:从入门到精通

    💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】 🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】 💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 3D科研绘图和学术图表绘制是科研和学术领域中不可或缺的一部分,可以帮助研究

    2024年02月08日
    浏览(34)
  • 3D引擎新势力,带你1分钟快速入门AMRT3D

    “ AMRT3D是由眸瑞科技出品的一款专业的轻量化图形引擎,一个互动性的3D场景搭建与全场景渲染工具,能够快速、轻松使用它来制作3D项目和应用,具有惊人的视觉效果,并具有无感知轻量化优势,场景加载快速且兼容性强,可以减少创建3D项目所需的成本和时间。 使用AMRT

    2024年02月22日
    浏览(26)
  • PCL三维点云中的立体框映射到二维图像(在图像中绘制立体框)

    三维点云与图像的映射,或者说是将三维点云中的点与二维图像中的某一个像素点进行对应。那么这么做的目的是什么呢?用途是什么呢“ 目的 :目的就是将三维点与二维图像之间的映射关系 作用 : 1、可以给点云赋予彩色信息,增强点云所表达物体或对象的辨识度;2、可

    2024年02月13日
    浏览(27)
  • ECharts: 绘制立体柱状图【圆柱体】

    其中里面的柱体渐变色是通过 ECharts中内置的渐变色生成器 echarts.graphic.LinearGradient 可以用来设置渐变色. Documentation - Apache ECharts

    2024年02月13日
    浏览(37)
  • 自制游戏引擎

    这是一个玩具 SmallEngine是引擎的核心模块,封装渲染功能和场景管理功能等 Editor是编辑器,类似unity和ue编辑器,能够动态添加对象和组件 Sandbox是游戏播放器,能够运行游戏 参考 https://www.bilibili.com/video/BV1KE41117BD/?spm_id_from=333.788.recommend_more_video.0vd_source=be4b42409fb0d5ad1e1bd5a5715b7da0 引

    2024年02月13日
    浏览(29)
  • python绘制3D条形图

    python条形图系列: 带有误差棒的条形图💎 分组条形图💎 3D条形图 尽管在matplotlib支持在一个坐标系中绘制多组条形图,效果如下 其中,蓝色表示中国,橘色表示美国,绿色表示欧盟。从这个图就可以非常直观地看出,三者自2018到2022年的GDP变化情况。但相比之下,通过增加

    2024年02月15日
    浏览(28)
  • Python绘制3D曲面图

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在数据可视化的世界中,3D曲面图是一种强大的工具,能够将复杂的数据模式以清晰直观的方式展现出来。Python提供了多种库和工具,使得创

    2024年04月28日
    浏览(22)
  • 自制游戏引擎之shader预编译

    shader预编译为二进制,在程序运行时候加载,可以提升性能,节省启动时间. third_party文件里需要放依赖的第三方 因为电脑访问google的问题,无法通过 shaderc-2023.4utilsgit-sync-deps 脚本自动下载第三方,手动下载 https://codeload.github.com/KhronosGroup/SPIRV-Tools/zip/refs/tags/v2023.3.rc1 https://codeloa

    2024年02月13日
    浏览(30)
  • WebGL入门之基于WebGL的3D可视化引擎介绍

    WebGL(Web Graphics Library)是一个JavaScript API,用于在任何兼容的Web浏览器中渲染高性能交互式3D和2D图形,而无需使用插件。WebGL通过引入一个非常符合OpenGL ES 2.0的API来实现这一点,该API可以在HTML 元素中使用。这种一致性使 API 可以利用用户设备提供的硬件图形加速。WebGL完全集

    2024年02月11日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包