当前位置: 首页 > news >正文

WebGL模型矩阵

前言:依赖矩阵库 WebGL矩阵变换库_山楂树の的博客-CSDN博客 

先平移,后旋转的模型变换:

1.将三角形沿着X轴平移一段距离。

2.在此基础上,旋转三角形。

先写下第1条(平移操作)中的坐标方程式。

等式1:

< “平移” 后的坐标>  =  <平移矩阵> x <原始坐标>

然后对<平移后的坐标>进行旋转。

等式2:

< “平移后旋转” 后的坐标>  =  <旋转矩阵> x <平移后的坐标>

 当然你也可以分步计算这两个等式,但更好的方法是,将等式1代入到等式2中,把两个等式组合起来:

等式3:

< “平移后旋转” 后的坐标>  =  <旋转矩阵> x(<平移矩阵> x <原始坐标>)

这里:

 <旋转矩阵> x(<平移矩阵> x <原始坐标>)

等于(注意括号的位置):

(<旋转矩阵> x <平移矩阵>)x <原始坐标>

最后,我们可以在JavaScript中计算<旋转矩阵>×<平移矩阵>,然后将得到的矩阵传入顶点着色器。像这样,我们就可以把多个变换复合起来了。一个模型可能经过了多次变换,将这些变换全部复合成一个等效的变换,就得到了模型变换(model transformation),或称建模变换(modeling transformation),相应地,模型变换的矩阵称为模型矩阵(model matrix)。 

再来复习一下矩阵的乘法:

如上所示,将两个3×3矩阵A与B相乘的结果如下:

等式4:

 上式是两个3×3矩阵相乘的结果,实际用到的模型矩阵是4×4的矩阵。然而要注意,矩阵相乘的次序很重要,A*B的结果并不一定等于B*A。

下面就来看一下如何使用Matrix4对象进行矩阵乘法,从而将多个变换复合起来,实现先平移,然后旋转。

示例代码: 

var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'uniform mat4 u_ModelMatrix;\n' +'void main() {\n' +'  gl_Position = u_ModelMatrix * a_Position;\n' +'}\n';var FSHADER_SOURCE ='void main() {\n' +'  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +'}\n';function main() {var canvas = document.getElementById('webgl');var gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}var n = initVertexBuffers(gl);if (n < 0) {console.log('Failed to set the positions of the vertices');return;}// 创建Matrix4对象以进行模型变换var modelMatrix = new Matrix4();// 计算模型矩阵var ANGLE = 60.0; // 旋转角var Tx = 0.5;     // 平移距离modelMatrix.setRotate(ANGLE, 0, 0, 1);  // 设置模型矩阵为旋转矩阵modelMatrix.translate(Tx, 0, 0);        // 将模型矩阵乘以平移矩阵// 将模型矩阵传输给顶点着色器var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');if (!u_ModelMatrix) {console.log('Failed to get the storage location of u_xformMatrix');return;}gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);gl.clearColor(0, 0, 0, 1);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, n);
}function initVertexBuffers(gl) {var vertices = new Float32Array([0, 0.3,   -0.3, -0.3,   0.3, -0.3]);var n = 3; // The number of verticesvar vertexBuffer = gl.createBuffer();if (!vertexBuffer) {console.log('Failed to create the buffer object');return false;}gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);var a_Position = gl.getAttribLocation(gl.program, 'a_Position');if (a_Position < 0) {console.log('Failed to get the storage location of a_Position');return -1;}gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_Position);return n;
}

最关键的两行是如下两行,我们计算了<旋转矩阵>×<平移矩阵>:

解释模型矩阵: 

我们首先调用了包含set前缀的方法setRotate(),传入的参数用以计算旋转矩阵,并写入modelMatrix(上图第一行)。接下来,我们调用了不带set前缀的方法translate(),意思就是,先计算出一个平移矩阵,然后用原先存储在modelMatrix变量中的矩阵乘以这个新计算出的平移矩阵,将得到的结果写回modelMatrix中(上图第二行)。由于在第一步之后,modelMatrix已经包含了一个旋转矩阵。那么经过了这一步,modelMatrix中的矩阵就是<旋转矩阵>×<平移矩阵>了。

