Tilt Five™ Unity API  1.3.0
 
Loading...
Searching...
No Matches
Display.cs
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-2022 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 System.Runtime.InteropServices;
18using UnityEngine;
19
21
22namespace TiltFive
23{
24 [Serializable]
25 public class AxesBoolean
26 {
27 public bool x = true;
28 public bool y = true;
29 public bool z = true;
30
31 public AxesBoolean(bool setX, bool setY, bool setZ)
32 {
33 x = setX;
34 y = setY;
35 z = setZ;
36 }
37 }
38
39 [Serializable]
40 public class AllAxesBoolean
41 {
42 public bool xyz = true;
43
44 public AllAxesBoolean(bool setXYZ)
45 {
46 xyz = setXYZ;
47 }
48 }
49
50 public struct ARProjectionFrustum
51 {
52 public float m_Left;
53 public float m_Right;
54 public float m_Bottom;
55 public float m_Top;
56 public float m_Near;
57 public float m_Far;
58
59
60 public ARProjectionFrustum(float l, float r, float b, float t, float n, float f)
61 {
62 m_Left = l; m_Right = r; m_Bottom = b; m_Top = t; m_Near = n; m_Far = f;
63 }
64 }
65
66 public class Display : TiltFive.SingletonComponent<Display>
67 {
68 // Display Settings.
69 [NonSerialized] int[] _displaySettings = new int[2];
70
71 // Frame sender render-thread callback.
72 [NonSerialized]
73 IntPtr _sendFrameCallback = IntPtr.Zero;
74
75 protected override void Awake()
76 {
77 base.Awake();
78
79 try
80 {
82 }
83 catch (System.DllNotFoundException e)
84 {
85 Log.Info("Could not connect to Tilt Five plugin to get callback: {0}", e);
86 }
87 catch (Exception e)
88 {
89 Log.Error(e.Message);
90 }
91
92 LogVersion();
93
94 QualitySettings.vSyncCount = 0;
95 QualitySettings.maxQueuedFrames = 0;
96 }
97
98 void Start()
99 {
100
101 }
102
103 void Update()
104 {
105
106 }
107
108 private void LogVersion()
109 {
110 string version = "NOT VERSIONED";
111
112 // load version file and get the string value
113 TextAsset asset = (TextAsset)Resources.Load("pluginversion", typeof(TextAsset));
114 if (asset != null)
115 {
116 version = asset.text;
117 }
118
119 // turn on logging if it was turned off
120 bool logEnabled = Debug.unityLogger.logEnabled;
121 if (!logEnabled)
122 {
123 Debug.unityLogger.logEnabled = true;
124 }
125
126 // get previous setting
127 StackTraceLogType logType = Application.GetStackTraceLogType(LogType.Log);
128
129 // turn off stacktrace logging for our messaging
130 Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
131
132 Log.Info("\n********************************" +
133 "\n* Tilt Five: Unity SDK Version - " +
134 version +
135 "\n********************************");
136
137 // reset to initial log settings
138 Application.SetStackTraceLogType(LogType.Log, logType);
139
140 // reset logging enabled to previous
141 Debug.unityLogger.logEnabled = logEnabled;
142 }
143
144 public static bool SetApplicationInfo()
145 {
146 return Instance.SetApplicationInfoImpl();
147 }
148
150 {
151 string applicationName = Application.productName;
152#if UNITY_EDITOR
153 // TODO: Localize
154 applicationName = $"Unity Editor: {applicationName}";
155#endif
156 string applicationId = Application.identifier;
157 string productVersion = Application.version;
158 string engineVersion = Application.unityVersion;
159 TextAsset pluginVersionAsset = (TextAsset)Resources.Load("pluginversion");
160 string applicationVersionInfo = $"App: {productVersion}, Engine: {engineVersion}, T5 SDK: {pluginVersionAsset.text}";
161
162 int result = 1;
163
164 try
165 {
166 using (T5_StringUTF8 appName = applicationName)
167 using (T5_StringUTF8 appId = applicationId)
168 using (T5_StringUTF8 appVersion = applicationVersionInfo)
169 {
170 result = NativePlugin.SetApplicationInfo(appName, appId, appVersion);
171 }
172 }
173 catch (System.DllNotFoundException e)
174 {
175 Log.Info("Could not connect to Tilt Five plugin to register project info: {0}", e);
176 }
177 catch (Exception)
178 {
179 Log.Error("Failed to register project info with the Tilt Five service.");
180 }
181
182 return result == 0;
183 }
184
190 public static bool GetGlassesAvailability()
191 {
194 }
195
196 static public bool PresentStereoImages(
197 PlayerIndex playerIndex,
198 IntPtr leftTexHandle,
199 IntPtr rightTexHandle,
200 int texWidth_PIX,
201 int texHeight_PIX,
202 bool isSrgb,
203 float fovYDegrees,
204 float widthToHeightRatio,
205 Quaternion rotToUGBD_ULVC,
206 Vector3 posOfULVC_UGBD,
207 Quaternion rotToUGBD_URVC,
208 Vector3 posOfURVC_UGBD) {
209 return Player.TryGetGlassesHandle(playerIndex, out var glassesHandle)
210 && PresentStereoImages(glassesHandle,
211 leftTexHandle,
212 rightTexHandle,
213 texWidth_PIX,
214 texHeight_PIX,
215 isSrgb,
216 fovYDegrees,
217 widthToHeightRatio,
218 rotToUGBD_ULVC,
219 posOfULVC_UGBD,
220 rotToUGBD_URVC,
221 posOfURVC_UGBD);
222 }
223
224 static internal bool PresentStereoImages(
225 GlassesHandle glassesHandle,
226 IntPtr leftTexHandle,
227 IntPtr rightTexHandle,
228 int texWidth_PIX,
229 int texHeight_PIX,
230 bool isSrgb,
231 float fovYDegrees,
232 float widthToHeightRatio,
233 Quaternion rotToUGBD_ULVC,
234 Vector3 posOfULVC_UGBD,
235 Quaternion rotToUGBD_URVC,
236 Vector3 posOfURVC_UGBD)
237 {
238 return Instance.PresentStereoImagesImpl(glassesHandle,
239 leftTexHandle,
240 rightTexHandle,
241 texWidth_PIX,
242 texHeight_PIX,
243 isSrgb,
244 fovYDegrees,
245 widthToHeightRatio,
246 rotToUGBD_ULVC,
247 posOfULVC_UGBD,
248 rotToUGBD_URVC,
249 posOfURVC_UGBD);
250 }
251
253 UInt64 glassesHandle,
254 IntPtr leftTexHandle,
255 IntPtr rightTexHandle,
256 int texWidth_PIX,
257 int texHeight_PIX,
258 bool isSrgb,
259 float fovYDegrees,
260 float widthToHeightRatio,
261 Quaternion rotToUGBD_ULVC,
262 Vector3 posOfULVC_UGBD,
263 Quaternion rotToUGBD_URVC,
264 Vector3 posOfURVC_UGBD)
265 {
266 // Unity reference frames:
267 //
268 // ULVC / URVC - Unity Left/Right Virtual Camera space.
269 // +x right, +y up, +z forward
270 // UGBD - Unity Gameboard space.
271 // +x right, +y up, +z forward
272 //
273 // Tilt Five reference frames:
274 //
275 // DC - Our right-handed version of Unity's default camera space
276 // (the LVC/RVC if there is no transform set on ULVC/URVC).
277 // +x right, +y up, +z backward
278 // LVC / RVC - Left/Right Virtual Camera space.
279 // +x right, +y up, +z backward
280 // GBD - Gameboard space.
281 // +x right, +y forward, +z up
282
283 Quaternion rotToDC_GBD = Quaternion.AngleAxis(-90f, Vector3.right);
284
285 // Calculate the VCI (the image rectangle in the normalized (z=1) image space of the virtual cameras)
286 float startY_VCI = -Mathf.Tan(fovYDegrees * (0.5f * Mathf.PI / 180.0f));
287 float startX_VCI = startY_VCI * widthToHeightRatio;
288 float width_VCI = -2f * startX_VCI;
289 float height_VCI = -2f * startY_VCI;
290 Rect vci = new Rect(startX_VCI, startY_VCI, width_VCI, height_VCI);
291
292 // Swizzle the left-handed Unity-based coordinates into our right-handed reference frames
293 Quaternion rotToLVC_DC = new Quaternion(rotToUGBD_ULVC.x, rotToUGBD_ULVC.y, -rotToUGBD_ULVC.z, rotToUGBD_ULVC.w);
294 Quaternion rotToRVC_DC = new Quaternion(rotToUGBD_URVC.x, rotToUGBD_URVC.y, -rotToUGBD_URVC.z, rotToUGBD_URVC.w);
295
296 Quaternion rotToLVC_GBD = rotToLVC_DC * rotToDC_GBD;
297 Quaternion rotToRVC_GBD = rotToRVC_DC * rotToDC_GBD;
298
299 // Swap the Y and Z axes to switch from left-handed to right-handed coords
300 Vector3 posOfLVC_GBD = new Vector3(posOfULVC_UGBD.x, posOfULVC_UGBD.z, posOfULVC_UGBD.y);
301 Vector3 posOfRVC_GBD = new Vector3(posOfURVC_UGBD.x, posOfURVC_UGBD.z, posOfURVC_UGBD.y);
302
303 // Build our frame info struct now that we're finished converting from Unity's coord space
304 T5_FrameInfo frameInfo = new T5_FrameInfo();
305
306 frameInfo.LeftTexHandle = leftTexHandle;
307 frameInfo.RightTexHandle = rightTexHandle;
308
309 frameInfo.TexWidth_PIX = (UInt16) texWidth_PIX;
310 frameInfo.TexHeight_PIX = (UInt16) texHeight_PIX;
311
312 frameInfo.IsSrgb = isSrgb;
313 frameInfo.IsUpsideDown = false; // False for Unity, but possibly true for other engines
314
315 frameInfo.VCI = vci;
316
317 frameInfo.RotToLVC_GBD = rotToLVC_GBD;
318 frameInfo.PosOfLVC_GBD = posOfLVC_GBD;
319
320 frameInfo.RotToRVC_GBD = rotToRVC_GBD;
321 frameInfo.PosOfRVC_GBD = posOfRVC_GBD;
322
323 int result = 1;
324 try
325 {
326 result = NativePlugin.QueueStereoImages(glassesHandle, frameInfo);
327 }
328 catch (Exception e)
329 {
330 Log.Error(e.Message);
331 }
332
333 if (result != 0) {
334 return false;
335 }
336
337 if(_sendFrameCallback == IntPtr.Zero)
338 {
339 // We failed to set _sendFrameCallback during Awake() - let's try again
340 try
341 {
343 }
344 catch (Exception)
345 {
346 Log.Error("Unable to send frame - the native plugin DLL may be failing to load");
347 return false;
348 }
349
350 if (_sendFrameCallback == IntPtr.Zero)
351 {
352 // If we reach this point, the native plugin loaded, but erroneously gave us a null callback
353 Log.Error("Unable to send frame - the native plugin returned a null SendFrame callback");
354 return false;
355 }
356 }
357
358 try
359 {
360 GL.IssuePluginEvent(_sendFrameCallback, 0);
361 GL.InvalidateState();
362 }
363 catch (Exception e)
364 {
365 Log.Error($"Failed to execute sendFrame callback: {e.Message}");
366 return false;
367 }
368
369 return true;
370 }
371
372 public static bool GetDisplayDimensions(ref Vector2Int displayDimensions)
373 {
374 return Instance.GetDisplayDimensionsImpl(ref displayDimensions);
375 }
376
377 private bool GetDisplayDimensionsImpl(ref Vector2Int displayDimensions)
378 {
379 int result = 1;
380 try
381 {
383
384 if(result == 0)
385 {
386 displayDimensions = new Vector2Int(_displaySettings[0], _displaySettings[1]);
387 }
388 else Log.Warn("Display.cs: Failed to retrieve display settings from plugin.");
389 }
390 catch (Exception e)
391 {
392 Log.Error(e.Message);
393 }
394
395 return (0 == result);
396 }
397
398 public static bool GetGlassesIPD(UInt64 glassesHandle, ref float glassesIPD)
399 {
400 return Instance.GetGlassesIPDImpl(glassesHandle, ref glassesIPD);
401 }
402
403 private bool GetGlassesIPDImpl(UInt64 glassesHandle, ref float glassesIPD)
404 {
405 int result = 1;
406 try
407 {
408 result = NativePlugin.GetGlassesIPD(glassesHandle, ref glassesIPD);
409
410 if(result != 0 && GetGlassesAvailability())
411 {
412 Log.Warn("Display.cs: Failed to retrieve glasses IPD");
413 }
414 }
415 catch (Exception e)
416 {
417 Log.Error(e.Message);
418 }
419
420 return (0 == result);
421 }
422 }
423
424 public class DisplayHelper
425 {
426 private static Matrix4x4 Frustum(ARProjectionFrustum f)
427 {
428 return Frustum(f.m_Left, f.m_Right, f.m_Bottom, f.m_Top, f.m_Near, f.m_Far);
429 }
430
431 /***********************************************************************
432 * This is our interpretation of glFrustum. CalculateObliqueMatrix
433 * has some params that I haven't figured out yet, so I'll use this
434 * instead.
435 ***********************************************************************/
436 public static Matrix4x4 Frustum(float L, float R, float B, float T, float n, float f)
437 {
438 Matrix4x4 m = new Matrix4x4();
439
440 m[0, 0] = (2 * n) / (R - L);
441 m[1, 1] = (2 * n) / (T - B);
442 m[0, 2] = (R + L) / (R - L);
443 m[1, 2] = (T + B) / (T - B);
444 m[2, 2] = -(f + n) / (f - n);
445 m[2, 3] = -(2 * f * n) / (f - n);
446 m[3, 2] = -1.0f;
447 m[3, 3] = 0.0f;
448
449 return m;
450 }
451 }
452}
AllAxesBoolean(bool setXYZ)
Definition: Display.cs:44
AxesBoolean(bool setX, bool setY, bool setZ)
Definition: Display.cs:31
static Matrix4x4 Frustum(float L, float R, float B, float T, float n, float f)
Definition: Display.cs:436
static Matrix4x4 Frustum(ARProjectionFrustum f)
Definition: Display.cs:426
void LogVersion()
Definition: Display.cs:108
bool PresentStereoImagesImpl(UInt64 glassesHandle, IntPtr leftTexHandle, IntPtr rightTexHandle, int texWidth_PIX, int texHeight_PIX, bool isSrgb, float fovYDegrees, float widthToHeightRatio, Quaternion rotToUGBD_ULVC, Vector3 posOfULVC_UGBD, Quaternion rotToUGBD_URVC, Vector3 posOfURVC_UGBD)
Definition: Display.cs:252
static bool GetDisplayDimensions(ref Vector2Int displayDimensions)
Definition: Display.cs:372
bool GetGlassesIPDImpl(UInt64 glassesHandle, ref float glassesIPD)
Definition: Display.cs:403
static bool GetGlassesIPD(UInt64 glassesHandle, ref float glassesIPD)
Definition: Display.cs:398
static bool SetApplicationInfo()
Definition: Display.cs:144
override void Awake()
Definition: Display.cs:75
IntPtr _sendFrameCallback
Definition: Display.cs:73
bool GetDisplayDimensionsImpl(ref Vector2Int displayDimensions)
Definition: Display.cs:377
static bool GetGlassesAvailability()
Get whether any glasses are available.
Definition: Display.cs:190
void Update()
Definition: Display.cs:103
void Start()
Definition: Display.cs:98
bool SetApplicationInfoImpl()
Definition: Display.cs:149
static bool PresentStereoImages(PlayerIndex playerIndex, IntPtr leftTexHandle, IntPtr rightTexHandle, int texWidth_PIX, int texHeight_PIX, bool isSrgb, float fovYDegrees, float widthToHeightRatio, Quaternion rotToUGBD_ULVC, Vector3 posOfULVC_UGBD, Quaternion rotToUGBD_URVC, Vector3 posOfURVC_UGBD)
Definition: Display.cs:196
int[] _displaySettings
Definition: Display.cs:69
The Logger.
Definition: Log.cs:42
static void Warn(string m, params object[] list)
WARN logging function call.
Definition: Log.cs:166
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
static int GetGlassesIPD(UInt64 glassesHandle, ref float glassesIPD)
static int QueueStereoImages(UInt64 glassesHandle, T5_FrameInfo frameInfo)
static IntPtr GetSendFrameCallback()
static int GetMaxDisplayDimensions([MarshalAs(UnmanagedType.LPArray, SizeConst=2)] int[] displayDimensions)
static int SetApplicationInfo(T5_StringUTF8 appName, T5_StringUTF8 appId, T5_StringUTF8 appVersion)
Provides access to player settings and functionality.
Definition: Player.cs:16
static bool IsConnected(PlayerIndex playerIndex)
Determines whether the specified player has an associated pair of glasses connected.
Definition: Player.cs:32
Definition: Log.cs:21
PlayerIndex
The Player index (e.g. Player One, Player Two, etc)
ARProjectionFrustum(float l, float r, float b, float t, float n, float f)
Definition: Display.cs:60
Render information to be used with NativePlugin.QueueStereoImages(T5_FrameInfo)
Represents a string value.