NxrDevice.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. // Copyright 2016 Nibiru. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. using UnityEngine;
  15. using System.Runtime.InteropServices;
  16. using System;
  17. /// @cond
  18. namespace Nxr.Internal
  19. {
  20. public abstract class NxrDevice :
  21. #if UNITY_ANDROID
  22. BaseAndroidDevice
  23. #else
  24. BaseARDevice
  25. #endif
  26. {
  27. // A relatively unique id to use when calling our C++ native render plugin.
  28. private const int kRenderEvent = 0x47554342;
  29. // Event IDs sent up from native layer. Bit flags.
  30. // Keep in sync with the corresponding declaration in unity.h.
  31. private const int kTilted = 1 << 1;
  32. private const int kProfileChanged = 1 << 2;
  33. private const int kVRBackButtonPressed = 1 << 3;
  34. private float[] position = new float[3];
  35. private float[] headData = new float[16];
  36. private float[] viewData = new float[16 * 6 + 12];
  37. private float[] profileData = new float[15];
  38. private Matrix4x4 headView = new Matrix4x4();
  39. private Matrix4x4 leftEyeView = new Matrix4x4();
  40. private Matrix4x4 rightEyeView = new Matrix4x4();
  41. private int _timewarp_view_number = 0;
  42. private bool isHeadPoseUpdated = false;
  43. public override NibiruService GetNibiruService()
  44. {
  45. return NxrGlobal.nibiruService;
  46. }
  47. public override void Init()
  48. {
  49. // Start will send a log event, so SetUnityVersion first.
  50. byte[] version = System.Text.Encoding.UTF8.GetBytes(Application.unityVersion);
  51. if (NxrViewer.USE_DTR)
  52. {
  53. if (!NxrGlobal.nvrStarted)
  54. {
  55. if (nibiruVRServiceId == 0)
  56. {
  57. // 初始化1次service
  58. nibiruVRServiceId = CreateNibiruVRService();
  59. }
  60. _NVR_InitAPIs(NxrGlobal.useNvrSo);
  61. _NVR_SetUnityVersion(version, version.Length);
  62. _NVR_Start(nibiruVRServiceId);
  63. SetDisplayQuality((int) NxrViewer.Instance.TextureQuality);
  64. SetMultiThreadedRendering(SystemInfo.graphicsMultiThreaded);
  65. Debug.LogError("graphicsMultiThreaded=" + SystemInfo.graphicsMultiThreaded);
  66. //
  67. if (NxrGlobal.soVersion >= 361)
  68. {
  69. ColorSpace colorSpace = QualitySettings.activeColorSpace;
  70. if (colorSpace == ColorSpace.Gamma)
  71. {
  72. Debug.Log("Color Space - Gamma");
  73. SetColorspaceType(0);
  74. }
  75. else if (colorSpace == ColorSpace.Linear)
  76. {
  77. Debug.Log("Color Space - Linear");
  78. SetColorspaceType(1);
  79. }
  80. } else
  81. {
  82. Debug.LogError("System Api Not Support ColorSpace!!!");
  83. }
  84. if (NxrGlobal.soVersion >= 365)
  85. {
  86. Debug.Log("Controller Support Mode - " + NxrViewer.Instance.controllerSupportMode.ToString());
  87. SetControllerSupportMode(NxrViewer.Instance.controllerSupportMode);
  88. }
  89. NxrGlobal.nvrStarted = true;
  90. // 初始化服务
  91. NibiruService nibiruService = new NibiruService();
  92. nibiruService.Init();
  93. NxrGlobal.nibiruService = nibiruService;
  94. //
  95. NxrSDKApi.Instance.IsSptEyeLocalRp = IsSptEyeLocalRotPos();
  96. if (NxrSDKApi.Instance.IsSptEyeLocalRp)
  97. {
  98. _NVR_GetEyeLocalRotPos(NxrSDKApi.Instance.LeftEyeLocalRotation,
  99. NxrSDKApi.Instance.LeftEyeLocalPosition, NxrSDKApi.Instance.RightEyeLocalRotation,
  100. NxrSDKApi.Instance.RightEyeLocalPosition);
  101. }
  102. }
  103. }
  104. Debug.Log("NxrDevice->Init.isSptEyeLocalRp=" + NxrSDKApi.Instance.IsSptEyeLocalRp);
  105. }
  106. public override int GetTimewarpViewNumber()
  107. {
  108. return _timewarp_view_number;
  109. }
  110. public override bool IsHeadPoseUpdated()
  111. {
  112. return isHeadPoseUpdated;
  113. }
  114. public override void UpdateState()
  115. {
  116. if (NxrViewer.USE_DTR)
  117. {
  118. _NVR_GetHeadPoseAndPosition(position, headData , ref _timewarp_view_number);
  119. NxrSDKApi.Instance.HeadPosition = new Vector3(position[0], position[1], position[2]);
  120. // Debug.LogError("HeadPosition:" + position[0] + "," + position[1] + "," + position[2]);
  121. if(NxrViewer.Instance.SixDofMode == SixDofMode.Head_3Dof_Ctrl_3Dof ||
  122. NxrViewer.Instance.SixDofMode == SixDofMode.Head_3Dof_Ctrl_6Dof)
  123. {
  124. position[0] = 0.0f;
  125. position[1] = 0.0f;
  126. position[2] = 0.0f;
  127. }
  128. if(position[0] != 0 || position[1] != 0 || position[2] != 0)
  129. {
  130. if(NxrViewer.onSixDofPosition != null)
  131. NxrViewer.onSixDofPosition(position[0], position[1], position[2]);
  132. }
  133. }
  134. // 头部锁定
  135. if ((NxrGlobal.verifyStatus >= 0 && NxrGlobal.verifyStatus != VERIFY_STATUS.SUCC) || NxrViewer.Instance.LockHeadTracker || (headData[0] == 0 && headData[15] == 0))
  136. {
  137. headData = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
  138. }
  139. if(NxrGlobal.verifyStatus >= 0 && NxrGlobal.verifyStatus != VERIFY_STATUS.SUCC)
  140. {
  141. AndroidLog("------------------------------Verify Failed : " +NxrGlobal.verifyStatus + "------------------------------");
  142. }
  143. ExtractMatrix(ref headView, headData);
  144. headPose.SetRightHanded(headView);
  145. headPose.SetPosition(new Vector3(position[0], position[1], position[2]));
  146. isHeadPoseUpdated = true;
  147. }
  148. public override void UpdateScreenData()
  149. {
  150. bool useDFT = NxrViewer.USE_DTR && !NxrGlobal.supportDtr;
  151. // so获取
  152. UpdateProfile();
  153. UpdateView();
  154. // so获取
  155. if(useDFT || NxrViewer.Instance.IsWinPlatform)
  156. {
  157. float far = NxrGlobal.fovFar > -1 ? NxrGlobal.fovFar : (Camera.main != null ? Camera.main.farClipPlane : 20000.0f);
  158. ComputeEyesFromProfile(1, far);
  159. }
  160. profileChanged = true;
  161. }
  162. public override void Recenter()
  163. {
  164. if (NxrViewer.USE_DTR)
  165. {
  166. _NVR_ResetHeadPose();
  167. }
  168. }
  169. public override void PostRender(RenderTexture stereoScreen)
  170. {
  171. // do nothing
  172. }
  173. public override void EnterARMode() {
  174. Debug.Log("NxrDevice->EnterARMode");
  175. NxrPluginEvent.Issue(NibiruRenderEventType.BeginVR);
  176. _NVR_ApplicationResume();
  177. // 更新参数信息
  178. UpdateScreenData();
  179. }
  180. public override void OnApplicationPause(bool pause)
  181. {
  182. Debug.Log("NxrDevice->OnApplicationPause." + pause);
  183. base.OnApplicationPause(pause);
  184. // 程序暂停
  185. if (pause)
  186. {
  187. Debug.Log("NxrDevice->OnPause");
  188. if (NxrViewer.USE_DTR)
  189. {
  190. NxrSDKApi.Instance.IsInXRMode = false;
  191. NxrPluginEvent.Issue(NibiruRenderEventType.EndVR);
  192. _NVR_ApplicationPause();
  193. }
  194. }
  195. else
  196. {
  197. Debug.Log("NxrDevice->OnResume");
  198. if (NxrViewer.USE_DTR)
  199. {
  200. NxrSDKApi.Instance.IsInXRMode = true;
  201. NxrPluginEvent.Issue(NibiruRenderEventType.BeginVR);
  202. _NVR_ApplicationResume();
  203. UpdateScreenData();
  204. }
  205. }
  206. }
  207. public override void Destroy()
  208. {
  209. Debug.Log("NxrDevice->Destroy");
  210. base.Destroy();
  211. }
  212. private bool applicationQuited = false;
  213. public override void OnApplicationQuit()
  214. {
  215. if (NxrViewer.USE_DTR && !applicationQuited)
  216. { // 关闭陀螺仪
  217. Input.gyro.enabled = false;
  218. NxrPluginEvent.Issue(NibiruRenderEventType.ShutDown);
  219. _NVR_ApplicationDestory();
  220. }
  221. applicationQuited = true;
  222. base.OnApplicationQuit();
  223. Debug.Log("NxrDevice->OnApplicationQuit.");
  224. }
  225. private void UpdateView()
  226. {
  227. if (NxrViewer.USE_DTR)
  228. {
  229. _NVR_GetViewParameters(viewData);
  230. }
  231. int j = 0;
  232. j = ExtractMatrix(ref leftEyeView, viewData, j);
  233. j = ExtractMatrix(ref rightEyeView, viewData, j);
  234. if (NxrViewer.USE_DTR)
  235. {
  236. // 转置处理
  237. leftEyeView = leftEyeView.transpose;
  238. rightEyeView = rightEyeView.transpose;
  239. }
  240. //leftEyePose.SetRightHanded(leftEyeView.inverse);
  241. //rightEyePose.SetRightHanded(rightEyeView.inverse);
  242. j = ExtractMatrix(ref leftEyeDistortedProjection, viewData, j);
  243. j = ExtractMatrix(ref rightEyeDistortedProjection, viewData, j);
  244. j = ExtractMatrix(ref leftEyeUndistortedProjection, viewData, j);
  245. j = ExtractMatrix(ref rightEyeUndistortedProjection, viewData, j);
  246. if (NxrViewer.USE_DTR)
  247. {
  248. // 转置处理
  249. leftEyeDistortedProjection = leftEyeDistortedProjection.transpose;
  250. rightEyeDistortedProjection = rightEyeDistortedProjection.transpose;
  251. leftEyeUndistortedProjection = leftEyeUndistortedProjection.transpose;
  252. rightEyeUndistortedProjection = rightEyeUndistortedProjection.transpose;
  253. }
  254. leftEyeUndistortedViewport.Set(viewData[j], viewData[j + 1], viewData[j + 2], viewData[j + 3]);
  255. leftEyeDistortedViewport = leftEyeUndistortedViewport;
  256. j += 4;
  257. rightEyeUndistortedViewport.Set(viewData[j], viewData[j + 1], viewData[j + 2], viewData[j + 3]);
  258. rightEyeDistortedViewport = rightEyeUndistortedViewport;
  259. j += 4;
  260. // 屏幕大小,纹理生成大小 1920*1080
  261. int screenWidth = (int)viewData[j];
  262. int screenHeight = (int)viewData[j + 1];
  263. j += 2;
  264. recommendedTextureSize = new Vector2(viewData[j], viewData[j + 1]);
  265. j += 2;
  266. if (NxrViewer.USE_DTR && !NxrGlobal.supportDtr) {
  267. // DFT
  268. recommendedTextureSize = new Vector2(screenWidth, screenHeight);
  269. Debug.Log("DFT texture size : " +screenWidth + "," + screenHeight);
  270. }
  271. }
  272. private void UpdateProfile()
  273. {
  274. if (NxrViewer.USE_DTR)
  275. {
  276. _NVR_GetNVRConfig(profileData);
  277. }
  278. if (profileData[13] > 0)
  279. {
  280. NxrGlobal.fovNear = profileData[13];
  281. }
  282. if (profileData[14] > 0)
  283. {
  284. NxrGlobal.fovFar = profileData[14] > NxrGlobal.fovFar ? profileData[14] : NxrGlobal.fovFar;
  285. }
  286. if (NxrViewer.USE_DTR && !NxrGlobal.supportDtr && NxrGlobal.dftProfileParams[0] != 0)
  287. {
  288. // DFT模式加载cardboard参数 0.062_0.03725_0.06_40.0_40.0_43.3_43.3_0.11825_0.39027_1920.0_1080.0_0.003_0.126_0.0625_-1
  289. // fov
  290. profileData[0] = NxrGlobal.dftProfileParams[3];//45;
  291. profileData[1] = NxrGlobal.dftProfileParams[4]; //45;
  292. profileData[2] = NxrGlobal.dftProfileParams[5]; //51.5f;
  293. profileData[3] = NxrGlobal.dftProfileParams[6]; //51.5f;
  294. // screen size
  295. profileData[4] = NxrGlobal.dftProfileParams[12]; //0.110f;
  296. profileData[5] = NxrGlobal.dftProfileParams[13]; //0.062f;
  297. // ipd
  298. profileData[7] = NxrGlobal.dftProfileParams[0]; //0.063f;
  299. // screen to lens
  300. profileData[9] = NxrGlobal.dftProfileParams[2]; //0.035f;
  301. // k1 k2
  302. profileData[11] = NxrGlobal.dftProfileParams[7]; //0.252f;
  303. profileData[12] = NxrGlobal.dftProfileParams[8]; //0.019f;
  304. if(NxrGlobal.offaxisDistortionEnabled)
  305. {
  306. // profileData[7] = 0.058f;
  307. }
  308. }
  309. NxrProfile.Viewer device = new NxrProfile.Viewer();
  310. NxrProfile.Screen screen = new NxrProfile.Screen();
  311. // left top right bottom
  312. device.maxFOV.outer = profileData[0];
  313. device.maxFOV.upper = profileData[2];
  314. device.maxFOV.inner = profileData[1];
  315. device.maxFOV.lower = profileData[3];
  316. screen.width = profileData[4];
  317. screen.height = profileData[5];
  318. screen.border = profileData[6];
  319. device.lenses.separation = profileData[7];
  320. device.lenses.offset = profileData[8];
  321. device.lenses.screenDistance = profileData[9];
  322. device.lenses.alignment = (int)profileData[10];
  323. device.distortion.Coef = new[] { profileData[11], profileData[12] };
  324. Profile.screen = screen;
  325. Profile.viewer = device;
  326. float[] rect = new float[4];
  327. Profile.GetLeftEyeNoLensTanAngles(rect);
  328. float maxRadius = NxrProfile.GetMaxRadius(rect);
  329. Profile.viewer.inverse = NxrProfile.ApproximateInverse(
  330. Profile.viewer.distortion, maxRadius);
  331. }
  332. private static int ExtractMatrix(ref Matrix4x4 mat, float[] data, int i = 0)
  333. {
  334. // 列优先
  335. // Matrices returned from our native layer are in row-major order.
  336. for (int r = 0; r < 4; r++)
  337. {
  338. for (int c = 0; c < 4; c++, i++)
  339. {
  340. mat[r, c] = data[i];
  341. }
  342. }
  343. return i;
  344. }
  345. public override IntPtr NGetRenderEventFunc() {
  346. return _NVR_GetRenderEventFunc();
  347. }
  348. public override void NSetSystemSplitMode(int flag) {
  349. _NVR_SetSystemVRMode(flag);
  350. }
  351. public override void NLockTracker()
  352. {
  353. _NVR_LockHeadPose();
  354. }
  355. public override void NUnLockTracker()
  356. {
  357. _NVR_UnLockHeadPose();
  358. }
  359. public override void SetTextureSizeNative(int w, int h)
  360. {
  361. // 1920*1080 = 1920*10000 + 1080 = 19201080
  362. _NVR_SetParamI(1002, w * 10000 + h);
  363. }
  364. public override void SetCpuLevel(NxrOverrideSettings.PerfLevel level)
  365. {
  366. _NVR_SetParamI(1003, (int) level);
  367. }
  368. public override void SetGpuLevel(NxrOverrideSettings.PerfLevel level)
  369. {
  370. _NVR_SetParamI(1004, (int)level);
  371. }
  372. public override void NIssuePluginEvent(int eventID)
  373. {
  374. // Queue a specific callback to be called on the render thread
  375. GL.IssuePluginEvent(NxrViewer.Instance.GetDevice().NGetRenderEventFunc(), eventID);
  376. }
  377. public override void SetColorspaceType(int colorSpace)
  378. {
  379. _NVR_SetParamI((int)PARAMS_KEY.COLOR_SPACE, colorSpace);
  380. }
  381. public override void SetControllerSupportMode(ControllerSupportMode csm)
  382. {
  383. _NVR_SetParamI((int)PARAMS_KEY.CONTROLLER_SUPPORT, (int) csm);
  384. }
  385. public override void SetMultiThreadedRendering(bool isMultiThreadedRendering)
  386. {
  387. _NVR_SetParamI((int)PARAMS_KEY.MULTITHREAD_RENDERING, isMultiThreadedRendering ? 1 : 0);
  388. }
  389. public override bool IsSptEyeLocalRotPos()
  390. {
  391. return _NVR_GetParamI((int)PARAMS_KEY.EYE_LOCAL_ROT_POS) == 1;
  392. }
  393. public override Quaternion GetEyeLocalRotation(NxrViewer.Eye eye)
  394. {
  395. float[] eulerAngles = new float[3];
  396. if(eye == NxrViewer.Eye.Left)
  397. {
  398. NxrCameraUtils.RotationMatrixToEulerAngles(ref eulerAngles, NxrSDKApi.Instance.LeftEyeLocalRotation);
  399. }
  400. else if(eye == NxrViewer.Eye.Right)
  401. {
  402. NxrCameraUtils.RotationMatrixToEulerAngles(ref eulerAngles, NxrSDKApi.Instance.RightEyeLocalRotation);
  403. }
  404. return Quaternion.Euler(eulerAngles[0], eulerAngles[1], eulerAngles[2]);
  405. }
  406. public override Vector3 GetEyeLocalPosition(NxrViewer.Eye eye)
  407. {
  408. if (eye == NxrViewer.Eye.Left)
  409. {
  410. return new Vector3(NxrSDKApi.Instance.LeftEyeLocalPosition[0], NxrSDKApi.Instance.LeftEyeLocalPosition[1], NxrSDKApi.Instance.LeftEyeLocalPosition[2]);
  411. }
  412. else if (eye == NxrViewer.Eye.Right)
  413. {
  414. return new Vector3(NxrSDKApi.Instance.RightEyeLocalPosition[0], NxrSDKApi.Instance.RightEyeLocalPosition[1], NxrSDKApi.Instance.RightEyeLocalPosition[2]);
  415. }
  416. return Vector3.zero;
  417. }
  418. public enum PARAMS_KEY
  419. {
  420. CONTROLLER_SUPPORT=1006,
  421. COLOR_SPACE = 1007,
  422. TURN_AROUND_STATE=1008,
  423. TURN_AROUND_YAWOFFSET=1009,
  424. MULTITHREAD_RENDERING=1010,
  425. EYE_LOCAL_ROT_POS = 1011
  426. }
  427. // 调用跳转so
  428. private const string nvrDllName = "nvr_unity";
  429. [DllImport(nvrDllName)]
  430. private static extern int _NVR_InitAPIs(bool supportDTR);
  431. [DllImport(nvrDllName)]
  432. private static extern bool _NVR_Start(long pointer);
  433. [DllImport(nvrDllName)]
  434. private static extern void _NVR_SetUnityVersion(byte[] version_str, int version_length);
  435. [DllImport(nvrDllName)]
  436. private static extern int _NVR_GetEventFlags();
  437. [DllImport(nvrDllName)]
  438. private static extern void _NVR_GetNVRConfig(float[] profile);
  439. [DllImport(nvrDllName)]
  440. private static extern void _NVR_GetHeadPose(float[] pose, ref int viewNumber);
  441. [DllImport(nvrDllName)]
  442. private static extern void _NVR_GetHeadPoseAndPosition(float[] position, float[] pose, ref int viewNumber);
  443. [DllImport(nvrDllName)]
  444. private static extern void _NVR_ResetHeadPose();
  445. [DllImport(nvrDllName)]
  446. private static extern void _NVR_GetViewParameters(float[] viewParams);
  447. [DllImport(nvrDllName)]
  448. private static extern void _NVR_ApplicationPause();
  449. [DllImport(nvrDllName)]
  450. private static extern void _NVR_ApplicationResume();
  451. [DllImport(nvrDllName)]
  452. private static extern void _NVR_ApplicationDestory();
  453. [DllImport(nvrDllName)]
  454. private static extern IntPtr _NVR_GetRenderEventFunc();
  455. [DllImport(nvrDllName)]
  456. private static extern void _NVR_LockHeadPose();
  457. [DllImport(nvrDllName)]
  458. private static extern void _NVR_UnLockHeadPose();
  459. [DllImport(nvrDllName)]
  460. private static extern void _NVR_SetSystemVRMode(int flag);
  461. [DllImport(nvrDllName)]
  462. private static extern void _NVR_SetParamI(int key, int value);
  463. [DllImport(nvrDllName)]
  464. private static extern int _NVR_GetParamI(int key);
  465. [DllImport(nvrDllName)]
  466. private static extern void _NVR_GetEyeLocalRotPos(float[] leftEyeRot, float[] leftEyePos, float[] rightEyeRot, float[] rightEyePos);
  467. }
  468. }
  469. /// @endcond