捕捉到 y 轴 Unity 中存储的相对旋转
Snapping to a stored relative rotation in y axis Unity
这适用于在 Unity 中开发的 Microsoft HoloLens 应用程序。
我正在开发一项功能,"saves" 用户可以轻松返回的视点。我这样做是通过将场景中对象的相对 position/orientation 存储到主相机,然后通过语音命令将对象恢复到它们之前的相对 position/orientation。
我的位置恢复工作正常,我只需要恢复偏航轴 (y) 的方向,以便用户被迫面向正确的方向。
我尝试使用此解决方案将场景对象(在本例中称为 "terrainContainer")的 relative y 方向恢复到主相机:
//this is the stored relative orientation in y
float deltaYaw = Camera.main.transform.rotation.eulerAngles.y - terrainContainer.transform.rotation.eulerAngles.y;
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
float curDeltaYaw = Camera.main.transform.rotation.eulerAngles.y - terrainContainer.transform.rotation.eulerAngles.y;
float diffDeltas = curDeltaYaw - deltaYaw;
float setYaw = terrainContainer.transform.rotation.eulerAngles.y + diffDeltas;
setYaw = Utils.MathUtils.Normalise(setYaw, 0, 360); //normalises the value recovered to a range from [0,360]
//adjusting terrainContainer rotation
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.x, setYaw, terrainContainer.transform.rotation.z);
}
当我执行以下操作时此实现有效:
- 保存我的观点
- 在位置和方向上移动主摄像头(通过 HoloLens 中的头部移动)
- 移动地形的位置,但不是方向
- 恢复到视点
当我执行以下操作时,此实施 失败 :
- 保存我的观点
- 将地形的方向重置为 0 度
- 沿任一方向将地形旋转任意量
- 恢复到视点
发生故障时,方向偏离了地形旋转的程度。所以如果地形被用户逆时针旋转了 20 度,地形应该是 50 度,那么地形最终是 70 度。
我不明白为什么会这样。我在位置变化之前进行轮换。如果您能提供任何帮助,我将不胜感激!
编辑:
正如下面评论中提到的,我采用了一种略有不同的方法来解决这个最终有效的问题:
//this is the stored relative orientation in y
float deltaYaw = viewpoint.transform.localRotation.eulerAngles.y
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
Quaternion toQuat = Camera.main.transform.localRotation;
//my implementation is flat on the xz plane
toQuat.eulerAngles = new Vector3(0, toQuater.eulerAngles.y, 0);
//orient terrain to same as camera
terrainContainer.transform.rotation = toQuat;
//now add the previous difference in rotation to the terrain
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.eulerAngles.x, terrainContainer.transform.rotation.eulerAngles.x + deltaYaw, terrainContainer.transform.rotation.eulerAngles.z);
}
但我还可以看到另一个问题
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.x, setYaw, terrainContainer.transform.rotation.z);
Rotation 是一个四元数,本质上是一个 Vector4,您可以通过 rot.x、rot.y、rot.z、rot.w 来寻址它的成员,但是那些是与构成四元数的欧拉角不同。改用 yhid:
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.eulerAngles.x, setYaw, terrainContainer.eulerAngles.z);
也可以通过
setYaw = Utils.MathUtils.Normalise(setYaw, 0, 360);
如果您的 setYaw 大于 360(在某些情况下很可能是这样),那么您正在截断信息。
你可以简单地删除这条线,因为 unity 在大于 360 的角度下工作得很好,或者如果你真的需要截断该值,你可以做
setYaw = setYaw % 360; //modulo division
正如下面评论中提到的,我采用了一种稍微不同的方法来解决这个最终有效的问题:
//this is the stored relative orientation in y
float deltaYaw = viewpoint.transform.localRotation.eulerAngles.y
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
Quaternion toQuat = Camera.main.transform.localRotation;
//my implementation is flat on the xz plane
toQuat.eulerAngles = new Vector3(0, toQuater.eulerAngles.y, 0);
//orient terrain to same as camera
terrainContainer.transform.rotation = toQuat;
//now add the previous difference in rotation to the terrain
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.eulerAngles.x, terrainContainer.transform.rotation.eulerAngles.x + deltaYaw, terrainContainer.transform.rotation.eulerAngles.z);
}
这适用于在 Unity 中开发的 Microsoft HoloLens 应用程序。
我正在开发一项功能,"saves" 用户可以轻松返回的视点。我这样做是通过将场景中对象的相对 position/orientation 存储到主相机,然后通过语音命令将对象恢复到它们之前的相对 position/orientation。
我的位置恢复工作正常,我只需要恢复偏航轴 (y) 的方向,以便用户被迫面向正确的方向。
我尝试使用此解决方案将场景对象(在本例中称为 "terrainContainer")的 relative y 方向恢复到主相机:
//this is the stored relative orientation in y
float deltaYaw = Camera.main.transform.rotation.eulerAngles.y - terrainContainer.transform.rotation.eulerAngles.y;
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
float curDeltaYaw = Camera.main.transform.rotation.eulerAngles.y - terrainContainer.transform.rotation.eulerAngles.y;
float diffDeltas = curDeltaYaw - deltaYaw;
float setYaw = terrainContainer.transform.rotation.eulerAngles.y + diffDeltas;
setYaw = Utils.MathUtils.Normalise(setYaw, 0, 360); //normalises the value recovered to a range from [0,360]
//adjusting terrainContainer rotation
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.x, setYaw, terrainContainer.transform.rotation.z);
}
当我执行以下操作时此实现有效:
- 保存我的观点
- 在位置和方向上移动主摄像头(通过 HoloLens 中的头部移动)
- 移动地形的位置,但不是方向
- 恢复到视点
当我执行以下操作时,此实施 失败 :
- 保存我的观点
- 将地形的方向重置为 0 度
- 沿任一方向将地形旋转任意量
- 恢复到视点
发生故障时,方向偏离了地形旋转的程度。所以如果地形被用户逆时针旋转了 20 度,地形应该是 50 度,那么地形最终是 70 度。
我不明白为什么会这样。我在位置变化之前进行轮换。如果您能提供任何帮助,我将不胜感激!
编辑: 正如下面评论中提到的,我采用了一种略有不同的方法来解决这个最终有效的问题:
//this is the stored relative orientation in y
float deltaYaw = viewpoint.transform.localRotation.eulerAngles.y
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
Quaternion toQuat = Camera.main.transform.localRotation;
//my implementation is flat on the xz plane
toQuat.eulerAngles = new Vector3(0, toQuater.eulerAngles.y, 0);
//orient terrain to same as camera
terrainContainer.transform.rotation = toQuat;
//now add the previous difference in rotation to the terrain
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.eulerAngles.x, terrainContainer.transform.rotation.eulerAngles.x + deltaYaw, terrainContainer.transform.rotation.eulerAngles.z);
}
但我还可以看到另一个问题
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.x, setYaw, terrainContainer.transform.rotation.z);
Rotation 是一个四元数,本质上是一个 Vector4,您可以通过 rot.x、rot.y、rot.z、rot.w 来寻址它的成员,但是那些是与构成四元数的欧拉角不同。改用 yhid:
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.eulerAngles.x, setYaw, terrainContainer.eulerAngles.z);
也可以通过
setYaw = Utils.MathUtils.Normalise(setYaw, 0, 360);
如果您的 setYaw 大于 360(在某些情况下很可能是这样),那么您正在截断信息。 你可以简单地删除这条线,因为 unity 在大于 360 的角度下工作得很好,或者如果你真的需要截断该值,你可以做
setYaw = setYaw % 360; //modulo division
正如下面评论中提到的,我采用了一种稍微不同的方法来解决这个最终有效的问题:
//this is the stored relative orientation in y
float deltaYaw = viewpoint.transform.localRotation.eulerAngles.y
//this function adjusts the orientation of the terrainContainer to match previous relative orientation that was stored
public void SwitchRelativeOrientation(float deltaYaw, GameObject terrainContainer){
Quaternion toQuat = Camera.main.transform.localRotation;
//my implementation is flat on the xz plane
toQuat.eulerAngles = new Vector3(0, toQuater.eulerAngles.y, 0);
//orient terrain to same as camera
terrainContainer.transform.rotation = toQuat;
//now add the previous difference in rotation to the terrain
terrainContainer.transform.rotation = Quaternion.Euler(terrainContainer.transform.rotation.eulerAngles.x, terrainContainer.transform.rotation.eulerAngles.x + deltaYaw, terrainContainer.transform.rotation.eulerAngles.z);
}