查找给定向量以及相对于 3D 空间中先前位置的垂直向量

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

我有 3 个向量,xyz,我只想更改 1 个向量,然后根据它们之前的方向(最接近它们的方向)计算其他 2 个向量。我想在内存使用/游戏设计方面以最有效的方式做到这一点。

small illustration of the problem


编辑(在 Stef 提出一些建设性意见后):

我们拥有:

  • x,y,z 3d 向量,标准化且具有相同原点 (0,0,0)
  • y'(向上矢量根据表面而变化)

我们需要什么(我相信):

  • z' 或 x'(并且全部相互垂直)

我尝试过的:

  • z' 借助围绕 x 轴的 y - y' 角度,反之亦然,借助 x' 和 z 轴。我认为这“可以”与适当的线性代数知识一起使用,但仍然意味着欧拉旋转,对吧?我更喜欢只用四元数旋转,尽管我仍然可以弄清楚它们
  • 使用 y' 和 x 的叉积得到 z',然后创建 z' 和 y' 的叉积得到 x'。理论上应该有效吗?我的 3 点积永远不会为 0,其中之一都不是

我的愿望:

  • 通过四元数根据 y 和 y' 的角度更改 x 和 z 向量。我正在戈多工作,仍在解决问题..也就是说,我刚刚发现了这个:
Quaternion Quaternion ( Vector3 arc_from, Vector3 arc_to )

Constructs a quaternion representing the shortest arc between two points on the surface of a sphere with a radius of 1.0.
math vector 3d godot godot4
1个回答
0
投票

如果我理解正确,您需要一个四元数来表示将一个向量转换为另一个向量所需的最短旋转,因此您可以将其应用为您的自定义基础。

我们可以从计算此旋转变换的旋转轴开始......

我将编写 GDScript。我假设向量非零且有限。

var axis := arc_from.cross(arc_to)

除非当矢量方向相同或相反时,这不起作用。所以,让我们考虑一下......

var axis := arc_from.cross(arc_to)
if axis.is_zero_approx():
    var longest_axis := arc_to.max_axis_index()
    var with := Vector3.ONE
    with[longest_axis] = 0.0
    axis = arc_to.cross(with)

在这里,我创建了一个新的

Vector3
,它将是
0.0
位于轴上,
arc_to
具有最长的幅度,
1.0
位于其他轴上。所以保证它不在同一方向,然后我用它与
arc_to
进行叉积,这应该给出一个垂直于
arc_to
的向量。

当然,我们应该标准化轴以确保它的长度

1.0

var axis := arc_from.cross(arc_to)
if axis.is_zero_approx():
    var longest_axis := arc_to.max_axis_index()
    var with := Vector3.ONE
    with[longest_axis] = 0.0
    axis = arc_to.cross(with)

axis = axis.normalized()

现在我们可以算出旋转的角度了:

var axis := arc_from.cross(arc_to)
if axis.is_zero_approx():
    var longest_axis := arc_to.max_axis_index()
    var with := Vector3.ONE
    with[longest_axis] = 0.0
    axis = arc_to.cross(with)

axis = axis.normalized()
var angle := arc_from.signed_angle_to(arc_to, axis)

并为其创建一个四元数:

var axis := arc_from.cross(arc_to)
if axis.is_zero_approx():
    var longest_axis := arc_to.max_axis_index()
    var with := Vector3.ONE
    with[longest_axis] = 0.0
    axis = arc_to.cross(with)

axis = axis.normalized()
var angle := arc_from.signed_angle_to(arc_to, axis)
return Quaternion(axis, angle)

我相信这足以满足您的需求。

© www.soinside.com 2019 - 2024. All rights reserved.