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

问题描述 投票:1回答:1

介绍。

以前,我有asked a question将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)非常简单,just as definedq2c(q, v) == (q*vec4(v, 0.0))*q'。这里,“*”运算符表示quaternion multiplication;让它成为一个功能vec4 qmul(in vec4 q1, in vec4 q2)。而“q'”表示qconjugate,让它成为vec4 qconj(in vec4 q)。省略他们简单的实现(你可以在完整的源代码中找到),我们会得到经典代码:

vec4 q2c(in vec4 q, in vec3 v) {
    return qmul(qmul(q, vec4(v, 0.0)), qconj(q));
}

所以现在我们有q2c(q,v)函数,通过旋转和缩放一些选定的3D矢量q,将四元数v转换为颜色。

问题是如何找到四元数q

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

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


如果你的答案是正确的,你怎么能检查?

实际上,检查方法可能源于这样一个事实,即如果你能够设法转换回来,你将得到初始值。因此检查条件是对于任何非零长度的vu必须始终等于q2c(c2q(u, v), v)v必须具有非零长度,因为人们不能“缩小零”以获得“某事”。

为了方便起见,我使用shadertoy.com服务准备了testing program

你需要一台体面的电脑,有互联网连接和支持webGL的网络浏览器(我正在使用Chrome)。程序应该适用于任何GPU,甚至嵌入到intel的处理器中。它甚至可以在我的低端智能手机上运行!

要测试你的答案,你应该把你提出的公式,用GLSL语法编写,在c2q()函数中。然后按应用按钮,您的更改将生效:enter image description here

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

您可以随意编辑和试验,只在本地,在您的计算机上进行更改,并且您不会破坏任何内容。如果视频没有在第一次打开时播放(shadertoy bug) - 尝试暂停/取消暂停。请享用!


c2q()大厅尝试

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

vec4 c2q(vec3 u, vec3 v) {
    return xxxxx;
}

让我们继续!

  • 最初我认为必须正常工作:vec4(cross(u, v), dot(u, v))enter image description here
  • SE answers之一:vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) )enter image description here
  • 并以他的暗示“别忘了规范化q”:normalize(vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) ))enter image description here
  • @ minorlogic的评论,似乎更近了一步:通过q扩展所有sqrt( length(v)/length(u) )的组件,vec4(cross(u, v), dot(u, v)) * sqrt( length(u)/length(v) )enter image description here
  • 交换比率:vec4(cross(u, v), dot(u, v)) * sqrt( length(v)/length(u) )enter image description here
colors linear-algebra transformation quaternions
1个回答
1
投票

我的尝试:

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));
}
© www.soinside.com 2019 - 2024. All rights reserved.