首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >四元数校正

四元数校正
EN

Stack Overflow用户
提问于 2018-05-11 11:24:17
回答 2查看 154关注 0票数 1

我试图为一个模拟刚体的客户端实现网络校正。每秒钟30次,我得到目标旋转,从中我计算旋转校正。然后,我将这一修正应用于许多帧。

网络更新:

代码语言:javascript
运行
复制
rotationCorrection = receivedRotation * Quaternion.Inverse(transform.rotation);

每一帧:

代码语言:javascript
运行
复制
var a = Mathf.Min(1, Time.deltaTime * 8);

var final = Quaternion.Slerp(transform.rotation, transform.rotation * rotationCorrection, a);
var actualCorrection = final * Quaternion.Inverse(transform.rotation);
rotationCorrection *= Quaternion.Inverse(actualCorrection);
//rotationCorrection = Quaternion.Slerp(rotationCorrection, Quaternion.identity, a); // First try

_rigidbody.MoveRotation(final);

我之所以不只是将当前的旋转插入到校正后的开始,是因为GameObject包含一个刚体,除了校正之外,它还应该模拟对象。

这有时确实有效(至少第一次尝试版本),除了在大约-90和90之间的角度。我怀疑这是将rotationCorrection细化为标识的代码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-11 11:36:26

(工作正在进行中,因为问题没有100%清楚)

减法公式产生错误的结果。请尝试使用欧拉,减去角度,你可以做想要的四元数。

你确定你不需要Lerp而不是Slerp吗?

无论如何,final不应该使用Lerp或Slerp。

如果作为final,您需要transform.rotation * rotationCorrection (这是当前的旋转加上校正),那么只需使用它。乘法实际上增加了旋转。

Lerp和Slerp将与时间相关的a参数一起使用,其中a==0将返回起始旋转,a==1将返回最终的旋转。因此,a应该随着时间的推移而缩放。另一方面,如果网络更正正是您所需要的,并且您是在特定的固定时间更新时得到的,那么如果没有任何Lerp,不妨试试transform.rotation = transform.rotation*rotationCorrection

rotationCorrection = receivedRotation * Quaternion.Inverse(transform.rotation);

这样做的是返回一个从receivedRotation开始到当前转换旋转的相反旋转的旋转。因此,无论是起点还是终点都与当前的不匹配。

因此:

将最后的四元数设置为currentRot * change

作为currentRot的起始

然后更新transform.rotation,使它= (S)Lerp具有start、end和一个参数,该参数在开始时等于0,在结束时等于1。

票数 0
EN

Stack Overflow用户

发布于 2018-05-11 13:40:37

网络更新是错误的。更正:

代码语言:javascript
运行
复制
rotationCorrection = Quaternion.Inverse(transform.rotation) * receivedRotation;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50291254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档