你可能会注意到,“先平移后旋转”的顺序与构造模型矩阵<旋转矩阵>×<平移矩阵>的顺序是相反的,这是因为变换矩阵最终要与三角形的三个顶点的原始坐标矢量相乘,再看一下等式3,你就明白了。

最后,我们把模型矩阵传给顶点着色器中的u_ModelMatrix变量,并如常将图形绘制出来。在浏览器中加载程序,你可以看到如下平移和旋转后的红色三角形。

先旋转,后平移的模型变换:

让我们修改一下示例程序,先进行旋转然后再平移。很简单,你只需交换旋转和平移的次序。在这个例子中,先调用含set前缀的方法setTranslate()进行平移操作,再调用不含set前缀的方法rotate()进行旋转。 

 如你所见,改变旋转和平移的次序之后,结果就不一样了。原理是显而易见的,如下图所示。

相关文章:

WebGL模型矩阵

前言&#xff1a;依赖矩阵库 WebGL矩阵变换库_山楂树の的博客-CSDN博客 先平移&#xff0c;后旋转的模型变换&#xff1a; 1.将三角形沿着X轴平移一段距离。 2.在此基础上&#xff0c;旋转三角形。 先写下第1条&#xff08;平移操作&#xff09;中的坐标方程式。 等式1&am…...

Flutter:WebSocket封装-实现心跳、重连机制

前言Permalink Flutter简介 Flutter 是 Google推出并开源的移动应用开发框架&#xff0c;主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App&#xff0c;一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口&#xff0c;开发者可以很快地为 F…...

c语言中:struct timespec

在C语言中&#xff0c;struct timespec 是一个结构体&#xff0c;通常用于处理时间和时间间隔。这个结构体通常包含以下两个成员&#xff1a; tv_sec&#xff1a;这是一个长整型&#xff08;long&#xff09;&#xff0c;用于存储秒数。它表示时间的整数部分&#xff0c;即秒数…...

Mendix如何实现导出文件

刚刚接触Mendix低代码两周&#xff0c;花了一周在b站看初级视频然后考完初级&#xff0c;第二周开始做个列表查询感觉照葫芦画瓢没啥难度。但最近要求写个导出列表数据&#xff0c;在mendix社区翻了翻&#xff0c;这个功能算是常见的。找了mendix官方提供的Docs磕磕盼盼才实现了…...

在IIS服务器上安装SSL证书(2023配置启用HTTPS部署教程)内容来源SSL市场网

https://www.sslmarket.com.cn/146.html...

如何处理ChatGPT与用户之间的互动和反馈?

处理ChatGPT与用户之间的互动和反馈是关于改进和优化用户体验的关键方面。这涉及到在聊天、对话和交互中建立积极的用户关系&#xff0c;同时利用用户的反馈来不断改进ChatGPT的性能和功能。本文将探讨如何有效地处理ChatGPT与用户之间的互动和反馈&#xff0c;以提供更好的用户…...

微服务-gateway鉴权

文章目录 一、前言二、gateway鉴权1、依赖配置2、编写代码3、GlobalFilter详解3.1、GlobalFilter简介3.2、GlobalFilter自定义执行顺序3.2.1、实现Order接口实现自定义执行顺序 一、前言 网关是介于客户端和服务器端之间的中间层&#xff0c;所有的外部请求都会先经过 网关这一…...

NET7快速开发一个商品管理模块-商品列表开发(一)

商品管理模块&#xff0c;一般包含以下几个模块&#xff1a; 商品列表&#xff1a;这里可以看到所有已发布的商品信息列表。 商品管理&#xff1a;添加商品、编辑商品以及删除商品。 具体功能如下图&#xff1a; 1.商品列表 2.添加商品 3.商品SKU编辑...

0829|C++day7 auto、lambda、C++数据类型转换、C++标准模板库(STL)、list、文件操作

