使用四元数进行弧球旋转(使用 iOS GLKit)

2024-07-01

我正在寻找一种在具有四元数的 3D 模型上进行轨迹球旋转的简单实现,特别是在 iOS 上使用 GLKit。到目前为止,我已经检查了以下来源:

  • 使用 GLKit 进行轨迹球旋转 http://thestrangeagency.com/arcball-rotation-with-glkit/
  • 如何使用 OpenGL 通过触摸旋转 3D 对象 http://www.raywenderlich.com/12667/how-to-rotate-a-3d-object-using-touches-with-opengl

我也一直在尝试理解源代码和数学here http://www.idevgames.com/articles/quaternions and here http://ofps.oreilly.com/titles/9780596804824/。我可以旋转我的物体,但它总是以某些角度跳跃,所以我担心万向节锁在起作用。我使用手势识别器来控制旋转(平移手势影响滚动和偏航,旋转手势影响俯仰)。我附加了四元数处理以及模型视图矩阵转换的代码。

变量:

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

模型视图矩阵变换(绘制循环内):

// Get Quaternion Rotation
GLKVector3 rAxis = GLKQuaternionAxis(self.transformations.rotationE);
float rAngle = GLKQuaternionAngle(self.transformations.rotationE);

// Set Modelview Matrix
GLKMatrix4 modelviewMatrix = GLKMatrix4Identity;
modelviewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f);
modelviewMatrix = GLKMatrix4Rotate(modelviewMatrix, rAngle, rAxis.x, rAxis.y, rAxis.z);
modelviewMatrix = GLKMatrix4Scale(modelviewMatrix, 0.5f, 0.5f, 0.5f);
glUniformMatrix4fv(self.sunShader.uModelviewMatrix, 1, 0, modelviewMatrix.m);

非常感谢任何帮助,但我确实想让它尽可能简单并坚持使用 GLKit。


这里似乎出现了一些问题。

  1. 您说您正在使用 [x,y] 进行平移,但看起来更像您正在使用它们进行俯仰和偏航。至少对我来说,平移是平移,而不是旋转。

  2. 除非我遗漏了某些东西,否则看起来每次您尝试更新它时都会替换整个旋转。您可以将向量旋转当前旋转的倒数,然后从该向量和某个角度创建一个四元数。我相信这相当于从原始向量创建四元数,然后按当前旋转逆旋转它。所以你有了q_e'*q_up。然后将其与当前旋转相乘,得到q_e*q_e'*q_up = q_up。当前旋转被取消。这似乎不是你想要的。

    您真正需要做的就是从轴和角度创建一个新的四元数,然后将其与当前的四元数相乘。如果新的四元数位于左侧,则方向更改将使用眼睛局部框架。如果新的四元数位于右侧,则方向变化将在全局框架内。我想你想要:

    self.rotationE =
      GLKQuaternionMultiply( 
        GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up),self.rotationE);
    

    执行此操作,无需对所有三种情况进行反向预旋转。

  3. 我从未使用过 GLKit,但从四元数转换为矩阵时提取轴角度的情况并不常见。如果角度为零,则轴未定义。当它接近于零时,就会出现数值不稳定的情况。看起来你应该使用GLKMatrix4MakeWithQuaternion然后将结果矩阵与平移矩阵和比例矩阵相乘:

    GLKMatrix4 modelviewMatrix = 
      GLKMatrix4Multiply( GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f),
                          GLKMatrix4MakeWithQuaternion( self.rotationE ) );
    modelviewMatrix = GLKMatrix4Scale( modelviewMatrix, 0.5f, 0.5f, 0.5f );
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用四元数进行弧球旋转(使用 iOS GLKit) 的相关文章

