KIVY 3D Rotating Monkey Head¶

news2024/11/19 6:25:26

3D Rotating Monkey Head — Kivy 2.3.0 documentation

KIVY  3D Rotating Monkey Head¶
kivy   3D 旋转猴子头

pic0

This example demonstrates using OpenGL to display a rotating monkey head. This includes loading a Blender OBJ file, shaders written in OpenGL’s Shading Language (GLSL), and using scheduled callbacks.
这个例子展示了如何使用OpenGL来显示一个旋转的猴子头部。这包括加载一个来自Blender的OBJ文件、使用OpenGL着色语言(GLSL)编写的着色器,以及使用计划好的回调函数。

The monkey.obj file is an OBJ file output from the Blender free 3D creation software. The file is text, listing vertices and faces and is loaded using a class in the file objloader.py. The file simple.glsl is a simple vertex and fragment shader written in GLSL.

monkey.obj文件是一个OBJ格式的文件,这个文件是由免费的3D创作软件Blender输出的。该文件是文本格式的,列出了顶点和面,并通过objloader.py文件中的一个类来加载。simple.glsl文件是一个简单的顶点和片元着色器,使用GLSL编写。

具体来说:

  1. OBJ文件:OBJ文件是一种标准的3D模型文件格式,它定义了物体的几何体,包括顶点、面、纹理坐标等信息。在这个例子中,monkey.obj文件包含了猴子头部的几何信息,用于在OpenGL环境中渲染。

  2. Blender:Blender是一款开源的3D图形软件,支持从建模、动画、材质、渲染、到音频处理、视频编辑等一系列的3D创作流程。用户可以在Blender中创建3D模型,并将其导出为OBJ等格式,供其他软件使用。

  3. objloader.py:这是一个Python脚本文件,其中定义了一个类,用于加载和解析OBJ文件。它读取文件中的顶点、面等数据,并将这些数据转换为OpenGL可以使用的格式。

  4. GLSL(OpenGL Shading Language):GLSL是一种用于OpenGL的高级着色语言,它允许开发者编写用于图形渲染的顶点和片元着色器。在这个例子中,simple.glsl文件包含了两个着色器程序:一个顶点着色器和一个片元着色器。顶点着色器处理顶点的变换,而片元着色器则负责计算每个像素的颜色。

  5. OpenGL:OpenGL是一个跨语言、跨平台的编程接口,用于渲染2D、3D矢量图形。它广泛用于CAD、虚拟现实、科学可视化程序和电子游戏开发等领域。在这个例子中,OpenGL被用来渲染加载的猴子头部模型,并使其旋转。

  6. 回调函数:在OpenGL程序中,回调函数通常用于处理如窗口大小改变、键盘输入或定时器事件等异步事件。在这个例子中,回调函数可能被用来更新猴子头部的旋转角度,并在每次渲染循环中重新绘制它。

File 3Drendering/main.py

'''
3D Rotating Monkey Head
========================

This example demonstrates using OpenGL to display a rotating monkey head. This
includes loading a Blender OBJ file, shaders written in OpenGL's Shading
Language (GLSL), and using scheduled callbacks.

The monkey.obj file is an OBJ file output from the Blender free 3D creation
software. The file is text, listing vertices and faces and is loaded
using a class in the file objloader.py. The file simple.glsl is
a simple vertex and fragment shader written in GLSL.
'''

from kivy.app import App
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.resources import resource_find
from kivy.graphics.transformation import Matrix
from kivy.graphics.opengl import glEnable, glDisable, GL_DEPTH_TEST
from kivy.graphics import RenderContext, Callback, PushMatrix, PopMatrix, \
    Color, Translate, Rotate, Mesh, UpdateNormalMatrix
from objloader import ObjFile


class Renderer(Widget):
    def __init__(self, **kwargs):
        self.canvas = RenderContext(compute_normal_mat=True)
        self.canvas.shader.source = resource_find('simple.glsl')
        self.scene = ObjFile(resource_find("monkey.obj"))
        super(Renderer, self).__init__(**kwargs)
        with self.canvas:
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)
        Clock.schedule_interval(self.update_glsl, 1 / 60.)

    def setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def update_glsl(self, delta):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.canvas['projection_mat'] = proj
        self.canvas['diffuse_light'] = (1.0, 1.0, 0.8)
        self.canvas['ambient_light'] = (0.1, 0.1, 0.1)
        self.rot.angle += delta * 100

    def setup_scene(self):
        Color(1, 1, 1, 1)
        PushMatrix()
        Translate(0, 0, -3)
        self.rot = Rotate(1, 0, 1, 0)
        m = list(self.scene.objects.values())[0]
        UpdateNormalMatrix()
        self.mesh = Mesh(
            vertices=m.vertices,
            indices=m.indices,
            fmt=m.vertex_format,
            mode='triangles',
        )
        PopMatrix()


