Unity SDK Docs 1.5.0-beta.6
Loading...
Searching...
No Matches
Display.cs
1/*
2 * Copyright (C) 2020-2023 Tilt Five, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16using System;
17using UnityEngine;
18
20
21namespace TiltFive
22{
23 [Serializable]
24 public class AxesBoolean
25 {
26 public bool x = true;
27 public bool y = true;
28 public bool z = true;
29
30 public AxesBoolean(bool setX, bool setY, bool setZ)
31 {
32 x = setX;
33 y = setY;
34 z = setZ;
35 }
36 }
37
38 [Serializable]
39 public class AllAxesBoolean
40 {
41 public bool xyz = true;
42
43 public AllAxesBoolean(bool setXYZ)
44 {
45 xyz = setXYZ;
46 }
47 }
48
49 public struct ARProjectionFrustum
50 {
51 public float m_Left;
52 public float m_Right;
53 public float m_Bottom;
54 public float m_Top;
55 public float m_Near;
56 public float m_Far;
57
58
59 public ARProjectionFrustum(float l, float r, float b, float t, float n, float f)
60 {
61 m_Left = l; m_Right = r; m_Bottom = b; m_Top = t; m_Near = n; m_Far = f;
62 }
63 }
64
65 public class Display : TiltFive.SingletonComponent<Display>
66 {
67 // Frame sender render-thread callback.
68 [NonSerialized]
69 IntPtr _sendFrameCallback = IntPtr.Zero;
70
71 protected override void Awake()
72 {
73 base.Awake();
74
75 try
76 {
77 _sendFrameCallback = NativePlugin.GetSendFrameCallback();
78 }
79 catch (System.DllNotFoundException e)
80 {
81 Log.Info("Could not connect to Tilt Five plugin to get callback: {0}", e);
82 }
83 catch (Exception e)
84 {
85 Log.Error(e.Message);
86 }
87
88 LogVersion();
89
90 QualitySettings.vSyncCount = 0;
91 QualitySettings.maxQueuedFrames = 0;
92 }
93
94 private void LogVersion()
95 {
96 string version = "NOT VERSIONED";
97
98 // load version file and get the string value
99 TextAsset asset = (TextAsset)Resources.Load("pluginversion", typeof(TextAsset));
100 if (asset != null)
101 {
102 version = asset.text;
103 }
104
105 // turn on logging if it was turned off
106 bool logEnabled = Debug.unityLogger.logEnabled;
107 if (!logEnabled)
108 {
109 Debug.unityLogger.logEnabled = true;
110 }
111
112 // get previous setting
113 StackTraceLogType logType = Application.GetStackTraceLogType(LogType.Log);
114
115 // turn off stacktrace logging for our messaging
116 Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
117
118 Log.Info("\n********************************" +
119 "\n* Tilt Five: Unity SDK Version - " +
120 version +
121 "\n********************************");
122
123 // reset to initial log settings
124 Application.SetStackTraceLogType(LogType.Log, logType);
125
126 // reset logging enabled to previous
127 Debug.unityLogger.logEnabled = logEnabled;
128 }
129
130 [Obsolete("This function has been moved into TiltFive.SystemControl", true)]
131 public static bool SetApplicationInfo()
132 {
133 return SystemControl.SetApplicationInfo();
134 }
135
141 public static bool GetGlassesAvailability()
142 {
145 }
146
147 static public bool PresentStereoImages(
148 PlayerIndex playerIndex,
149 IntPtr leftTexHandle,
150 IntPtr rightTexHandle,
151 int texWidth_PIX,
152 int texHeight_PIX,
153 bool isSrgb,
154 float fovYDegrees,
155 float widthToHeightRatio,
156 Quaternion rotToUSTAGE_ULVC,
157 Vector3 posOfULVC_USTAGE,
158 Quaternion rotToUSTAGE_URVC,
159 Vector3 posOfURVC_USTAGE) {
160 return Player.TryGetGlassesHandle(playerIndex, out var glassesHandle)
161 && PresentStereoImages(glassesHandle,
162 leftTexHandle,
163 rightTexHandle,
164 texWidth_PIX,
165 texHeight_PIX,
166 isSrgb,
167 fovYDegrees,
168 widthToHeightRatio,
169 rotToUSTAGE_ULVC,
170 posOfULVC_USTAGE,
171 rotToUSTAGE_URVC,
172 posOfURVC_USTAGE);
173 }
174
175 static internal bool PresentStereoImages(
176 GlassesHandle glassesHandle,
177 IntPtr leftTexHandle,
178 IntPtr rightTexHandle,
179 int texWidth_PIX,
180 int texHeight_PIX,
181 bool isSrgb,
182 float fovYDegrees,
183 float widthToHeightRatio,
184 Quaternion rotToUSTAGE_ULVC,
185 Vector3 posOfULVC_USTAGE,
186 Quaternion rotToUSTAGE_URVC,
187 Vector3 posOfURVC_USTAGE)
188 {
189 return Instance.PresentStereoImagesImpl(glassesHandle,
190 leftTexHandle,
191 rightTexHandle,
192 texWidth_PIX,
193 texHeight_PIX,
194 isSrgb,
195 fovYDegrees,
196 widthToHeightRatio,
197 rotToUSTAGE_ULVC,
198 posOfULVC_USTAGE,
199 rotToUSTAGE_URVC,
200 posOfURVC_USTAGE);
201 }
202
203 bool PresentStereoImagesImpl(
204 UInt64 glassesHandle,
205 IntPtr leftTexHandle,
206 IntPtr rightTexHandle,
207 int texWidth_PIX,
208 int texHeight_PIX,
209 bool isSrgb,
210 float fovYDegrees,
211 float widthToHeightRatio,
212 Quaternion rotToUSTAGE_ULVC,
213 Vector3 posOfULVC_USTAGE,
214 Quaternion rotToUSTAGE_URVC,
215 Vector3 posOfURVC_USTAGE)
216 {
217 // Unity reference frames:
218 //
219 // ULVC / URVC - Unity Left/Right Virtual Camera space.
220 // +x right, +y up, +z forward
221 // USTAGE - Unity Stage space.
222 // +x right, +y up, +z forward
223 //
224 // Tilt Five reference frames:
225 //
226 // DC - Our right-handed version of Unity's default camera space
227 // (the LVC/RVC if there is no transform set on ULVC/URVC).
228 // +x right, +y up, +z backward
229 // LVC / RVC - Left/Right Virtual Camera space.
230 // +x right, +y up, +z backward
231 // STAGE - Stage space.
232 // +x right, +y forward, +z up
233
234 Quaternion rotToDC_STAGE = Quaternion.AngleAxis(-90f, Vector3.right);
235
236 // Calculate the VCI (the image rectangle in the normalized (z=1) image space of the virtual cameras)
237 float startY_VCI = -Mathf.Tan(fovYDegrees * (0.5f * Mathf.PI / 180.0f));
238 float startX_VCI = startY_VCI * widthToHeightRatio;
239 float width_VCI = -2f * startX_VCI;
240 float height_VCI = -2f * startY_VCI;
241 Rect vci = new Rect(startX_VCI, startY_VCI, width_VCI, height_VCI);
242
243 // Swizzle the left-handed Unity-based coordinates into our right-handed reference frames
244 Quaternion rotToLVC_DC = new Quaternion(rotToUSTAGE_ULVC.x, rotToUSTAGE_ULVC.y, -rotToUSTAGE_ULVC.z, rotToUSTAGE_ULVC.w);
245 Quaternion rotToRVC_DC = new Quaternion(rotToUSTAGE_URVC.x, rotToUSTAGE_URVC.y, -rotToUSTAGE_URVC.z, rotToUSTAGE_URVC.w);
246
247 Quaternion rotToLVC_STAGE = rotToLVC_DC * rotToDC_STAGE;
248 Quaternion rotToRVC_STAGE = rotToRVC_DC * rotToDC_STAGE;
249
250 // Swap the Y and Z axes to switch from left-handed to right-handed coords
251 Vector3 posOfLVC_STAGE = new Vector3(posOfULVC_USTAGE.x, posOfULVC_USTAGE.z, posOfULVC_USTAGE.y);
252 Vector3 posOfRVC_STAGE = new Vector3(posOfURVC_USTAGE.x, posOfURVC_USTAGE.z, posOfURVC_USTAGE.y);
253
254 // Build our frame info struct now that we're finished converting from Unity's coord space
255 T5_FrameInfo frameInfo = new T5_FrameInfo();
256
257 frameInfo.LeftTexHandle = leftTexHandle;
258 frameInfo.RightTexHandle = rightTexHandle;
259
260 frameInfo.TexWidth_PIX = (UInt16) texWidth_PIX;
261 frameInfo.TexHeight_PIX = (UInt16) texHeight_PIX;
262
263 frameInfo.IsSrgb = isSrgb;
264 frameInfo.IsUpsideDown = false; // False for Unity, but possibly true for other engines
265
266 frameInfo.VCI = vci;
267
268 frameInfo.RotToLVC_STAGE = rotToLVC_STAGE;
269 frameInfo.PosOfLVC_STAGE = posOfLVC_STAGE;
270
271 frameInfo.RotToRVC_STAGE = rotToRVC_STAGE;
272 frameInfo.PosOfRVC_STAGE = posOfRVC_STAGE;
273
274 int result = NativePlugin.T5_RESULT_UNKNOWN_ERROR;
275 try
276 {
277 result = NativePlugin.QueueStereoImages(glassesHandle, frameInfo);
278 }
279 catch (Exception e)
280 {
281 Log.Error(e.Message);
282 }
283
284 if (result != NativePlugin.T5_RESULT_SUCCESS) {
285 return false;
286 }
287
288 if(_sendFrameCallback == IntPtr.Zero)
289 {
290 // We failed to set _sendFrameCallback during Awake() - let's try again
291 try
292 {
293 _sendFrameCallback = NativePlugin.GetSendFrameCallback();
294 }
295 catch (Exception)
296 {
297 Log.Error("Unable to send frame - the native plugin DLL may be failing to load");
298 return false;
299 }
300
301 if (_sendFrameCallback == IntPtr.Zero)
302 {
303 // If we reach this point, the native plugin loaded, but erroneously gave us a null callback
304 Log.Error("Unable to send frame - the native plugin returned a null SendFrame callback");
305 return false;
306 }
307 }
308
309 try
310 {
311 GL.IssuePluginEvent(_sendFrameCallback, 0);
312 GL.InvalidateState();
313 }
314 catch (Exception e)
315 {
316 Log.Error($"Failed to execute sendFrame callback: {e.Message}");
317 return false;
318 }
319
320 return true;
321 }
322
323 [Obsolete("This function is obsolete. " +
324 "Please use GetDisplayDimensions(PlayerIndex playerIndex, " +
325 "ref Vector2Int displayDimensions) instead.")]
326 public static bool GetDisplayDimensions(ref Vector2Int displayDimensions)
327 {
328 return GetDisplayDimensions(PlayerIndex.One, ref displayDimensions);
329 }
330
331 public static bool GetDisplayDimensions(
332 PlayerIndex playerIndex,
333 ref Vector2Int displayDimensions)
334 {
335 if (!Player.TryGetGlassesHandle(playerIndex, out var glassesHandle))
336 {
337 return false;
338 }
339 return GetDisplayDimensions(glassesHandle, ref displayDimensions);
340 }
341
342 internal static bool GetDisplayDimensions(
343 GlassesHandle glassesHandle,
344 ref Vector2Int displayDimensions)
345 {
346 int result = NativePlugin.T5_RESULT_UNKNOWN_ERROR;
347 try
348 {
349 result = NativePlugin.GetMaxDisplayDimensions(
350 glassesHandle,
351 out var framebufferWidth,
352 out var framebufferHeight);
353
354 if(result == NativePlugin.T5_RESULT_SUCCESS)
355 {
356 displayDimensions = new Vector2Int(framebufferWidth, framebufferHeight);
357 }
358 else Log.Warn("Display.cs: Failed to retrieve display settings from plugin.");
359 }
360 catch (Exception e)
361 {
362 Log.Error(e.Message);
363 }
364
365 return result == NativePlugin.T5_RESULT_SUCCESS;
366 }
367
368 public static bool GetGlassesIPD(UInt64 glassesHandle, ref float glassesIPD)
369 {
370 return Instance.GetGlassesIPDImpl(glassesHandle, ref glassesIPD);
371 }
372
373 private bool GetGlassesIPDImpl(UInt64 glassesHandle, ref float glassesIPD)
374 {
375 int result = NativePlugin.T5_RESULT_UNKNOWN_ERROR;
376 try
377 {
378 result = NativePlugin.GetGlassesIPD(glassesHandle, ref glassesIPD);
379
380 if(result != NativePlugin.T5_RESULT_SUCCESS && GetGlassesAvailability())
381 {
382 Log.Warn("Display.cs: Failed to retrieve glasses IPD");
383 }
384 }
385 catch (Exception e)
386 {
387 Log.Error(e.Message);
388 }
389
390 return result == NativePlugin.T5_RESULT_SUCCESS;
391 }
392
393 internal static void ApplyGraphicsSettings(GraphicsSettings graphicsSettings)
394 {
395 // If we are optimizing the framerate and a player is connected, overwrite the application's target framerate and vsync settings.
396 if (graphicsSettings.matchGlassesFramerate && Player.TryGetFirstConnectedPlayer(out var anyPlayer))
397 {
398 Application.targetFrameRate = GraphicsSettings.PREFERRED_GLASSES_FRAMERATE;
399 QualitySettings.vSyncCount = GraphicsSettings.VSYNC_DISABLED;
400 }
401 // Otherwise, restore them to the settings we observed during Awake()
402 else
403 {
404 Application.targetFrameRate = graphicsSettings.applicationTargetFramerate;
405 QualitySettings.vSyncCount = graphicsSettings.applicationVSyncCount;
406 }
407 }
408 }
409
410 public class DisplayHelper
411 {
412 private static Matrix4x4 Frustum(ARProjectionFrustum f)
413 {
414 return Frustum(f.m_Left, f.m_Right, f.m_Bottom, f.m_Top, f.m_Near, f.m_Far);
415 }
416
417 /***********************************************************************
418 * This is our interpretation of glFrustum. CalculateObliqueMatrix
419 * has some params that I haven't figured out yet, so I'll use this
420 * instead.
421 ***********************************************************************/
422 public static Matrix4x4 Frustum(float L, float R, float B, float T, float n, float f)
423 {
424 Matrix4x4 m = new Matrix4x4();
425
426 m[0, 0] = (2 * n) / (R - L);
427 m[1, 1] = (2 * n) / (T - B);
428 m[0, 2] = (R + L) / (R - L);
429 m[1, 2] = (T + B) / (T - B);
430 m[2, 2] = -(f + n) / (f - n);
431 m[2, 3] = -(2 * f * n) / (f - n);
432 m[3, 2] = -1.0f;
433 m[3, 3] = 0.0f;
434
435 return m;
436 }
437 }
438}
static bool GetGlassesAvailability()
Get whether any glasses are available.
Definition Display.cs:141
bool matchGlassesFramerate
Determines whether the Tilt Five SDK should optimize the project's framerate and vsync for sending fr...
The Logger.
Definition Log.cs:42
static void Info(string m, params object[] list)
INFO logging function call.
Definition Log.cs:140
static void Error(string m, params object[] list)
ERROR logging function call.
Definition Log.cs:127
Provides access to player settings and functionality.
Definition Player.cs:31
static bool IsConnected(PlayerIndex playerIndex)
Determines whether the specified player has an associated pair of glasses connected.
Definition Player.cs:48
PlayerIndex
The Player index (e.g. Player One, Player Two, etc)