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

【3D编程技巧】如何用四元数旋转矢量在相机空间进行光照计算

这里介绍一个小TIPS,很久没有这么有成就感了。我以前在学3D数学的时候,书上就有一句话,说你把矢量这些东西用久了,就应该形成一种“直觉”,仿佛这些东西就是你的左右手一样。而这次,我居然真的用“直觉”来解决问题了,可以说是“瞎猫碰到死耗子”式的解决问题方法:

(一)问题起因

我现在在写的是一个软件光栅化的引擎。在软件光栅化的阶段,有两个地方可以进行光照渲染,一个是在世界空间下进行,一个是在相机空间下进行。在世界空间下进行会很方便,因为光照并不涉及旋转,而只是涉及平移。但是,因为矩阵乘法可以结合,所以从物体空间变换到世界空间再变换到相机空间,这两个矩阵可以合二为一,因为我是写软件光栅化,所以节约一些算力是有必要的。

 (二)矢量旋转的问题

我有一个平行光。平行光是没有距离的,只有方向,这个方向用一个矢量(像Vector3(1,1,1)这样)。但在旋转中有两个问题:

1、矢量的旋转不像点的旋转。顶点是可以通过矩阵进行旋转的,但是矢量不行。虽然在数学上矢量和点都是等价的。但是因为旋转属于非线性变换,所以最终在数学上的结果(归一化)之后,这个矢量方向其实不是你想要的矢量。

2、从世界空间到相机空间的旋转,其实是一个旋转的逆运算。也就是说,相机的Rotation,不是将世界空间按这个Rotation旋转,而是要做逆旋转。

(三)解决的过程

当时我想了一些歪门邪道。开始的时候我尝试用两个点记录位置。比如将矢量转化为P1和P2。然后使用这P1和P2进行相机旋转,因为P1和P2就是两个点,点旋转之后,之间的位置关系是不变的。在旋转之后,再取这两个点计算矢量方向。理论上应该可行,但不知道为什么失败了。

后来我将角度反转,然后进行四元数的矢量旋转乘法,四元数的矢量乘法公式如下:

V=要变换的矢量(要进行齐次变化,W设置为0),Q=旋转的四元数,Q-1=四元数的逆

V = Q * V * (Q-1)

没到想居然成功了。这样得到的矢量居然是可以用的。光照计算没有问题。但是为什么我说瞎猫碰到死耗子?因为在我的变换矩阵中有一个BUG。相机变换矩阵是按照XYZ三个轴进行变换的。我使用的是Unity的规则,按照Z-X-Y(Roll-Pitch-Yaw)的顺序变换。我在写相机变换矩阵的时候,也是这么写的。但是我忘记了,相机变换是一个逆变换,其实应该写成Y-X-Z变换的。其实先后顺序只是规则的问题,你怎么写,实际变换上也不会出错。所以我一开始没看出这个BUG。

但是后来我在进行相机的旋转控制的时候,我发现我的旋转控制有问题:在进行了Yaw的旋转之后,再使用Pitch会沿Y轴旋转,而不是在地平线旋转。虽然在数学上这没有问题,但做为玩家控制来说有大问题。这也是为什么Unity使用Z-X-Y旋转顺序的原因。

然后查出BUG之后,才知道是我的旋转搞错了。我就把旋转改了。但这样一改,原来那个我将角度反转之后,再利用四元数旋转的方法就失灵了,得到的是一个错误的结果。

(四)解决方法

这里就是靠“直觉”解决问题了。如果将角度反转没有作用,那么,将四元数的运算反转呢?这是一个突发奇想,我在教程,书里面都没有见过这种说法,所以我说“瞎猫碰到死耗子”,当然,这应该也有其它书里面说,只是我没看到而已。但总之这个思路解决了问题。只需要将四元数旋转的运算改变,就能够得到一个能成功变换到相机空间的矢量:

使用逆运算公式:V = (Q-1) * V * Q

// 旋转矢量
Vector3 RotateDirection(Vector direction, Quaternion rotation)
{Quaternion re(rotation.GetEular());Vector3 transDirection = re.RotateMulInverse(direction);return transDirection.Normalize();
}// 求四元数的逆
Quaternion Quaternion::GetInverse(void) const {// 这是四元数的长度// 因为四元数长度始终是单位1,所以其实这一步可以省,只要你确保它没发生蠕变float len = Magnitude(); return Quaternion(-x / len, -y / len, -z / len, w / len);
}// 四元数的乘法(正常)
Vector3 Quaternion::RotateMul(const Vector3& v) const {Quaternion vq(v.x, v.y, v.z, 0.0);Quaternion r = *this * vq * this->GetInverse();return Vector3(r.x, r.y, r.z);
}// 四元数的乘法(逆向)
Vector3 Quaternion::RotateMulInverse(const Vector3& v) const {Quaternion vq(v.x, v.y, v.z, 0.0);Quaternion r = this->GetInverse() * vq * (*this);return Vector3(r.x, r.y, r.z);
}