class RendererApp(App):
    def build(self):
        return Renderer()


if __name__ == "__main__":
    RendererApp().run()

File 3Drendering/objloader.py

class MeshData(object):
    def __init__(self, **kwargs):
        self.name = kwargs.get("name")
        self.vertex_format = [
            (b'v_pos', 3, 'float'),
            (b'v_normal', 3, 'float'),
            (b'v_tc0', 2, 'float')]
        self.vertices = []
        self.indices = []

    def calculate_normals(self):
        for i in range(len(self.indices) / (3)):
            fi = i * 3
            v1i = self.indices[fi]
            v2i = self.indices[fi + 1]
            v3i = self.indices[fi + 2]

            vs = self.vertices
            p1 = [vs[v1i + c] for c in range(3)]
            p2 = [vs[v2i + c] for c in range(3)]
            p3 = [vs[v3i + c] for c in range(3)]

            u, v = [0, 0, 0], [0, 0, 0]
            for j in range(3):
                v[j] = p2[j] - p1[j]
                u[j] = p3[j] - p1[j]

            n = [0, 0, 0]
            n[0] = u[1] * v[2] - u[2] * v[1]
            n[1] = u[2] * v[0] - u[0] * v[2]
            n[2] = u[0] * v[1] - u[1] * v[0]

            for k in range(3):
                self.vertices[v1i + 3 + k] = n[k]
                self.vertices[v2i + 3 + k] = n[k]
                self.vertices[v3i + 3 + k] = n[k]


class ObjFile:
    def finish_object(self):
        if self._current_object is None:
            return

        mesh = MeshData()
        idx = 0
        for f in self.faces:
            verts = f[0]
            norms = f[1]
            tcs = f[2]
            for i in range(3):
                # get normal components
                n = (0.0, 0.0, 0.0)
                if norms[i] != -1:
                    n = self.normals[norms[i] - 1]

                # get texture coordinate components
                t = (0.0, 0.0)
                if tcs[i] != -1:
                    t = self.texcoords[tcs[i] - 1]

                # get vertex components
                v = self.vertices[verts[i] - 1]

                data = [v[0], v[1], v[2], n[0], n[1], n[2], t[0], t[1]]
                mesh.vertices.extend(data)

            tri = [idx, idx + 1, idx + 2]
            mesh.indices.extend(tri)
            idx += 3

        self.objects[self._current_object] = mesh
        # mesh.calculate_normals()
        self.faces = []

    def __init__(self, filename, swapyz=False):
        """Loads a Wavefront OBJ file. """
        self.objects = {}
        self.vertices = []
        self.normals = []
        self.texcoords = []
        self.faces = []

        self._current_object = None

        material = None
        for line in open(filename, "r"):
            if line.startswith('#'):
                continue
            if line.startswith('s'):
                continue
            values = line.split()
            if not values:
                continue
            if values[0] == 'o':
                self.finish_object()
                self._current_object = values[1]
            # elif values[0] == 'mtllib':
            #    self.mtl = MTL(values[1])
            # elif values[0] in ('usemtl', 'usemat'):
            #    material = values[1]
            if values[0] == 'v':
                v = list(map(float, values[1:4]))
                if swapyz:
                    v = v[0], v[2], v[1]
                self.vertices.append(v)
            elif values[0] == 'vn':
                v = list(map(float, values[1:4]))
                if swapyz:
                    v = v[0], v[2], v[1]
                self.normals.append(v)
            elif values[0] == 'vt':
                self.texcoords.append(list(map(float, values[1:3])))
            elif values[0] == 'f':
                face = []
                texcoords = []
                norms = []
                for v in values[1:]:
                    w = v.split('/')
                    face.append(int(w[0]))
                    if len(w) >= 2 and len(w[1]) > 0:
                        texcoords.append(int(w[1]))
                    else:
                        texcoords.append(-1)
                    if len(w) >= 3 and len(w[2]) > 0:
                        norms.append(int(w[2]))
                    else:
                        norms.append(-1)
                self.faces.append((face, norms, texcoords, material))
        self.finish_object()


