理解HTC Vive更新——控制相机旋转和位移
来源:互联网 发布:诱导源码 编辑:程序博客网 时间:2024/06/08 14:04
本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:http://blog.csdn.net/cartzhang/article/details/72188658
作者:cartzhang
一、写在前面
在HTC的vive 头盔中,
一旦Vive头盔连接都unity游戏中,就会控制所有Camera的旋转和位置。
这对于有需要的控制非头盔相机带来了烦恼。
比方说,上篇博客中,在VR中,对某个特点位置截图,就会由于头盔控制所有相机的旋转,
造成截图不精确和出现偏移。
地址:
http://blog.csdn.net/cartzhang/article/details/71136498
现在,经过测试发现,其实是可以控制的。
在Win10系统下测试,unity版本为5.4.4f1,Steam VR 版本v1.1.1。
二、怎么控制
图0
头盔在正常情况下,被头盔具体位置和旋转赋值控制。
图1
同时头盔的参数也控制其他,比如UI相机的位置和旋转。
加上我们的脚本:
图2
游戏编辑器下运行,头盔给Ui相机的赋值,被强制给变成了零。
三、控制脚本代码
接下来看看脚本代码:
//@cartzhangusing UnityEngine;using System.Collections;public class StickRotate : MonoBehaviour { // Use this for initialization void Start () { } // NO ,不行。 //private void FixedUpdate() //{ // transform.rotation = Quaternion.identity; //} // yes ,可以限定。 //private void OnPreCull() //{ // transform.rotation = Quaternion.identity; //} // Update is called once per frame void OnPostRender () { transform.rotation = Quaternion.identity; transform.position = Vector3.zero; }}
经过测试,发现在Update和fixedUpdate中处理上不可行的。
在OnPreCull和OnPostRender进行重新赋值都可以的。
四、重点来了,都是幻觉
1. 没有那么简单
当时第六感就怀疑,应该没有这么简单。要不就不会有成群结队的人要求unity和steamVR插件做接口和选项了,让可以控制旋转和移动了。
当时是这样想的:
结果我还是有一定的怀疑的。是不是由于脚本执行顺序不同,在不同的电脑和不同时候结果也不一样的。
若有的话,试试看通过调整脚本执行顺序看能不能解决问题。
2.转折了
结果,出去遛一圈回来,就不行了。郁闷啊!!
截图都在,电脑不认了。
都是幻觉啊!!
图3
找到了方法
https://steamcommunity.com/app/358720/discussions/0/365163686052028359/
说在5.3 可用,5.4不可用。天啊…
(说明下,之前想的调整渲染顺序,然并卵。理想与现实的差距啊…)
3. 然而,并不气
气也没有用。考虑对策,
第一,我试图把VR5.3的VR插件直接拷贝到我的5.4.4f1版本里来做替换,结果可想而知,失败,替换后根本就没有了VR效果,因为VR的插件相当于没有加载。
第二、使用相对旋转和相对位置实时做矫正。
也参看来其他的只需要旋转的一个问题。有需要的可以参考:
http://answers.unity3d.com/questions/1209337/vrvive-allow-rotation-only.html
这个方案与我之前的小场地扩展到大场地的策略类似,可以参考:
HTC Vive小场地与大场景空间的解决方案————
http://blog.csdn.net/cartzhang/article/details/52780621
这个结果是成功了。
图4
4. 给出代码
using UnityEngine;using System.Collections;public class StickRotate : MonoBehaviour{ private Vector3 InitialPos; private Vector3 hmdPos; public GameObject HMD; private Transform CameraPos; void Start() { CameraPos = transform; InitialPos = transform.position; } // Update is called once per frame void LateUpdate() { hmdPos = HMD.transform.localPosition; transform.position = CameraPos.position - hmdPos; transform.rotation = Quaternion.Euler(CameraPos.rotation.eulerAngles - HMD.transform.rotation.eulerAngles); } // NO ,不行。 //private void FixedUpdate() //{ // transform.rotation = Quaternion.identity; //} // NO ,不能限制旋转。 //private void Update() //{ // transform.rotation = Quaternion.identity; //} // yes ,可以限定。这个原来是可以的,后来莫名就不行了。 // private void OnPreCull() // { // transform.rotation = Quaternion.identity; // } // // 这个跟上面一下,当时还有点沾沾自喜... // void OnPostRender () // { // transform.rotation = Quaternion.identity; // transform.position = Vector3.zero; //}}
五、试着了解 Vive头盔的更新
1. 头盔的渲染更新是在SteamVR_Render中进行的。
// 注释 @cartzhangvoid Update() {#if !(UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) // 添加PoseUpdate。在SteamVR_UpdatePoses中实现了位置更新。 // if (poseUpdater == null) { var go = new GameObject("poseUpdater"); go.transform.parent = transform; poseUpdater = go.AddComponent<SteamVR_UpdatePoses>(); }#else if (cameras.Length == 0) { enabled = false; return; } // If our FixedUpdate rate doesn't match our render framerate, then catch the handoff here. SteamVR_Utils.QueueEventOnRenderThread(SteamVR.Unity.k_nRenderEventID_PostPresentHandoff);#endif // Force controller update in case no one else called this frame to ensure prevState gets updated. // 强制调用手柄更新,以防止本帧没有调用。 SteamVR_Controller.Update(); // Dispatch any OpenVR events. // 事件分发。 var system = OpenVR.System; if (system != null) { var vrEvent = new VREvent_t(); var size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VREvent_t)); for (int i = 0; i < 64; i++) { if (!system.PollNextEvent(ref vrEvent, size)) break; switch ((EVREventType)vrEvent.eventType) { case EVREventType.VREvent_InputFocusCaptured: // another app has taken focus (likely dashboard) if (vrEvent.data.process.oldPid == 0) { SteamVR_Utils.Event.Send("input_focus", false); } break; case EVREventType.VREvent_InputFocusReleased: // that app has released input focus if (vrEvent.data.process.pid == 0) { SteamVR_Utils.Event.Send("input_focus", true); } break; case EVREventType.VREvent_ShowRenderModels: SteamVR_Utils.Event.Send("hide_render_models", false); break; case EVREventType.VREvent_HideRenderModels: SteamVR_Utils.Event.Send("hide_render_models", true); break; default: var name = System.Enum.GetName(typeof(EVREventType), vrEvent.eventType); if (name != null) SteamVR_Utils.Event.Send(name.Substring(8) /*strip VREvent_*/, vrEvent); break; } } } // Ensure various settings to minimize latency. // 不限制最高帧率 Application.targetFrameRate = -1; // 可以在后台运行,不需要强制窗口焦点。 Application.runInBackground = true; // don't require companion window focus // 不限制驱动程序的最大队列值。这个只有DX有,OpenGL中被忽略。 QualitySettings.maxQueuedFrames = -1; // 关闭垂直同步。 QualitySettings.vSyncCount = 0; // this applies to the companion window // 是否锁定刷新速率与物理同步。 if (lockPhysicsUpdateRateToRenderFrequency && Time.timeScale > 0.0f) { var vr = SteamVR.instance; if (vr != null) { var timing = new Compositor_FrameTiming(); timing.m_nSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(Compositor_FrameTiming)); vr.compositor.GetFrameTiming(ref timing, 0); // 设置新的物理更新间隔。 Time.fixedDeltaTime = Time.timeScale / vr.hmd_DisplayFrequency; } } }
在代码中加了中文注释。
在编辑器模式下运行过程中,关闭与steamVR 相关脚本并不会影响头盔的旋转和位置。
我理解的的是,这是Unity在VR的底层代码进行的处理。或者在OnEnable或Awake中进行了绑定,所有以后是否运行脚本都没有关系了。
2. SteamVR_UpdatePoses姿态更新
单独说下这个更新,是由于若在Vive相机上直接对相机下的模型贴上UI会造成在编辑器下正常,在游戏中UI的煽动,也就是在移动过程中,并不是实时的更随物体移动,而是有类似于弹簧似的移动,就像是使用了DoTween。
解决方法就在这里。
//void OnPreCull() //fixed change for ui follow controller at leaset one frame delay.@zpj void LateUpdate()
把原来的OnPreCull修改为LateUpdate,目前是解决了问题,暂时没有发现副作用。
若有问题,还请多多指教!!
这一篇,真是不容易,过山车一般。把思路和走过的错误道路记录下来,希望大家别在走弯路。
希望你能点赞支持,手留余香!!
六、参考
【1】 http://www.ceeger.com/Script/QualitySettings/QualitySettings.html
【2】 http://answers.unity3d.com/questions/1209337/vrvive-allow-rotation-only.html
【3】 http://blog.csdn.net/cartzhang/article/details/71136498
【4】 https://steamcommunity.com/app/358720/discussions/0/365163686052028359/
- 理解HTC Vive更新——控制相机旋转和位移
- Unity +HTC VIVE 虚拟现实开发— 手柄控制
- [HTC Vive + Unity开发]——VRTK的研究——用手柄旋转物体(使用VRTK_Knob脚本)
- HTC VIVE TouchPad简单方向控制
- HTC Vive手柄圆盘控制角色移动
- Unity +HTC VIVE 虚拟现实开发— 移动漫游
- Unity +HTC VIVE 虚拟现实开发— UI设计(UGUI)
- Unity +HTC VIVE 虚拟现实开发— 手柄震动
- Unity +HTC VIVE 虚拟现实开发— 警示线处理
- Unity +HTC VIVE 虚拟现实开发— 移动漫游
- 转载一篇用htc vive手柄旋转物体的代码
- HTC vive开发:关于手柄按键对接控制
- HTC vive开发:关于手柄按键对接控制
- 酷科技 | HTC Vive可控制丰田人形机器人
- IOS系列——简单动画-位移和渐隐和旋转
- Android图片旋转,缩放,位移,倾斜,对称完整示例(二)——Bitmap.createBitmap()和Matrix
- HTC Vive 新体验——奥秘之家VR实体店之行
- HTC Vive之Unity3d开发日记——手柄交互编程
- ACM必学知识点清单.
- UVA
- ionic图片懒加载的实现整合 --ionic-image-lazy-load.js
- EventTrigger触发3D物体事件
- map用法测试(遍历)
- 理解HTC Vive更新——控制相机旋转和位移
- node-发送邮件-nodemailer
- ReactJS读书笔记一:深入理解JSX
- HDU5172
- 记录一次使用_RecordsetPtr去访问已有表的新增字段时,出现的怪异问题!
- Android NDK 使用JNI调用java代码,通用代码封装
- Spring+SpringMVC+Mybatis 多数据源整合
- linux下使用串口调试助手XGcom
- ReactJS读书笔记二:组件生命周期