OK。以上就是解决方案了。

相关文章:

【3D编程技巧】如何用四元数旋转矢量在相机空间进行光照计算

这里介绍一个小TIPS,很久没有这么有成就感了。我以前在学3D数学的时候,书上就有一句话,说你把矢量这些东西用久了,就应该形成一种“直觉”,仿佛这些东西就是你的左右手一样。而这次,我居然真的用“直觉”来…...

ICMP 和 IGMP 的区别

ICMP 和 IGMP 协议 IP 层分支图 ICMP(Internet Control Message Protocol,因特网控制信息协议) 用于补充 IP 传输数据报的过程中,发送主机无法确定数据报是否到达目标主机。 ICMP 报文分为出错报告报文和查询报文两种。 若数据…...

【Vue3】工程创建及目录说明

【Vue3】工程创建及目录说明 背景简介开发环境开发步骤及源码 背景 随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日…...

算法学习2——排序算法(2)

上一篇介绍了几种常见且使用较多的排序算法,本章主要是一个进阶内容,介绍三个较为复杂的算法。 计数排序 (Counting Sort) 计数排序是一种适用于范围较小的整数序列的排序算法。它通过统计每个元素的出现次数,然后依次输出元素,…...

嵌入式人工智能(9-基于树莓派4B的PWM-LED呼吸灯)

1、PWM简介 (1)、什么是PWM 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是在具有惯性的系统中利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制…...

python-NLP:1中文分词

文章目录 规则分词正向最大匹配法逆向最大匹配法双向最大匹配法 统计分词语言模型HMM模型 jieba分词分词关键词提取词性标注 规则分词 基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行…...

iOS 开发包管理之CocoaPods

CocoaPods(Objective-C 时期,支持Objective-C和swift),CocoaPods下载第三方库源代码后会将其编译成静态库.a 文件 或动态库框架.framework 文件 的形式,并将它们添加到项目中,建立依赖关系,这种…...

Windows搭建RTMP视频流服务器

参考了一篇文章,见文末。 博客中nginx下载地址失效,附上一个有效的地址: Index of /download/ 另外,在搭建过程中,遇到的问题总结如下: 1 两个压缩包下载解压并重命名后,需要 将nginx-rtmp…...

VS2019安装MFC组件

VS2019支持的MFC版本是mfc140 ~ mfc142版本,它兼容VS2015、VS2017之前的老版本程序。 一、MFC的历史版本 MFC的历史版本如下: IDE发布时间工具集版本MSC_VERMSVCMFC版本dllVisual C6.01998V601200MSVC6.06.0mfc42.dll、mfcce400.dllVisual Studio 2002…...

Python学习—open函数,json与pickle知识点,Os模块详解

目录 1. Open函数 2.json与pickle模块 json模块 1. json.dumps() 2. json.dump() 3. json.loads() 4. json.load() pickle 模块 1. pickle.dumps() 2. pickle.dump() 3. pickle.loads() 4. pickle.load() 3.Os模块 1. Open函数 在Python中,open() 函数…...

基于SSM的高考志愿选择辅助系统

基于SSM的高考志愿选择辅助系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台 前台首页 院校展示 后台 后台首页 学校管理 摘要 随着高考制度的不断完…...

引领小模型潮流!OpenAI发布功能强大且成本低的GPT-4o mini

GPT-4o mini的成本比GPT-3.5 Turbo低了超过60%,其聊天表现优于Google的Gemini Flash和Anthropic的Claude Haiku。该模型从周四开始对ChatGPT的免费用户、ChatGPT Plus用户和团队订阅用户开放,并将在下周向企业用户开放。OpenAI计划未来将图像、视频和音频…...

【考研数学】线代满分经验分享+备考复盘

我一战二战复习都听了李永乐的线代课,二战的时候只听了一遍强化,个人感觉没有很乱,永乐大帝的课逻辑还是很清晰的。 以下是我听向量这一章后根据听课内容和讲义例题总结的部分思维导图,永乐大帝讲课的时候也会特意点到线代前后联…...

Java项目:基于SSM框架实现的海鲜自助餐厅系统【ssm+B/S架构+源码+数据库+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的海鲜自助餐厅系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能…...

前端面试题日常练-day97 【Less】

题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末 在Less中,以下哪个功能用于处理文本字间距? a) letter-spacing() b) word-spacing() c) text-spacing() d) space-between() Less中的Variables可以存储哪些类型的值&#xff…...

压缩视频大小的方法 怎么减少视频内存大小 几个简单方法