def MTL(filename):
    contents = {}
    mtl = None
    return
    for line in open(filename, "r"):
        if line.startswith('#'):
            continue
        values = line.split()
        if not values:
            continue
        if values[0] == 'newmtl':
            mtl = contents[values[1]] = {}
        elif mtl is None:
            raise ValueError("mtl file doesn't start with newmtl stmt")
        mtl[values[0]] = values[1:]
    return contents

File 3Drendering/simple.glsl

/* simple.glsl

simple diffuse lighting based on laberts cosine law; see e.g.:
    http://en.wikipedia.org/wiki/Lambertian_reflectance
    http://en.wikipedia.org/wiki/Lambert%27s_cosine_law
*/
---VERTEX SHADER-------------------------------------------------------
#ifdef GL_ES
    precision highp float;
#endif

attribute vec3  v_pos;
attribute vec3  v_normal;

uniform mat4 modelview_mat;
uniform mat4 projection_mat;

varying vec4 normal_vec;
varying vec4 vertex_pos;

void main (void) {
    //compute vertex position in eye_space and normalize normal vector
    vec4 pos = modelview_mat * vec4(v_pos,1.0);
    vertex_pos = pos;
    normal_vec = vec4(v_normal,0.0);
    gl_Position = projection_mat * pos;
}


---FRAGMENT SHADER-----------------------------------------------------
#ifdef GL_ES
    precision highp float;
#endif

varying vec4 normal_vec;
varying vec4 vertex_pos;

uniform mat4 normal_mat;

void main (void){
    //correct normal, and compute light vector (assume light at the eye)
    vec4 v_normal = normalize( normal_mat * normal_vec ) ;
    vec4 v_light = normalize( vec4(0,0,0,1) - vertex_pos );
    //reflectance based on lamberts law of cosine
    float theta = clamp(dot(v_normal, v_light), 0.0, 1.0);
    gl_FragColor = vec4(theta, theta, theta, 1.0);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习筑基篇,​Ubuntu 24.04 快速安装 PyCharm IDE 工具,无需激活!

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] Ubuntu 24.04 快速安装 PyCharm IDE 工具 描述:虽然在之前我们安装了VScode,但是其对于使用Python来写大型项目以及各类配置还是比较复杂的,所以这里我们还是推…

docker buildx 交叉编译设置

dockerd配置文件 /etc/docker/daemon.json设置: rootubuntu:/etc/docker# cat daemon.json {"insecure-registries":["localhost:5000","127.0.0.1:5000","172.16.67.111:5000"],"features": {"buildkit&…

三、数据库系统(考点篇)

1、三级模式一两级映像 内模式:管理如何存储物理的 数据 ,对数据的存储方式、优化、存放等。 模式:又称为概念模式, 就是我们通常使用的表这个级别 ,根据应用、需求将物理数据划分成一 张张表。 外模式:…

springboot出租房租赁系统-计算机毕业设计源码80250

摘 要 随着城市化进程的不断推进,人口流动日益频繁,住房租赁需求逐渐增加。为了更好地满足人们对住房租赁服务的需求,本论文基于Spring Boot框架,设计并实现了一套出租房租赁系统。 首先,通过对市场需求和现有系统的调…

职升网:中级统计师是否属于中级职称?

中级统计师确实属于中级职称。 在统计专业人员的职称体系中,中级统计师占据了重要的位置,它属于中级职称范畴。这个职称体系包括初级、中级、高级和正高级四个层次,每个层次都对应着不同的专业技术岗位等级。初级职称只设助理级,…

Podman 深度解析

目录 引言Podman 的定义Podman 的架构Podman 的工作原理Podman 的应用场景Podman 在 CentOS 上的常见命令实验场景模拟总结 1. 引言 随着容器化技术的发展,Docker 已成为容器管理的代名词。然而,由于 Docker 的一些局限性,如需要守护进程和 …

昇思25天学习打卡营第08天|模型训练

模型训练 模型训练一般分为四个步骤: 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 现在我们有了数据集和模型后,可以进行模型的训练与评估。 ps:这里的训练和Stable Diffusion中的训练是一样…

BUUCTF - Basic

