首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查找四元数,表示从一个向量到另一个向量的转换

查找四元数,表示从一个向量到另一个向量的转换
EN

Stack Overflow用户
提问于 2019-04-01 18:41:56
回答 1查看 972关注 0票数 3

简介。

在此之前,我曾使用提出一个问题将rgb三元组转换为四元数。在这个问题之后,我设法得到了单位四元数,但我怀疑他们的内部结构。没有容易的方法来操作它们,并分离卢马和色度,因为这是单位长度的四元数。根据我对它的感觉,亮度应该被编码在一个真实的部分,或者整个幅值;颜色的“色度”信息应该被编码在想象的部分。

今天,我决定改进一下,采取另一种方法,不同于上面链接中的第一种方法。我认为它可以成功,因为四元数不仅可以存储旋转(单位四元数),而且还可以存储规模。首先是第一件事,所以我将首先解释我的下一个想法。我将在下面的解释中使用GLSL着色器语法。

方法描述和问题体。

对于图像的某些像素,让我们在单位立方体中构造一个三维矢量vec3 u,其中正坐标位于封闭范围0.0,1.0,并且表示整个rgb颜色空间。因此,现在u的坐标、u.xu.yu.z将相应地表示该像素的红色、绿色和蓝色值。然后,让我们取一个纯白色矢量const vec3 v = vec3(1.0, 1.0, 1.0);。让我们定义一些四元数q,这样我们的向量u是"v,旋转和缩放的四元数q“。简单地说,q必须回答“如何转换v__,以获得最初构想的颜色u__?”这个问题。让我们介绍一下“旋转和缩放”操作的功能:vec3 q2c(in vec4 q, in vec3 v)。我称之为“四元数到彩色”转换器。

编写q2c(q, v)非常简单,如所定义q2c(q, v) == (q*vec4(v, 0.0))*q'。在这里,"*“运算符表示四元数乘法;让它成为一个函数vec4 qmul(in vec4 q1, in vec4 q2)。"q'“指的是q共轭,让它变成vec4 qconj(in vec4 q)。省略它们的简单实现(您可以在完整的源代码中找到),我们就可以看到经典的代码:

代码语言:javascript
复制
vec4 q2c(in vec4 q, in vec3 v) {
    return qmul(qmul(q, vec4(v, 0.0)), qconj(q));
}

现在我们有了q2c(q,v)函数,它通过旋转和缩放选择的三维矢量v,将四元数q转换成颜色。

问题是如何找到四元数q**?**

从程序员的角度来看,目标是编写反向函数vec4 c2q(in vec3 u, in vec3 v) --对应的“颜色到四元数”转换器。

请注意,您不应该触摸q2c(),没有一个真正的好理由。例如,一个严重的错误,在其逻辑,导致“不可能解决任务”,你可以证明这一点。

如果你的答案是正确的,你怎么能核实?

实际上,如果您能够前后转换,那么检查方法将产生于这样一个事实:您将得到初始值。因此,对于任何非零长度的v**,** u ,检查条件是必须始终等于 q2c(c2q(u, v), v).。v必须具有非零长度,因为不能“缩放零”才能得到“某物”。

为了简单起见,我使用测试程序服务编写了shadertoy.com。

你需要一台像样的电脑,有可工作的互联网连接和支持webGL的网络浏览器(我正在使用Chrome)。程序应该工作在任何GPU,甚至嵌入英特尔的处理器。它甚至可以在我的低端智能手机上工作!

为了测试您的答案,您应该将用GLSL语法编写的公式放在c2q()函数中。然后按“应用”按钮,您的更改将生效:

左边的图像表示一些未更改的源像素。右半部分将包含像素,由q2c(c2q())前后转换。显然,一半必须在视觉上相等,你不应该注意到任何垂直线。一个小的数学误差(不明显)可能会出现,但只是由于浮点的性质-其有限的精度和可能的四舍五入误差。

请随意编辑和实验,更改将只在本地进行,在您的计算机上,您不能破坏任何东西。如果视频没有在第一次播放(着色玩具错误)-尝试暂停/取消它。享受吧!

c2q()大厅尝试

如果一切都是正确的,则图像的右侧(处理后的)应该等于左侧(原件)。在这里,我将回顾不同的结果,这些结果是通过在c2q()实现中放置一些东西而不是c2q()来获得的:

代码语言:javascript
复制
vec4 c2q(vec3 u, vec3 v) {
    return xxxxx;
}

让我们继续!

  • 最初,我认为这必须是有效的:vec4(cross(u, v), dot(u, v))

  • SE回答中的一个:vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) )

  • 带着他的暗示“别忘了让Q正常化”:normalize(vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) ))

  • @minorlogic的评论,似乎更近了一步:用q__'s组件按sqrt( length(v)/length(u) )vec4(cross(u, v), dot(u, v)) * sqrt( length(u)/length(v) )

  • 交换比率:vec4(cross(u, v), dot(u, v)) * sqrt( length(v)/length(u) )

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-05 01:03:46

我的尝试:

代码语言:javascript
复制
vec4 c2q(vec3 u, vec3 v) {
    float norm_q = sqrt(length(u) / length(v));
    vec4 u4 = vec4(normalize(u), 0.0);
    vec4 v4 = vec4(normalize(v), 0.0);
    return norm_q * (qmul(u4, v4 + u4) / length(v4 + u4));
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55461627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档