我有两个对象,每个对象有两个向量:
就像这张图片:

向上向量垂直于法向量。现在我想找到从一个对象到另一个对象的唯一旋转,该怎么做?
我有一种方法可以找到一个向量到另一个向量之间的旋转,并且它有效。问题是我需要注意两个向量:法向量和向上向量。如果我使用此方法将法线向量从对象 1 旋转到对象 2 的法线,则向上向量可能指向错误的方向,并且它们需要平行。
这是查找最短旋转的代码:
GE::Quat GE::Quat::fromTo(const Vector3 &v1, const Vector3 &v2)
{
Vector3 a = Vector3::cross(v1, v2);
Quat q;
float dot = Vector3::dot(v1, v2);
if ( dot >= 1 )
{
q = Quat(0,0,0,1);
}
else if ( dot < -0.999999 )
{
Vector3 axis = Vector3::cross(Vector3(1,0,0),v2);
if (axis.length() == 0) // pick another if colinear
axis = Vector3::cross(Vector3(0,1,0),v2);
axis.normalize();
q = Quat::axisToQuat(axis,180);
}
else
{
float s = sqrt( (1+dot)*2 );
float …Run Code Online (Sandbox Code Playgroud) 我四处搜索,结果发现这个问题的答案令人惊讶地难以找到。那里的算法可以生成四元数形式的随机方向,但它们涉及 sqrt 和 trig 函数。我真的不需要均匀分布的方向。我只需要生成(许多)四元数,以便它们的方向随机性“足够好”。我不能指定什么是“足够好”,除了我需要能够快速生成。
我正在CMDeviceMotion使用本答案中描述的CMDeviceMotion扩展将SceneKit相机设置为当前姿态:
func deviceDidMove(motion: CMDeviceMotion?, error: NSError?) {
if let motion = motion {
let orientation = motion.gaze(atOrientation: UIApplication.sharedApplication().statusBarOrientation)
cameraNode.orientation = orientation
}
}
Run Code Online (Sandbox Code Playgroud)
这很漂亮,但是,我想阻止旋转(滚动)并且只允许相机转动(偏转)和俯仰.
我试图将四元数转换回欧拉角,并将roll保持为0:
cameraNode.eulerAngles = SCNVector3(
x: orientation.pitch(),
y: orientation.yaw(),
z: 0)
Run Code Online (Sandbox Code Playgroud)
然而,这仅适用于偏航运动的一半.另一半,相机倒置.我怀疑这是涉及欧拉角的万向节锁定问题.
四元数对我来说有点像黑魔法,但是有没有办法直接在四元数上去除滚动分量,这样我就可以避免欧拉角?
我想通过四元数进行一些旋转。
glm 库在这方面做得很好。
以下是我的代码:
vec3 v(0.0f, 0.0f, 1.0f);
float deg = 45.0f * 0.5f;
quat q(glm::cos(glm::radians(deg)), 0, glm::sin(glm::radians(deg)), 0);
vec3 newv = q*v;
printf("v %f %f %f \n", newv[0], newv[1], newv[2]);
Run Code Online (Sandbox Code Playgroud)
我的问题是,在许多文章中,四元数旋转的公式是
rotated_v = q*v*q_conj
Run Code Online (Sandbox Code Playgroud)
有点奇怪。在glm中,向量“v”只需乘以四元数“q”就可以进行旋转。
这让我很困惑。
我已经(有点盲目地)在物理刚体模拟中使用四元数进行旋转有一段时间了,但最近开始对四元数旋转通常是如何定义的以及我是如何定义的(基于游戏开发者的物理书)感到困惑。
在书中,您有一个角速度 angVel 和一个时间步长 dt 以及一个初始方向。
它的步骤如下
方向 += 0.5*方向*angVel * dt
其中四元数向量乘法是通过首先将向量 xyz 转换为四元数 xyz,0 来完成的
这是可行的,但在其他任何地方,程序都是创建一个四元数,它定义了时间积分 angVel,在 dt 上,然后在方向上乘以它。它本质上将 angVel*dt 转换为旋转(非常有意义),然后通过乘法将其应用于原始方向,如下所示,语法更好https://math.stackexchange.com/questions/39553/how-do- i-apply-an-angular-velocity-vector3-to-a-unit-quaternion-orientation
我的问题是上面的 0.5 * 四元数 * 矢量 * 标量在概念上是什么,以及将这个结果四元数添加到我的方向是什么,考虑到你通常乘法而不是加法来旋转。
我将 Cesium 的模型之一加载到场景中,并且我想使用两个点来计算模型的方向,这是我创建的函数。
// calculate the direction which the model is facing
calculateOrientation({ position, nextPosition }) {
let dir = new Cesium.Cartesian3();
let normalizedDir = new Cesium.Cartesian3();
Cesium.Cartesian3.subtract(nextPosition, position, dir);
Cesium.Cartesian3.normalize(dir, normalizedDir);
var heading = Math.acos(normalizedDir.x);
var pitch = Math.acos(normalizedDir.y);
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
return orientation;
}
Run Code Online (Sandbox Code Playgroud)
但我得到的轮换没有任何意义。我的数学错了吗?
在@Keshet 给出第一个答案后,我查找了如何找到平面和向量之间的角度。我想如果我找到每个平面的法线和 -90 之间的角度,我应该得到正确的角度,但我不确定这是否正确。
另外我不知道Cesium Axis是如何工作的,也找不到任何描述它的文档。例如XY平面等。
let dir = new Cesium.Cartesian3();
let xyNormal = new Cesium.Cartesian3(0,0,1);
let xzNormal = …Run Code Online (Sandbox Code Playgroud) Quaternion multiplication is well-defined, and is known to me as "Hamilton product":
// hamilton product
vec4 qmul(in vec4 q1, in vec4 q2) {
return vec4(
q1.w * q2.xyz + q2.w * q1.xyz - cross(q1.xyz, q2.xyz),
q1.w*q2.w - dot(q1.xyz, q2.xyz)
);
}
Run Code Online (Sandbox Code Playgroud)
However, for implementing qtanh() quaternionic function, we need division. So far I've found this, and it is working OK. Could you help me to undestand, where does this comes from?
// division
// https://www.boost.org/doc/libs/1_67_0/boost/math/quaternion.hpp
vec4 qdiv(in vec4 q1, in …Run Code Online (Sandbox Code Playgroud) 我在每个时间段都有陀螺仪+加速度计数据T.
使用C++,我想计算每次对象的旋转 - 它可以在其轴上旋转.我已经读过,用四元数(不是欧拉角)表示系统的旋转是很方便的.
如何从角速度(从陀螺仪)转换为四元数表示?我认为为了做到这一点,我需要使用数值方法求解微分方程.
我刚刚开始使用Quaternions,但是我在使用Quaternions使一个简单的FPS相机正常工作时遇到了一些烦人的困难.
基本上,每当我尝试移动鼠标时,我在屏幕上绘制的三角形变得疯狂,并且在屏幕上移动的速度比我看到的要快.移动键(wsad)按预期工作,UNTIL我移动鼠标,然后它全部搞砸了.我认为问题在于轮换,但过去几天我一直在倾向于这个问题但无济于事.
这是一个正在发生的事情的视频:四元数测试视频
仅供参考,以下是我正在使用的3个主要类:
Quaternion.h
CameraSceneNode.h
CameraSceneNode.cpp
最相关的部分是tick()(我更新旋转四元数)和render()(我渲染'相机',其中包括旋转和平移场景).
这是tick()方法:
void CameraSceneNode::tick(float32 time) {
// movement direction
if (movement_[MOVE_DIR_FORWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, -moveSpeed_ * time);
if (movement_[MOVE_DIR_BACKWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, moveSpeed_ * time);
if (movement_[MOVE_DIR_LEFT] == 1)
pos_ += rotation_ * vmath::Vector3f(-moveSpeed_ * time, 0, 0);
if (movement_[MOVE_DIR_RIGHT] == 1)
pos_ += rotation_ * vmath::Vector3f(moveSpeed_ * time, 0, 0);
// …Run Code Online (Sandbox Code Playgroud) 我正在寻找带有四元数的3D模型上的弧形旋转的简单实现,特别是在iOS上使用GLKit.到目前为止,我已经检查了以下来源:
我也一直试图从这里和这里了解源代码和数学.我可以旋转我的物体,但它在某些角度不停跳跃,所以我担心万向节锁在起作用.我正在使用手势识别器来控制旋转(平移手势会影响滚动和偏航,旋转手势会影响音高).我将附加我的代码用于四元数处理以及模型视图矩阵转换.
变量:
GLKQuaternion rotationE;四元数处理:
- (void)rotateWithXY:(float)x and:(float)y
{
const float rate = M_PI/360.0f;
GLKVector3 up = GLKVector3Make(0.0f, 1.0f, 0.0f);
GLKVector3 right = GLKVector3Make(1.0f, 0.0f, 0.0f);
up = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), up);
self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up));
right = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), right);
self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(y*rate, right));
}
- (void)rotateWithZ:(float)z
{
GLKVector3 front = GLKVector3Make(0.0f, 0.0f, -1.0f);
front = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), front);
self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(z, front));
}
Run Code Online (Sandbox Code Playgroud)
模型视图矩阵变换(内部绘制循环):
// Get Quaternion Rotation …Run Code Online (Sandbox Code Playgroud) quaternions ×10
rotation ×4
c++ ×3
camera ×2
ios ×2
opengl ×2
3d ×1
arcball ×1
cesiumjs ×1
core-motion ×1
glkit ×1
glm-math ×1
glsl ×1
javascript ×1
math ×1
opengl-es ×1
orientation ×1
physics ×1
rigid-bodies ×1
scenekit ×1