随着4K、8K高清视频的流行,我们越来越容易遇到视频文件体积过大,导致存储空间不足、传输速度缓慢等问题。视频压缩成为解决这一问题的有效途径,但如何在减小文件大小的同时,保证视频质量不受影响呢?本文将为你揭晓答案…...

JVM:GraalVM

文章目录 一、介绍1、什么是GraalVM:2、GraalVM版本 二、两种使用模式 一、介绍 1、什么是GraalVM: GraalVM是Oracle官方推出的一款高性能JDK,使用它享受比OpenJDK或者OracleJDK更好的性能。GraalVM的官网地址:https://www.graa…...

海外营销推广:快速创建维基百科(wiki)词条-大舍传媒

一、维基百科的永久留存问题 许多企业和个人关心维基百科是否能永久留存。实际上,只要企业和个人的行为没有引起维基百科管理方的反感,词条就可以长期保存。如果有恶意行为或被投诉,维基百科可能会对词条进行删除或修改。 二、创建维基百科…...

【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理

【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理 在之前我们已经学习了页面布局相关的知识,绘制静态页面已经问题不大。那么今天来学习一下如何让页面动起来、并且结合所学完成一个代码实例。 交互 如果是为移动端开发应用,那么交…...

处理uniapp刷新后,点击返回按钮跳转到登录页的问题

在使用uniapp的原生返回的按钮时,如果没有刷新会正常返回到对应的页面,如果刷新后会在当前页反复横跳,或者跳转到登录页。那个时候我第一个想法时:使用浏览器的history.back()方法。因为浏览器刷新后还是可以通过右上角的返回按钮…...

PT插件配置完全指南:从基础到进阶的全方位解决方案

PT插件配置完全指南:从基础到进阶的全方位解决方案 【免费下载链接】PT-Plugin-Plus PT 助手 Plus,为 Microsoft Edge、Google Chrome、Firefox 浏览器插件(Web Extensions),主要用于辅助下载 PT 站的种子。 项目地址…...

别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码)

别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码) 在电机控制项目中,精确的速度测量往往是实现闭环控制的第一步。许多初学者会直接采用简单的M法(频率测量法),但在实际测试…...

Anaconda3重装避雷指南:Win11系统这些配置不删干净等于白装(2024实测)

Anaconda3重装避雷指南:Win11系统深度清理实战手册 为什么你的Anaconda重装总失败? 每次重装Anaconda后,那些熟悉的报错信息又阴魂不散地出现?"明明已经卸载干净了"——这是大多数数据科学从业者最常发出的困惑。实际上…...

Qwen3-4B写作大师实战:辅助程序员编写项目文档与技术方案

Qwen3-4B写作大师实战:辅助程序员编写项目文档与技术方案 1. 程序员文档写作的痛点与挑战 程序员在日常工作中需要编写大量技术文档,包括项目说明、API文档、技术方案、开发日志等。然而,许多开发者面临共同的写作难题: 技术思维与…...

CVXPY多目标优化终极指南:如何在复杂决策中找到最佳平衡点

CVXPY多目标优化终极指南:如何在复杂决策中找到最佳平衡点 【免费下载链接】cvxpy A Python-embedded modeling language for convex optimization problems. 项目地址: https://gitcode.com/gh_mirrors/cv/cvxpy CVXPY是一个嵌入Python的凸优化建模语言&…...

终极指南:Fn与云原生生态的完美集成,如何与Istio、Prometheus等工具无缝协作

终极指南:Fn与云原生生态的完美集成,如何与Istio、Prometheus等工具无缝协作 【免费下载链接】fn The container native, cloud agnostic serverless platform. 项目地址: https://gitcode.com/gh_mirrors/fn/fn Fn是一款容器原生的无服务器平台&…...

brpc配置中心高可用部署:集群配置与故障转移全攻略

brpc配置中心高可用部署:集群配置与故障转移全攻略 【免费下载链接】brpc brpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendat…...

深入理解栈溢出:我是如何通过CSAPP的AttackLab实验重新认识缓冲区安全的

深入理解栈溢出:从AttackLab实验看现代系统安全防御博弈 当我在深夜的实验室里第一次看到Segmentation fault提示时,并没有意识到这行简单的错误信息背后隐藏着怎样的安全危机。作为计算机系统安全领域最经典的漏洞类型,栈溢出攻击在过去三十…...

3步终极解放QQ音乐加密文件:QMCDecode全平台播放攻略

3步终极解放QQ音乐加密文件:QMCDecode全平台播放攻略 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默认转…...

UE4网络同步实战:AIController与RPC的避坑指南(含C++代码示例)

UE4网络同步实战:AIController与RPC的避坑指南(含C代码示例) 在多人联机游戏的开发中,网络同步始终是开发者面临的核心挑战之一。虚幻引擎4(UE4)提供了强大的网络框架,但其中AIController的服务…...