一、思维导图 二、【试编程】将实例化类对象写入容器后&#xff0c;写入.txt文本中&#xff0c;再重新定义一个类容器&#xff0c;将.txt中的内容读取出来&#xff0c;输出到终端 封装一个学生的类&#xff0c;定义一个学生这样类的vector容器, 里面存放学生对象&#xff08;至…...

SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】

文章目录 一、数据库表二、引入依赖三、修改配置文件四、公共组件1、BaseController2、BaseService3、IService4、BaseMapper 五、代码1、Application2、Student实体类3、Controller4、Service5、ServiceImpl6、Mapper7、Mapper.xml 一、数据库表 CREATE TABLE student (id i…...

node基础之三:http 模块

// 1. 导入模块 const http require("http"); // 2. 创建服务 const server http.createServer((request, response) > {// 获取请求方法request.method;// 获取请求 url&#xff08;只包含url中的路径和查询字符串&#xff09;request.url;// 获取 HTTP 协议版…...

【高阶数据结构】AVL树 {概念及实现;节点的定义;插入并调整平衡因子;旋转操作:左单旋,右单旋,左右双旋,右左双旋;AVL树的验证及性能分析}

AVL树 一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明…...

Netty—FuturePromise

Netty—Future&Promise 一、JDK原生 Future二、Netty包下的 Future三、Promise1、使用Promise同步获取结果2、使用Promise异步获取结果.3、使用Promise同步获取异常 - sync & get4、使用Promise同步获取异常 - await5、使用Promise异步获取异常 在异步处理时&#xff0…...

固定资产卡片乱怎么管理

固定资产卡片是记录公司固定资产信息的重要工具&#xff0c;如果管理不善&#xff0c;容易造成卡片混乱、数据错误等问题。 为了避免这种情况的发生&#xff0c;可以采取以下措施&#xff1a;  建立完善的资产管理制度&#xff0c;明确固定资产的分类、标准和使用情况&#x…...

AutoHotkey(AHK)脚本,自动截图当前屏幕并发送给微信窗口

前提先安装好 AutoHotkey &#xff0c;本脚本依赖AutoHotkey 环境 首先 &#xff0c;设置微信的快捷键 执行代码如下&#xff1a; Loop {SendInput, {Alt down}s{Alt up}Sleep, 2000 ; 等待2秒; 双击鼠标左键Click, 2Sleep, 1000 ; 等待1秒SendInput, {Alt down}a{Alt up}Sl…...

Golang - go build打包文件

Go编译打包文件 1、简单打包 程序 main1.go&#xff1a; package mainimport "fmt"func main() {fmt.Println("Hello World!") } 打包&#xff1a; # 在linux服务上执行下面的3个命令 # linux平台,生成main1可执行程序 CGO_ENABLED0 GOOSlinux GOARCHam…...

Java的归并排序

不爱生姜不吃醋⭐️⭐️⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 &#x1f334;前言&#x1f334;一.归并排序1.概念2.时间复杂度3.代码实现 &#x1f334;二、小和问题1.概念2.举例3.代码实现 &#x1f334…...

B. The Walkway Codeforces Round 893 (Div. 2)

Problem - B - Codeforces 题目大意&#xff1a;小明在数轴上要从1走到n&#xff0c;其中某些坐标上有一些饼干店&#xff0c;共m个&#xff0c;小明身上也有无限多的饼干&#xff0c;它首先一定会在1的位置吃一个饼干&#xff0c;在每个饼干店的位置会吃一个&#xff0c;在前…...

第四篇 DirectShow 采集调用结构关系

第一篇: DirectShow视频采集_会头痛的可达鸭的博客-CSDN博客 一、GraphBuilder 1、IFilterGraph2、IGraphBuilder、ICaptureGraphBuiler2 (1)、CLSID IFilterGraph CLSID_FilterGraphIFilterGraph2 CLSID_CaptureGraphBuilderIGraphBuilder CL…...

2605. 从两个数字数组里生成最小数字

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;枚举比较法方法二&#xff1a;集合的位运算表示法 写在最后 Tag 【贪心】【位运算】【数组】 题目来源 2605. 从两个数字数组里生成最小数字 题目解读 给定两个各自只包含数字 1 到 9 的两个数组&#xff0c;每个数组…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...