草庐IT

c++ - 四元数旋转不起作用

coder 2024-02-11 原文

我才刚刚开始使用四元数,但在使用四元数让简单的 FPS 相机正常工作时遇到了一些烦人的困难。

基本上,每当我尝试移动鼠标时,我在屏幕上绘制的三角形就会变得疯狂,并且在屏幕上移动的速度比我看到的还要快。移动键 (wsad) 按预期工作,直到我移动鼠标,然后它变得一团糟。我认为问题出在轮换上,但过去几天我一直在努力解决这个问题,但无济于事。

这是一段视频:Quaternion Test Video

  • 要查看鼠标输入,请从头开始观看。
  • 要查看键盘输入(前进、后退等),请跳至 0:51 秒。

仅供引用,以下是我使用的 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);

    // rotation
    if (xRot_ != 0) {
        Quaternion quatRotation = Quaternion();
        quatRotation.buildFromAxisAngle(1, 0, 0, (xRot_ * time * rotSpeed_) *         math::DEGTORAD);
        //quatRotation.normalize();
        rotation_ = rotation_ * quatRotation;
        xRot_ = 0;
        rotation_.normalize();
    }
    if (yRot_ != 0) {
        Quaternion quatRotation = Quaternion();
        quatRotation.buildFromAxisAngle(0, 1, 0, (yRot_ * time * rotSpeed_) *         math::DEGTORAD);
        //quatRotation.normalize();
        rotation_ = quatRotation * rotation_;
        yRot_ = 0;
        rotation_.normalize();
    }
}

这里是 render() 方法:

void CameraSceneNode::render() {
    if (isActive()) {
        float32 matrix[16];
        rotation_.fillMatrix(matrix);

        glMultMatrixf(&matrix[0]);

        //glRotatef(rotYTest, 0, 1, 0);
        //glRotatef(rotXTest, 1, 0, 0);

        glTranslatef(-pos_.x, -pos_.y, -pos_.z);
    }
}

此外,在我调用相机上的 render() 之前,我运行了这段代码:

glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

tick(..)render() 在我的主游戏循环中的每一帧都会被调用。 CameraSceneNode 类中的函数接受移动方向和相机旋转的变化(即改变 movement_ 缓冲区或 xRot_ yRot_) .

如果这还不够,我很抱歉。一些函数(如 fillMatrix(..))在我上面引用的那 3 个 .h/.cpp 文件中定义。我检查了 Quaternion 类好几次,看起来对我来说是正确的。但话又说回来,我使用的所有代码对我来说都是正确的,所以谁知道 :S

我对此完全束手无策。如果有人能阐明为什么这不起作用,我将不胜感激!!

干杯

贾勒特

最佳答案

从它的外观来看,您在每个滴答声中逐渐累积您的旋转 (rotation_ = quatRotation * rotation_;),这在一开始是有道理的,因为您所做的只是稍微调整旋转,所以它应该是安全的在现有的基础上再旋转一两度,对吗?

但是,每次旋转(通过您正在做的事情)时,您实际上每次都在稍微改变旋转轴,这就是为什么您会看到这种不稳定的行为。

我的建议是跟踪整个 X/Y 旋转,随着鼠标移动而递增或递减,然后每次都直接计算旋转而不是累积旋转。因此,如果您在 X 中旋转 1 度 15 次,则您当前的代码实质上是“在 X 中旋转 1 度,在 X 中旋转 1 度,等等”。我的建议是跟踪单个旋转因子 X,并在它发生变化时直接设置旋转“旋转 13 度、旋转 14 度、旋转 15 度等”。

从您的视频来看,旋转似乎也太大了,因此您可能希望将使用的最终旋转缩放 10 或 50(或其他)倍数。

我可能离题太远了,但我在 3D 编码冒险中遇到过类似的事情,这是我最好的建议。如果这不是问题,因为您正在处理相机旋转,您可能需要使用逆矩阵。更糟的是,查看特定旋转的模型 View 矩阵,看看它是否符合您的预期(痛苦,但也是一个有值(value)的调试练习)。

关于c++ - 四元数旋转不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6365347/

有关c++ - 四元数旋转不起作用的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - 字符串文字前面的 * 在 ruby​​ 中有什么作用? - 2

    这段代码似乎创建了一个范围从a到z的数组,但我不明白*的作用。有人可以解释一下吗?[*"a".."z"] 最佳答案 它叫做splatoperator.SplattinganLvalueAmaximumofonelvaluemaybesplattedinwhichcaseitisassignedanArrayconsistingoftheremainingrvaluesthatlackcorrespondinglvalues.Iftherightmostlvalueissplattedthenitconsumesallrvaluesw

随机推荐