随机推荐

  • 通过 JAAS 以编程方式登录用户

    我试图通过以编程方式登录这样的用户 剥离异常处理 在不同的身份验证下在 JBoss 容器中运行代码 LoginContext ctx ctx new LoginContext MyLoginSchema new UsernamePasswo
  • 翻译基础设施无法在应用程序之前初始化

    我正在关注姜戈文档 https docs djangoproject com en 1 9 ref settings std setting LANGUAGES 但是当我按照它的说明操作时 我收到以下错误消息 The translation
  • 三元运算符 C++ 中的 return 语句

    我使用三元运算符编写了绝对函数 如下所示 int abs int a a gt 0 return a return a 我收到以下错误消息 src templates cpp In function int abs int src temp
  • Admob 自适应横幅广告实施

    我将用新的自适应横幅广告替换当前的横幅广告 自适应广告尺寸是在捕获宽度尺寸后计算的 我将 adview 的框架布局放置在布局的底部
  • printf 与 std::string ?

    我的理解是string是的成员std命名空间 那么为什么会出现以下情况呢 include
  • psutil.Process(pid).name 的替代方案

    我已经测量了性能psutil Process pid name事实证明它比例如慢十倍以上psutil Process pid exe 由于这些函数的最后一个需要对路径的不同权限 因此我不能只从路径中提取文件名 我的问题是 有没有其他选择ps
  • 如何创建大型SWT图像?

    在我的 eclipse rcp 应用程序中 我需要创建尺寸为 30000x10000 像素或更大的图像 这张图片是NatTable http nattable org drupal 表示 使用标准图像创建方法 它会因不同的问题而失败 Out
  • C++ 函数参数:使用引用还是指针(然后取消引用)?

    我得到了一些代码 其中一些参数是指针 然后指针被取消引用 提供价值 我担心指针取消引用会消耗周期 但是在查看之后 之前的 StackOverflow 文章 取消引用指针的代价有多大 https stackoverflow com quest
  • 使用 Oozie 运行 shell 脚本

    我正在尝试运行一个sh通过Oozie编写脚本 但我面临一个问题 无法运行程序 script sh 在目录中 mapred local taskTracker dell jobcache job 201312061003 0001 attem
  • ASP .NET Core MVC:RedirectToAction 上的请求会发生什么情况

    我整天都在尝试在控制器之间传递数据 但现在我认为我还不太理解基础知识 在 ASP NET core 的整个文档中 他们使用 请求 一词 我假设这是由 WebServer 客户端发出的 HttpRequest 还有一些不同的事情应该与请求的生
  • SQLite:从命令行插入二进制数据

    我有这个 SQLite 表 create table mytable aid INTEGER NOT NULL PRIMARY KEY bid INTEGER NOT NULL image BLOB 我想将一个二进制文件插入到image该表
  • 在pushViewController之前设置视图控制器属性

    在我的应用程序中 我向视图添加了标签 将其连接到插座 但当我第一次从另一个视图控制器分配此插座然后调用时 什么也没有显示pushViewController来显示它 这是推送下一个显示标签的视图之前的代码 CustomViewControl
  • LaTeX:两栏文章中的多个作者

    我对 LaTeX 有点陌生 我遇到了一些问题 我正在使用一个twocolumn我的布局article 有四位作者涉及不同的隶属关系 我试图将他们全部列在标题下 以便他们跨越页面的整个宽度 都在同一水平上 它应该类似于这样 Article T
  • Eigen 静态库内存对齐

    我正在使用 C 17 GCC 7 4 0 Eigen 3 3 4 这是我的最小例子 我有两节课 B and C C位于静态库中 尝试创建实例时 程序因分段错误而崩溃B 静态库是通过优化构建的 构建类型 发布 如果在没有优化的情况下构建 程序
  • VueJS 语法:挂载时运行方法

    我想加载一些数据vue resource当页面加载时 如果按下刷新按钮 则重新加载该数据 保留我的代码DRY https en wikipedia org wiki Don 27t repeat yourself我想将此功能放入一个方法中
  • 在谷歌云平台中运行数据流时“找不到方案gs的文件系统”

    我正在 Google Cloud Platform GCP 中运行我的 google dataflow 作业 当我在本地运行此作业时 它运行良好 但是当我在 GCP 上运行它时 出现此错误 java lang IllegalArgument
  • Rails Installer + Cygwin:如何在 Cygwin 中最好地使用 ruby​​ 版本的 Rails 安装程序?

    我刚刚安装了 Windows 设置 以便通过 RailsInstaller 处理 Ruby on Rails 在 Windows 命令行上 一切都运行良好 我还使用 cygwin 它默认安装它自己的 ruby 版本 这与 bcrypt ru
  • 如何确定 Azure 队列中的所有消息是否都已处理完毕?

    我刚刚开始修补 Windows Azure 希望能帮助解答一个问题 如何确定 Windows Azure 队列是否为空并且其中的所有工作项都已被处理 如果我有多个工作进程查询工作项队列 则如果队列为空 GetMessage s 不会返回任何
  • Split() 已弃用 [重复]

    这个问题在这里已经有答案了 可能的重复 PHP 拆分替代方案 https stackoverflow com questions 2813241 php split alternative Successful geocode geocod
  • 使用四元数进行弧球旋转(使用 iOS GLKit)

    我正在寻找一种在具有四元数的 3D 模型上进行轨迹球旋转的简单实现 特别是在 iOS 上使用 GLKit 到目前为止 我已经检查了以下来源 使用 GLKit 进行轨迹球旋转 http thestrangeagency com arcball