文章目录 1. Linux Labs 【SSH连接漏洞】2. BUU LFI COURSE【文件包含漏洞】3. BUU BRUTE【暴力破解用户名密码】4. BUU SQL COURSE【SQL注入-当前数据库】5. Upload-Labs-Linux 1【文件上传漏洞】7. Buu Upload Course 1【文件上传包含漏洞】8. sqli-labs 1【SQL注入-服务器上…

【论文笔记】BEVCar: Camera-Radar Fusion for BEV Map and Object Segmentation

原文链接:https://arxiv.org/abs/2403.11761 0. 概述 本文的BEVCar模型是基于环视图像和雷达融合的BEV目标检测和地图分割模型,如图所示。模型的图像分支利用可变形注意力,将图像特征提升到BEV空间中,其中雷达数据用于初始化查询…

Linux 进程间的信号

1.信号的初认识 信号是进程之间事件异步通知的一种方式,属于软中断。通俗来说信号就是让用户或进程给其他用户和进程发生异步信息的一种方式。对于信号我们可以根据实际生活,对他有以下几点认识:1.在没有产生信号时我们就知道产生信号要怎么处…

C++:特殊类的设计(无线程)

目录 一、设计一个不能拷贝类 二、设计一个只能在堆上创建对象的类 方法一:析构函数私有化 方法二:构造函数私有化 三、设计一个只能在栈上创建对象的类 四、设计一个类不能被继承 五、设计一个只能创建一个对象的类(单例模式&#xf…

加盖骑缝章软件、可以给PDF软件加盖自己的骑缝章

加盖骑缝章的软件多种多样,尤其是针对PDF文件,有多种软件可以实现给PDF文件加盖自己的骑缝章。以下是一些常用的软件及其特点: 1. Adobe Acrobat Pro DC 特点: 多功能PDF编辑:Adobe Acrobat Pro DC是一款功能强大的…

开发必备基础知识【Linux环境变量文件合集】

开发必备基础知识【Linux环境变量文件合集】 在Linux系统中,环境配置文件用于定制用户的Shell环境,包括定义环境变量、设置命令别名、定义启动脚本等。不同的Shell(如bash、zsh)有着各自对应的配置文件。 .bashrc:每新…

【推荐图书】深入浅出Spring Boot 3.x

推荐原因 这部SpringBoot3.x经典之作,时隔六年迎来重磅升级! 适合java开发相关读者 购买链接 商品链接:https://item.jd.com/14600442.html 介绍 书名:深入浅出Spring Boot 3.x ISBN:978-7-115-63282-1/ 作者&…

C语言之Const关键字与指针

目录 1 前言2 变量与指针的储存方式3 const int *var;int *const var;const int *const var;理解与区分4 总结 1 前言 实际开发过程中经常遇到const关键字作用于指针的情况,例如:const int *var;int *const var;const…

红薯小眼睛接口分析与Python脚本实现

文章目录 1. 写在前面2. 接口分析3. 算法脚本实现 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Py…

比 PIP 快 100 倍的安装工具

uv 是一个由 Rust 开发的 pip 工具,比 pip 快 100 倍,难以置信,不过真的是快太多了。 安装 在 Mac 上直接通过 brew install uv 安装即可。 venv 创建运行环境,默认当前目录下 .venv uv venv 依赖安装 uv pip install -r re…

Java | Leetcode Java题解之第217题存在重复元素

题目&#xff1a; 题解&#xff1a; class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> set new HashSet<Integer>();for (int x : nums) {if (!set.add(x)) {return true;}}return false;} }

谷粒商城学习笔记-14-项目结构创建提交到码云

一&#xff0c;码云上创建工程仓库 1&#xff0c;,点击右上角加号&#xff0c;选择新建仓库 2&#xff0c;填充必要信息 ①仓库名称&#xff0c;可以理解为工程名称。 ②仓库介绍&#xff0c;添加关于仓库的说明。 ③仓库权限设置&#xff0c;如果是公司项目&#xff0c;一般…

InnoDB内部结构

在mysql数据库中&#xff0c;InnoDB存储引擎是最为常用和强大的存储引擎之一。了解InnoDB的内存结构对于优化数据库的性能&#xff0c;提高系统的稳定性和扩展性至关重要。本文将深入探讨InnoDB的内存结构。 1.Buffer Pool Buffer Pool: 缓冲池&#xff0c;其作用是用来缓存表…