用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”

备注:本系列文章介绍如何使用Python和OpenGL 4.5进行数据可视化的开发。因此请参考《准备工作(一)Windows下检测显卡和OpenGL信息》一文检测读者的电脑是否支持OpenGL 4.5版本(基本上2018年之后销售的电脑都可以支持OpenGL 4.5)。

再参考《准备工作(二)配置Windows下VS Code + Python + OpenGL开发环境》配置本文需要的开发环境)

前几节通过绘制三维坐标轴和三维立方体,我们已经初步了解了OpenGL如何通过一系列的数学变换,把三维世界的图形映射到了二维屏幕上(见下图):

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第1张图片

本节我们详细讨论视图矩阵和投影矩阵。如上图所示,作为开发人员,我们需要自己完成前四步的空间变换,OpenGL只需要程序开发人员提供几个变换矩阵给它,正如前几节顶点着色器中的如下代码:

gl_Position = projection * view * model * vec4(position, 1.0);
之后OpenGL会完成后两步的变换。

“照相机”和“照相机空间”是人类参考人眼成像的过程抽象出来的概念,从而便于进行数学变换:

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第2张图片

还是通过代码的实践来帮助我们的理解。

运行VS Code,选择File菜单里“Open Folder”,打开D:\pydev\pygl,在basic文件夹下新建一个camera_app.py文件

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第3张图片

在camera_app.py输入以下代码:

import sys
parent_dir = "../pygl"
sys.path.append(parent_dir)
import ctypes
import OpenGL.GL as gl
import glm
import imgui
import numpy as np
import pygl
from common import App, AxesHelper, Cube

class CameraApp(App):
    # 初始化着色器,vao vbo等
    def setupVertex(self) -> None:
        gl.glEnable(gl.GL_DEPTH_TEST)
        self.background_color = glm.vec4(0.3, 0.3, 0.3, 1.0)
        self.cube = Cube(0.4, "textures/cratetex.png")
        self.cube_axes = AxesHelper(0.6, 5.0)
        self.world_axes = AxesHelper(0.9, 2.0)
        self.imgui_window_width = 250
        self.imgui_window_height = 450
        self.initCamera()

    def initCamera(self) ->None:
        self.camera_position = glm.vec3(0.0, 0.0, 3.0)
        self.camera_target = glm.vec3(0.0, 0.0, 0.0)
        self.camera_fov = 45.0
        self.camera_aspect = float(self.width)/self.height
        self.camera_near = 1.0
        self.camera_far = 6.0

    # 配置imgui界面元素
    def showImGui(self)->None:
        # 增加ImGui窗口的透明度
        imgui_style = imgui.get_style()
        color = imgui_style.colors[imgui.COLOR_WINDOW_BACKGROUND]
        imgui_style.colors[imgui.COLOR_WINDOW_BACKGROUND] = imgui.Vec4(color.x, 
                                                    color.y, color.z, 0.6)
        imgui.begin("照相机设置")
        _, self.cube.use_vertex_color = imgui.checkbox("使用顶点颜色", 
                                                self.cube.use_vertex_color)
        if imgui.button("重置"):
            self.initCamera()
        _, pos = imgui.slider_float3("位置", self.camera_position.x, 
                    self.camera_position.y, self.camera_position.z, 0.0, 10.0)
        self.camera_position = glm.vec3(pos)
        _, tg = imgui.slider_float3("目标", self.camera_target.x, 
                        self.camera_target.y, self.camera_target.z, -0.5, 0.5)
        self.camera_target = glm.vec3(tg)
        _, self.camera_fov = imgui.slider_float("视野", self.camera_fov,5, 170)
        _, self.camera_near = imgui.slider_float("近面", self.camera_near,1.0, 10.0)
        _, self.camera_far = imgui.slider_float("远面", self.camera_far,1.0, 10.0)
        imgui.text("视图矩阵")
        imgui.begin_table("view data", 4)
        for i in range(4):
            imgui.table_next_row()
            for j in range(4):
                imgui.table_next_column()
                imgui.text(str("{:.3f}").format(self.view[j, i]))
        imgui.end_table()
        imgui.text("投影矩阵")
        imgui.begin_table("projection data", 4)
        for i in range(4):
            imgui.table_next_row()
            for j in range(4):
                imgui.table_next_column()
                imgui.text(str("{:.3f}").format(self.projection[j, i]))
        imgui.end_table()
        imgui.end()       

    # 渲染图形
    def render(self) -> None:
        gl.glClearBufferfv(gl.GL_COLOR, 0, self.background_color.to_tuple())
        gl.glClearBufferfv(gl.GL_DEPTH, 0, 1.0)
        self.view = glm.lookAt(self.camera_position, self.camera_target, 
                               glm.vec3(0.0, 1.0, 0.0))
        self.projection = glm.perspective(glm.radians(self.camera_fov), 
                            self.camera_aspect, self.camera_near, self.camera_far)
        self.cube.updateModelMatrix()
        self.cube.render(self.view,self.projection)
        self.cube_axes.model_matrix = self.cube.model_matrix
        self.cube_axes.render(self.view, self.projection)
        self.world_axes.render(self.view, self.projection)

    # 释放资源
    def cleanup(self) -> None:
        self.cube.delete()
        self.cube_axes.delete()
        self.world_axes.delete()

if __name__ == "__main__":
    app = CameraApp(100, 100, 800, 800, "你好,照相机App!")
    app.run()

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第4张图片

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第5张图片

点击VS Code右上角的三角形图标,运行代码,结果如下:

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第6张图片

“位置”旁边的三个滑动条分别代表了照相机在X、Y、Z三个方向上的坐标,拖动鼠标就可以改变照相机的观察位置,同时视图矩阵就会发生相应的变化。

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第7张图片

“目标”旁边的三个滑动条分别代表了照相机观察的目标中心位置的X、Y、Z坐标,拖动鼠标就可以改变照相机的观察目标位置,同时视图矩阵也会发生相应的变化。

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第8张图片

“视野”、“近面”、“远面”旁边的滑动条分别代表了照相机投影变换中的几个参数,可以改变投影矩阵,下图是近平面和远平面裁剪了部分立方体时的截图:

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第9张图片

点击“使用顶点颜色”可以让立方体在彩色模式和纹理模式之间切换

用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”_第10张图片

可以任意时刻用鼠标点击重置,可以让照相机回到初始设置。

以上就是“用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞””的全部内容,希望对你有所帮助。

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、Python必备开发工具

img

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

五、Python练习题

检查学习结果。

img

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

img

最后祝大家天天进步!!

上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。

你可能感兴趣的:(python,信息可视化,开发语言)