查找四元数,表示从一个向量到另一个向量的转换 [英] Finding quaternion, representing transformation from one vector to another

查看:304
本文介绍了查找四元数,表示从一个向量到另一个向量的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前,我已经提出了一个问题 rgb 三元组转换为四元数.在提出这个问题之后,我设法获得了单元四元数,但是我对其四元数的内部结构感到怀疑.没有简单的方法来操作它们,以及分隔 luma chroma ,因为它们是单位长度的四元数.根据我对它的感觉,亮度应该编码为实数部分或整个大小.颜色"色度"信息应编码在虚部.

Previously, I've asked a question on converting rgb triple to quaternion. After that question I've managed to get unit quaternions, but I am in doubt of their internal structure. There was no easy way to operate them, and to separate luma and chroma, since that were quaternions of unit length. According to my feeling about it, luminance should be encoded in the either real part, or a whole magnitude; And color "chroma" information should be encoded in the imaginary part.

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

Today I've decided to improve things up, taking another approach, different from the first one in the link above. I think it could success, since quaternion could store not only rotation(unit quaternion), but scale as well. First things first, so I'll start with explaining my next idea. I would use GLSL shader syntax in the following explanations.

对于图像的某些像素,让我们设想一个单位立方体内的3D矢量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).我将其称为四元数到颜色"转换器.

For some pixel of an image, let's concieve a 3D vector vec3 u within the unit cube, where positive coordinates are lying in closed range [0.0, 1.0], and are representing full rgb colorspace. So now u's coordinates , u.x, u.y and u.z would represent red, green and blue values of that pixel, accordingly. Then lets take a pure white vector const vec3 v = vec3(1.0, 1.0, 1.0);. And let's define some quaternion q, so that our vector u is the "v, rotated and scaled with quaternion q". In simple words, q must answer the question "How to transform v, in order to get initially conceived color u?". And lets introduce function for that "rotate and scale" operation: vec3 q2c(in vec4 q, in vec3 v). I'll call it "quaternion-to-color" converter.

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).省略它们的简单实现(您可能会在完整的源代码中找到),我们将使用经典代码:

Writing q2c(q, v) is pretty simple, just as defined: q2c(q, v) == (q*vec4(v, 0.0))*q'. Here, the "*" operator denotes quaternion multiplication; Lets make it a function vec4 qmul(in vec4 q1, in vec4 q2). And "q'" denotes q's conjugate, lets make it vec4 qconj(in vec4 q). Omitting their simple implementation (that you may find in full source), we would come to classic code:

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

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

So now we have q2c(q,v) function, that converts quaternion q to color, by rotating and scaling some chosen 3D vector v.

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

The question is How to find that quaternion q?

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

From a programmer's perspective, the goal is To write reverse function vec4 c2q(in vec3 u, in vec3 v) - a corresponding "color to quaternion" converter.

请注意,如果没有充分的理由,请勿触摸q2c().例如,逻辑上的一个严重错误,导致无法解决任务",您可以证明这一点.

Please note, that you should not touch q2c(), without a really good reason. E.g, a serious bug in its logic, leading to "impossibility to solve task", and you can proof that.

实际上,如果您设法来回转换,那么将获得初始值这一事实将产生检查方法.因此,检查条件为对于任何非零长度vu必须始终等于q2c(c2q(u, v), v) . v必须具有非零长度,因为一个人不能缩放零"以获得某物".

Indeed, the checking method would arise from the fact that you would get initial value, if you will manage to convert forth and back. So the checking condition is For any non-zero length v, u must always be equal to q2c(c2q(u, v), v). v must have non-zero length, because one cannot "scale zero" to get "something".

为了简化工作,我使用shadertoy.com服务准备了测试程序

To easy things up, I've prepared testing program, using shadertoy.com service.

您需要一台像样的计算机,可以正常连接互联网,并需要一个具有webGL支持的网络浏览器(我使用的是Chrome).程序应该可以在任何GPU上运行,甚至可以嵌入到英特尔的处理器中.它甚至可以在我的低端智能手机上使用!

You would require a decent computer, with working internet connection and a web browser with webGL support (I'm using Chrome). Program should work on any GPU, even embedded into intel's processors. It even worked on my lower-end smartphone!

要测试您的答案,您应该将以GLSL语法编写的建议公式放在c2q()函数中.然后按应用"按钮,您的更改将生效:

To test your answer, you should put your proposed formula, written in GLSL syntax, inside c2q() function. Then press apply button, and your changes will come into effect:

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

Image at the left represents some unchanged source pixels. And right half will contain pixels, transformed forth and back by q2c(c2q()). Obviously, halves must be visually equal, you should not notice any vertical line. An some little mathematical(unnoticeable) error may arise, but only due to floating point's nature - its finite precision and possible rounding errors.

可以随意进行编辑和实验,更改只能在本地计算机上进行,并且不会破坏任何内容.如果视频在第一次打开时未播放(阴影玩具错误),请尝试暂停/取消暂停它.享受吧!

Feel free to edit and experiment, changes will be done only locally, on your computer, and you cannot wreck anything. If video is not playing on first open (shadertoy bug) - try to pause/unpause it. Enjoy!

如果一切正确,则图像的右侧(处理后的图像)应与左侧(原始图像)相等.在这里,我将回顾通过在c2q()实现中放一些东西而不是xxxxx所获得的不同结果:

If everything is correct, the right side of image(processed one) should be equal to the left side(original). And here I would review different results, that were obtained by putting something instead of xxxxx, in the c2q() implementation:

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

让我们继续吧!

  • 最初,我认为这必须可行: vec4(cross(u, v), dot(u, v)):

  • Initially I've thought that must just work: 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) )):

And with his hint "Don't forget to normalize q": normalize(vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) )):

@minorlogic的评论似乎更近了: sqrt( length(v)/length(u) ) 缩放所有q的组件, vec4(cross(u, v), dot(u, v)) * sqrt( length(u)/length(v) ):

@minorlogic's comment, seems to be a step closer: scale all q's components by 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) ):

推荐答案

我的尝试:

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));
}

这篇关于查找四元数,表示从一个向量到另一个向量的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