当前位置: 首页 > news >正文

关于unity世界坐标和相对坐标

其实就是父子集的关系

估计没有多少人闲着没事写这个问题,但架不住有好学的小伙伴深究这个问题,所以我们从数学角度剖析下。

如果将物体拖拽到某个物体成为子集对象后,此时就变成了这个子集对象的坐标相对于这个父物体坐标,以下我们简称相对坐标。

那么如果我们以世界坐标为基准,来计算这个子集物体对象的坐标该如何计算呢?

首先你得先知道这个父物体的世界坐标,以及代表它当前姿态的四元数

四元数为 w、x、y、z,这个w要注意可能与unity不同

然后这里面有个根据四元数的cbi计算矩阵

下面为cbi矩阵

从计算给定四元数的方向余弦矩阵cbi,经过上面cbi计算,就能得出我们当前的世界坐标

这样就完成了将向量从机体坐标系转换到世界坐标系的全过程,即得出子集对象的世界坐标位置,并会受到当前对象的四元数影响。

用代码实现这个过程如下所示:

using UnityEngine;public class ObjectPositionCalculator : MonoBehaviour
{[Header("参考对象")] public Transform referenceObject; // 提供姿态和位置信息的参考对象[Header("目标对象")] public Transform targetObject; // 需要计算位置的目标对象[Header("CBI参数")] public Vector3 localOffset = Vector3.zero; // 局部坐标系偏移public Vector3 globalOffset = Vector3.zero; // 全局坐标系偏移public bool useQuaternionRotation = true; // 是否使用四元数旋转[Header("平滑设置")] public bool useSmoothing = false;public float smoothingFactor = 0.1f;private Vector3 previousPosition;private Quaternion previousRotation;void Start(){if (referenceObject == null){Debug.LogError("参考对象未设置!");return;}previousPosition = referenceObject.position;previousRotation = referenceObject.rotation;// 初始计算目标对象位置CalculateTargetPosition();}void Update(){if (referenceObject == null || targetObject == null)return;CalculateTargetPosition();}void CalculateTargetPosition(){// 获取参考对象的当前姿态和位置Vector3 referencePosition = referenceObject.position;Quaternion referenceRotation = referenceObject.rotation;// 计算位置变化和旋转变化Vector3 positionDelta = referencePosition - previousPosition;Quaternion rotationDelta = referenceRotation * Quaternion.Inverse(previousRotation);// 基于CBI推算目标位置Vector3 calculatedPosition = CalculateCBIPosition(referencePosition,referenceRotation,positionDelta,rotationDelta);// 应用平滑if (useSmoothing){calculatedPosition = Vector3.Lerp(targetObject.position,calculatedPosition,smoothingFactor * Time.deltaTime);}// 设置目标对象位置targetObject.position = calculatedPosition;// 更新上一帧数据previousPosition = referencePosition;previousRotation = referenceRotation;}Vector3 CalculateCBIPosition(Vector3 refPosition, Quaternion refRotation,Vector3 deltaPosition, Quaternion deltaRotation){Vector3 finalPosition;if (useQuaternionRotation){// 使用四元数旋转的方法// 应用局部偏移(在参考对象的局部坐标系中)Vector3 rotatedOffset = refRotation * localOffset;// 应用全局偏移finalPosition = refPosition + rotatedOffset + globalOffset;// 考虑位置变化的影响finalPosition += deltaPosition;// 考虑旋转变化对位置的影响Vector3 rotationEffect = deltaRotation * (rotatedOffset * 0.5f);finalPosition += rotationEffect;}else{// 简化的位置推算方法finalPosition = refPosition + refRotation * localOffset + globalOffset;}return finalPosition;}// 高级CBI计算方法(可用于更精确的惯性导航)Vector3 CalculateAdvancedCBIPosition(Vector3 refPosition, Quaternion refRotation,Vector3 velocity, Vector3 angularVelocity, float deltaTime){// 基于速度和角速度的预测Vector3 predictedPosition = refPosition + velocity * deltaTime;// 考虑角速度对局部偏移的影响Quaternion predictedRotation = refRotation * Quaternion.Euler(angularVelocity * Mathf.Rad2Deg * deltaTime);// 应用旋转后的偏移Vector3 rotatedOffset = predictedRotation * localOffset;return predictedPosition + rotatedOffset + globalOffset;}// 公共方法:手动触发位置计算public void ForceRecalculate(){CalculateTargetPosition();}// 公共方法:设置偏移参数public void SetOffsets(Vector3 newLocalOffset, Vector3 newGlobalOffset){localOffset = newLocalOffset;globalOffset = newGlobalOffset;ForceRecalculate();}// 公共方法:获取当前推算的位置public Vector3 GetCalculatedPosition(){return CalculateCBIPosition(referenceObject.position,referenceObject.rotation,referenceObject.position - previousPosition,referenceObject.rotation * Quaternion.Inverse(previousRotation));}#if UNITY_EDITORvoid OnDrawGizmosSelected(){if (referenceObject != null && targetObject != null){// 绘制参考对象到目标对象的连线Gizmos.color = Color.yellow;Gizmos.DrawLine(referenceObject.position, targetObject.position);// 绘制局部偏移示意Gizmos.color = Color.blue;Vector3 localOffsetWorld = referenceObject.rotation * localOffset;Gizmos.DrawLine(referenceObject.position, referenceObject.position + localOffsetWorld);}}
}#endif

http://www.dtcms.com/a/573786.html

相关文章:

  • 企业网站建设研究凡科互动永久解封
  • 专做排名的网站做漫画网站
  • 数据库 连接工具 免费
  • 魔云手机建站商务网站规划建设与管理答案
  • django中request.GET.urlencode的使用
  • 优秀网站设计重庆网站营销
  • 孟村县网站建设通州网站建设是什么
  • Qt解决_mm_loadu_si64找不到标识符问题
  • 灾难恢复(DR):RTO/RPO 定义、冷备/热备/双活架构
  • 台州网站设计 解放路成都网站开发哪家好
  • 吉林网络公司哪家好如何做好seo基础优化
  • 芜湖有哪些招聘网站企业网站优化问题
  • 借助 Kiro:实现《晚间手机免打扰》应用,破解深夜刷屏困境
  • Apache DolphinScheduler 3.3.2 正式发布!性能与稳定性有重要更新
  • 视频网站开发技术书糕点网站设计
  • 站点和网页的关系移动网站建设哪家好
  • Linux进程调度与Nice值完全指南:从新手到精通
  • Hadess零基础学习,如何管理Go制品
  • 贷中风控策略:分群、支用、调额、调价、预警...
  • STM32单片机 IIC 通信协议
  • 旅游平台网站合作建设方案微信h5的制作方法
  • Spring Boot3零基础教程,响应式编程,前景提要,笔记108
  • 北京优化网站推广成都app
  • 李宏毅深度强化学习课程笔记
  • vue怎么拿到url上的参数
  • WiFi1到WiFi7的发展史:它们之间的区别有什么
  • 6-5〔O҉S҉C҉P҉ ◈ 研记〕❘ 客户端攻击▸利用Windows库文件进行攻击-1
  • 用Python和Telegram API构建一个消息机器人
  • 的建站公司绵阳吉工建设
  • 个人网站设计摘要给公司做一个网站流程