This commit is contained in:
2025-11-13 17:40:28 +08:00
parent 962ab49609
commit 10156da245
5503 changed files with 805282 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
#if PICO_OPENXR_SDK
using System;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.NativeTypes;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public enum SystemDisplayFrequency
{
Default,
RefreshRate72 = 72,
RefreshRate90 = 90,
RefreshRate120 = 120,
}
#if UNITY_EDITOR
[OpenXRFeature(UiName = "OpenXR Display Refresh Rate",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class DisplayRefreshRateFeature : OpenXRFeatureBase
{
public const string featureId = "com.pico.openxr.feature.refreshrate";
public const string extensionString = "XR_FB_display_refresh_rate";
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
public override string GetExtensionString()
{
return extensionString;
}
public override void SessionCreate(ulong xrSessionId)
{
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
if (projectConfig.displayFrequency != SystemDisplayFrequency.Default)
{
SetDisplayRefreshRate(projectConfig.displayFrequency);
}
}
public static bool SetDisplayRefreshRate(SystemDisplayFrequency DisplayFrequency)
{
PLog.e(extensionString,$"SetDisplayRefreshRate:{DisplayFrequency}");
float rate = 0;
switch (DisplayFrequency)
{
case SystemDisplayFrequency.Default:
return true;
case SystemDisplayFrequency.RefreshRate72:
rate = 72;
break;
case SystemDisplayFrequency.RefreshRate90:
rate = 90;
break;
case SystemDisplayFrequency.RefreshRate120:
rate = 120;
break;
}
return SetDisplayRefreshRate(rate);
}
public static bool GetDisplayRefreshRate(ref float displayRefreshRate)
{
if (!isExtensionEnable)
{
return false;
}
return Pxr_GetDisplayRefreshRate(ref displayRefreshRate) == (int)XrResult.Success;
}
public static bool SetDisplayRefreshRate(float displayRefreshRate)
{
if (!isExtensionEnable)
{
return false;
}
return Pxr_SetDisplayRefreshRate(displayRefreshRate) == (int)XrResult.Success;
}
[Obsolete("Please use GetDisplayFrequenciesAvailable")]
public static int GetDisplayRefreshRateCount()
{
return 0;
}
[Obsolete("Please use GetDisplayFrequenciesAvailable")]
public static bool TryGetSupportedDisplayRefreshRates(
Allocator allocator, out NativeArray<float> refreshRates)
{
refreshRates = default;
return false;
}
public static float[] GetDisplayFrequenciesAvailable()
{
if (!isExtensionEnable)
{
return null;
}
float[] configArray = { 0 };
int configCount = 0;
IntPtr configHandle = IntPtr.Zero;
bool ret = false;
ret = Pxr_GetDisplayRefreshRatesAvailable(ref configCount, ref configHandle);
if (ret)
{
configArray = new float[configCount];
Marshal.Copy(configHandle, configArray, 0, configCount);
}
return configArray;
}
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetDisplayRefreshRate(ref float displayRefreshRate);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_SetDisplayRefreshRate(float refreshRate);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern bool Pxr_GetDisplayRefreshRatesAvailable(ref int configCount, ref IntPtr configArray);
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f13a1b00c8524d6495757293c2324596
timeCreated: 1738739475

View File

@@ -0,0 +1,156 @@
#if PICO_OPENXR_SDK
using UnityEditor;
using UnityEngine.XR.OpenXR.Features;
using System.Runtime.InteropServices;
using System;
using Unity.XR.OpenXR.Features.PICOSupport;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.XR.OpenXR;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
[OpenXRFeature(UiName = "OpenXR Foveation",
BuildTargetGroups = new[] { BuildTargetGroup.Android },
OpenxrExtensionStrings = extensionList,
Company = "PICO",
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class FoveationFeature : OpenXRFeatureBase
{
public const string extensionList = "XR_FB_foveation " +
"XR_FB_foveation_configuration " +
"XR_FB_foveation_vulkan " +
"XR_META_foveation_eye_tracked " +
"XR_META_vulkan_swapchain_create_info " +
"XR_FB_swapchain_update_state ";
public const string featureId = "com.pico.openxr.feature.foveation";
private static string TAG = "FoveationFeature";
public enum FoveatedRenderingLevel
{
Off = 0,
Low = 1,
Medium = 2,
High = 3
}
public enum FoveatedRenderingMode
{
FixedFoveatedRendering = 0,
EyeTrackedFoveatedRendering = 1
}
private static UInt32 _foveatedRenderingLevel = 0;
private static UInt32 _useDynamicFoveation = 0;
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled("XR_FB_foveation");
public override string GetExtensionString()
{
return extensionList;
}
public override void SessionCreate(ulong xrSessionId)
{
if (!isExtensionEnable)
{
return ;
}
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
if (projectConfig.foveationEnable)
{
PICO_setFoveationEyeTracked(projectConfig.foveatedRenderingMode ==
FoveatedRenderingMode.EyeTrackedFoveatedRendering);
foveatedRenderingLevel = projectConfig.foveatedRenderingLevel;
}
}
public static FoveatedRenderingLevel foveatedRenderingLevel
{
get
{
if (!isExtensionEnable)
{
return FoveatedRenderingLevel.Off;
}
UInt32 level;
FBGetFoveationLevel(out level);
PLog.i(TAG,$" foveatedRenderingLevel get if level= {level}");
return (FoveatedRenderingLevel)level;
}
set
{
if (!isExtensionEnable)
{
return;
}
PLog.e(TAG,$" foveatedRenderingLevel set if value= {value}");
_foveatedRenderingLevel = (UInt32)value;
FBSetFoveationLevel(xrSession, _foveatedRenderingLevel, 0.0f, _useDynamicFoveation);
}
}
public static bool useDynamicFoveatedRendering
{
get
{
if (!isExtensionEnable)
{
return false;
}
UInt32 dynamic;
FBGetFoveationLevel(out dynamic);
return dynamic != 0;
}
set
{
if (!isExtensionEnable)
{
return ;
}
if (value)
_useDynamicFoveation = 1;
else
_useDynamicFoveation = 0;
FBSetFoveationLevel(xrSession, _foveatedRenderingLevel, 0.0f, _useDynamicFoveation);
}
}
public static bool supportsFoveationEyeTracked
{
get
{
if (!isExtensionEnable)
{
return false;
}
bool supported=false;
Pxr_GetEyeTrackingFoveationRenderingSupported(ref supported);
return supported;
}
}
#region OpenXR Plugin DLL Imports
[DllImport("UnityOpenXR", EntryPoint = "FBSetFoveationLevel")]
private static extern void FBSetFoveationLevel(UInt64 session, UInt32 level, float verticalOffset, UInt32 dynamic);
[DllImport("UnityOpenXR", EntryPoint = "FBGetFoveationLevel")]
private static extern void FBGetFoveationLevel(out UInt32 level);
[DllImport("UnityOpenXR", EntryPoint = "FBGetFoveationDynamic")]
private static extern void FBGetFoveationDynamic(out UInt32 dynamic);
#endregion
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern bool Pxr_GetEyeTrackingFoveationRenderingSupported(ref bool supported);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern void PICO_setFoveationEyeTracked(bool value);
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7137a47eb739c7a4485f1395871a6d68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using Unity.XR.CoreUtils;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.OpenXR;
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public class LayerBase : MonoBehaviour
{
public static int ID = 0;
private Transform overlayTransform;
private Camera xrRig;
private Vector3 modelTranslations;
private Quaternion modelRotations;
private Vector3 modelScales ;
private XROrigin cameraRig;
private XROrigin lastcameraRig;
public bool isXROriginChange = false;
private float offsetY = 0;
bool isUpdateOffsetY= false;
private Vector3 cameraPosOri;
private TrackingOriginModeFlags lastTrackingOriginMod = TrackingOriginModeFlags.Unknown;
public void Awake()
{
ID++;
lastcameraRig=cameraRig=FindActiveXROrigin();
overlayTransform = GetComponent<Transform>();
PXR_Plugin.System.RecenterSuccess+=()=>
{
isUpdateOffsetY = true;
};
#if UNITY_ANDROID && !UNITY_EDITOR
if (overlayTransform != null)
{
MeshRenderer render = overlayTransform.GetComponent<MeshRenderer>();
if (render != null)
{
render.enabled = false;
}
}
#endif
}
XROrigin FindActiveXROrigin()
{
XROrigin[] xrOrigins = FindObjectsOfType<XROrigin>();
foreach (XROrigin xrOrigin in xrOrigins)
{
if (xrOrigin.gameObject.activeInHierarchy)
{
return xrOrigin;
}
}
return null;
}
private void OnDestroy()
{
ID--;
}
public void UpdateCoords(bool isCreate = false)
{
if (isXROriginChange)
{
cameraRig=FindActiveXROrigin();
isUpdateOffsetY=cameraRig!= lastcameraRig;
lastcameraRig = cameraRig;
}
if (isCreate)
{
cameraPosOri=cameraRig.transform.position;
}
if (isCreate||cameraRig.CurrentTrackingOriginMode != lastTrackingOriginMod ||isUpdateOffsetY)
{
if (cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor)
{
offsetY= cameraRig.Camera.transform.position.y;
}
Debug.Log("CurrentTrackingOriginMode:"+cameraRig.CurrentTrackingOriginMode+" offsetY:"+offsetY);
isUpdateOffsetY=false;
lastTrackingOriginMod = cameraRig.CurrentTrackingOriginMode;
}
var worldInsightModel = GetTransformMatrixForPassthrough(overlayTransform.localToWorldMatrix);
modelTranslations=worldInsightModel.GetPosition();
modelRotations = worldInsightModel.rotation;
modelScales = overlayTransform.lossyScale;
}
private Matrix4x4 GetTransformMatrixForPassthrough(Matrix4x4 worldFromObj)
{
Matrix4x4 trackingSpaceFromWorld =
(cameraRig != null) ? cameraRig.CameraFloorOffsetObject.transform.worldToLocalMatrix : Matrix4x4.identity;
return trackingSpaceFromWorld * worldFromObj;
}
public void GetCurrentTransform(ref GeometryInstanceTransform geometryInstanceTransform)
{
geometryInstanceTransform.pose.position.x = modelTranslations.x;
geometryInstanceTransform.pose.position.y = modelTranslations.y-offsetY+ (cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor
? (cameraRig.transform.position.y - cameraPosOri.y)
: 0);
geometryInstanceTransform.pose.position.z = -modelTranslations.z;
geometryInstanceTransform.pose.orientation.x = -modelRotations.x;
geometryInstanceTransform.pose.orientation.y = -modelRotations.y;
geometryInstanceTransform.pose.orientation.z = modelRotations.z;
geometryInstanceTransform.pose.orientation.w = modelRotations.w;
geometryInstanceTransform.scale.x = modelScales.x;
geometryInstanceTransform.scale.y = modelScales.y;
geometryInstanceTransform.scale.z = 1;
geometryInstanceTransform.isFloor = cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7d95410458cc9bf46a74d78dcba2294f
timeCreated: 1695197751

View File

@@ -0,0 +1,54 @@
#if PICO_OPENXR_SDK
using System.Runtime.InteropServices;
using Unity.XR.PXR;
using UnityEngine.XR.OpenXR;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "OpenXR Composition Layer Secure Content",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class LayerSecureContentFeature : OpenXRFeatureBase
{
public const string featureId = "com.pico.openxr.feature.LayerSecureContent";
public const string extensionString = "XR_FB_composition_layer_secure_content";
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
public override string GetExtensionString()
{
return extensionString;
}
public override void SessionCreate(ulong xrSessionId)
{
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
if (projectConfig.useContentProtect)
{
SetSecureContentFlag(projectConfig.contentProtectFlags);
}
}
public static void SetSecureContentFlag(SecureContentFlag flag)
{
if (!isExtensionEnable)
{
return;
}
SetSecureContentFlag((int)flag);
}
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern void SetSecureContentFlag(int state);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9496d215cb181c64c9cde2f724356e20
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public abstract class OpenXRFeatureBase : OpenXRFeature
{
protected static ulong xrInstance = 0ul;
protected static ulong xrSession = 0ul;
protected override bool OnInstanceCreate(ulong instance)
{
xrInstance = instance;
xrSession = 0ul;
InstanceCreate(instance);
return true;
}
protected override void OnSessionCreate(ulong xrSessionId)
{
xrSession = xrSessionId;
base.OnSessionCreate(xrSessionId);
SessionCreate(xrSessionId);
}
public bool isExtensionEnabled(string extensionUrl)
{
string[] exts = extensionUrl.Split(' ');
if (exts.Length > 0)
{
foreach (var _ext in exts)
{
if (!string.IsNullOrEmpty(_ext) && !OpenXRRuntime.IsExtensionEnabled(_ext))
{
PLog.e("OpenXRFeatureBase", _ext + " is not enabled");
return false;
}
}
}
else
{
if (!string.IsNullOrEmpty(extensionUrl) && !OpenXRRuntime.IsExtensionEnabled(extensionUrl))
{
PLog.e("OpenXRFeatureBase", extensionUrl + " is not enabled");
return false;
}
}
return true;
}
public virtual void InstanceCreate(ulong instance) {}
public virtual void SessionCreate(ulong xrSessionId) {}
public abstract string GetExtensionString();
#if UNITY_EDITOR
protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
{
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup);
rules.Add(new ValidationRule(this)
{
message = "No PICO OpenXR Features selected.",
checkPredicate = () =>
{
if (null == settings)
return false;
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is OpenXRExtensions)
{
return feature.enabled;
}
}
return false;
},
fixIt = () =>
{
if (null == settings)
return ;
var openXRExtensions = settings.GetFeature<OpenXRExtensions>();
if (openXRExtensions != null)
{
openXRExtensions.enabled = true;
}
},
error = true
});
}
#endif
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 03de18223d234dd4914b78bf7b2ad088
timeCreated: 1738739629

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b7a3b25af74c35240b11ce66fc7614ef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,251 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.XR.PXR;
using UnityEngine;
#if AR_FOUNDATION_5||AR_FOUNDATION_6
using UnityEngine.XR.ARSubsystems;
#endif
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public enum XrBodyJointSetBD
{
XR_BODY_JOINT_SET_DEFAULT_BD = 0, //default joint set XR_BODY_JOINT_SET_BODY_STAR_WITHOUT_ARM_BD
XR_BODY_JOINT_SET_BODY_START_WITHOUT_ARM_BD = 1,
XR_BODY_JOINT_SET_BODY_FULL_STAR_BD = 2
}
#if UNITY_EDITOR
[OpenXRFeature(UiName = "PICO Body Tracking",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class BodyTrackingFeature : OpenXRFeatureBase
{
public const string featureId = "com.pico.openxr.feature.PICO_BodyTracking";
public const string extensionString = "XR_BD_body_tracking XR_PICO_body_tracking2";
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_BD_body_tracking");
public override string GetExtensionString()
{
return extensionString;
}
[Obsolete("Please use StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)")]
public static bool StartBodyTracking(XrBodyJointSetBD Mode)
{
if (!isEnable)
{
return false;
}
BodyTrackingBoneLength boneLength=new BodyTrackingBoneLength();
return StartBodyTracking((BodyJointSet)Mode, boneLength)==0;
}
/// <summary>Starts body tracking.</summary>
/// <param name="mode">Specifies the body tracking mode (default or high-accuracy).</param>
/// <param name="boneLength">Specifies lengths (unit: cm) for the bones of the avatar, which is only available for the `BTM_FULL_BODY_HIGH` mode.
/// Bones that are not set lengths for will use the default values.
/// </param>
/// <returns>
/// - `0`: success
/// - `1`: failure
/// </returns>
public static int StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)
{
if (!isEnable)
{
return 1;
}
BodyTrackingStartInfo startInfo = new BodyTrackingStartInfo();
startInfo.jointSet = JointSet;
startInfo.BoneLength = boneLength;
return Pxr_StartBodyTracking(ref startInfo);
}
/// <summary>Launches the PICO Motion Tracker app to perform calibration.
/// - For PICO Motion Tracker (Beta), the user needs to follow the instructions on the home of the PICO Motion Tracker app to complete calibration.
/// - For PICO Motion Tracker (Official), "single-glance calibration" will be performed. When a user has a glance at the PICO Motion Tracker on their lower legs, calibration is completed.
/// </summary>
/// <returns>
/// - `0`: success
/// - `1`: failure
/// </returns>
public static int StartMotionTrackerCalibApp()
{
if (!isEnable)
{
return 1;
}
return Pxr_StartBodyTrackingCalibApp();
}
public static bool IsBodyTrackingSupported()
{
if (!isEnable)
{
return false;
}
bool supported=false;
Pxr_GetBodyTrackingSupported(ref supported);
return supported;
}
/// <summary>
/// Gets the data about the poses of body joints.
/// </summary>
/// <param name="predictTime">Reserved parameter, pass `0`.</param>
/// <param name="bodyTrackerResult">Contains the data about the poses of body joints, including position, action, and more.</param>
[Obsolete("Please use GetBodyTrackingData",true)]
public static bool GetBodyTrackingPose(ref BodyTrackerResult bodyTrackerResult)
{
return false;
}
/// <summary>Stops body tracking.</summary>
/// <returns>
/// - `0`: success
/// - `1`: failure
/// </returns>
public static int StopBodyTracking()
{
return Pxr_StopBodyTracking();
}
[Obsolete("Please use StopBodyTracking")]
private void OnDestroy()
{
if (!isEnable)
{
return;
}
StopBodyTracking();
}
[Obsolete("Please use StartMotionTrackerCalibApp")]
public static void OpenFitnessBandCalibrationAPP()
{
StartMotionTrackerCalibApp();
}
/// <summary>Gets body tracking data.</summary>
/// <param name="getInfo"> Specifies the display time and the data filtering flags.
/// For the display time, for example, when it is set to 0.1 second, it means predicting the pose of the tracked node 0.1 seconds ahead.
/// </param>
/// <param name="data">Returns the array of data for all tracked nodes.</param>
/// <returns>
/// - `0`: success
/// - `1`: failure
/// </returns>
public unsafe static int GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data)
{
if (!isEnable)
{
return 1;
}
int val = -1;
{
val = Pxr_GetBodyTrackingData(ref getInfo, ref data);
for (int i = 0; i < (int)BodyTrackerRole.ROLE_NUM; i++)
{
data.roleDatas[i].localPose.PosZ = -data.roleDatas[i].localPose.PosZ;
data.roleDatas[i].localPose.RotQz = -data.roleDatas[i].localPose.RotQz;
data.roleDatas[i].localPose.RotQw = -data.roleDatas[i].localPose.RotQw;
data.roleDatas[i].velo[3] = -data.roleDatas[i].velo[3];
data.roleDatas[i].acce[3] = -data.roleDatas[i].acce[3];
data.roleDatas[i].wvelo[3] = -data.roleDatas[i].wvelo[3];
data.roleDatas[i].wacce[3] = -data.roleDatas[i].wacce[3];
}
}
return val;
}
/// <summary>Gets the state of PICO Motion Tracker and, if any, the reason for an exception.</summary>
/// <param name="isTracking">Indicates whether the PICO Motion Tracker is tracking normally:
/// - `true`: is tracking
/// - `false`: tracking lost
/// </param>
/// <param name="state">Returns the information about body tracking state.</param>
/// <returns>
/// - `0`: success
/// - `1`: failure
/// </returns>
public static int GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state)
{
int val = -1;
{
val = Pxr_GetBodyTrackingState(ref isTracking, ref state);
}
return val;
}
#if AR_FOUNDATION_5||AR_FOUNDATION_6
public bool isBodyTracking=false;
static List<XRHumanBodySubsystemDescriptor> s_HumanBodyDescriptors = new List<XRHumanBodySubsystemDescriptor>();
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
if (isBodyTracking)
{
CreateSubsystem<XRHumanBodySubsystemDescriptor, XRHumanBodySubsystem>(
s_HumanBodyDescriptors,
PXR_HumanBodySubsystem.k_SubsystemId);
}
}
protected override void OnSubsystemStart()
{
if (isBodyTracking)
{
StartSubsystem<XRHumanBodySubsystem>();
}
}
protected override void OnSubsystemStop()
{
if (isBodyTracking)
{
StopSubsystem<XRHumanBodySubsystem>();
}
}
protected override void OnSubsystemDestroy()
{
if (isBodyTracking)
{
DestroySubsystem<XRHumanBodySubsystem>();
}
}
#endif
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StartBodyTrackingCalibApp();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingSupported(ref bool supported);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StartBodyTracking(ref BodyTrackingStartInfo startInfo);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StopBodyTracking();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa772d31a64f93d49bd62d49064fee41
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "PICO Scene Capture",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = "1.0.0",
FeatureId = featureId)]
#endif
public class PICOSceneCapture: OpenXRFeature
{
public const string featureId = "com.pico.openxr.feature.scenecapture";
public const string extensionString = "XR_PICO_scene_capture XR_PICO_spatial_sensing XR_EXT_future";
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_scene_capture");
protected override void OnSessionCreate(ulong xrSession)
{
base.OnSessionCreate(xrSession);
PXR_Plugin.MixedReality.UPxr_CreateSceneCaptureSenseDataProvider();
}
protected override void OnSessionExiting(ulong xrSession)
{
PXR_MixedReality.GetSenseDataProviderState(PxrSenseDataProviderType.SceneCapture, out var providerState);
if (providerState == PxrSenseDataProviderState.Running)
{
PXR_MixedReality.StopSenseDataProvider(PxrSenseDataProviderType.SceneCapture);
}
PXR_Plugin.MixedReality.UPxr_DestroySenseDataProvider(
PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SceneCapture));
base.OnSessionExiting(xrSession);
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a0b5403262c64d5888bf5672e1e1f3bb
timeCreated: 1721806849

View File

@@ -0,0 +1,96 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
#if AR_FOUNDATION_5||AR_FOUNDATION_6
using UnityEngine.XR.ARSubsystems;
#endif
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "PICO Spatial Anchor",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = "1.0.0",
FeatureId = featureId)]
#endif
public class PICOSpatialAnchor: OpenXRFeature
{
public const string featureId = "com.pico.openxr.feature.spatialanchor";
public const string extensionString = "XR_PICO_spatial_anchor XR_PICO_spatial_sensing XR_EXT_future";
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_spatial_anchor");
protected override void OnSessionCreate(ulong xrSession)
{
base.OnSessionCreate(xrSession);
PXR_Plugin.MixedReality.UPxr_CreateSpatialAnchorSenseDataProvider();
}
protected override void OnSessionExiting(ulong xrSession)
{
PXR_MixedReality.GetSenseDataProviderState(PxrSenseDataProviderType.SpatialAnchor, out var providerState);
if (providerState == PxrSenseDataProviderState.Running)
{
PXR_MixedReality.StopSenseDataProvider(PxrSenseDataProviderType.SpatialAnchor);
}
PXR_Plugin.MixedReality.UPxr_DestroySenseDataProvider(
PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SpatialAnchor));
base.OnSessionExiting(xrSession);
}
#if AR_FOUNDATION_5||AR_FOUNDATION_6
public bool isAnchorSubsystem=false;
static List<XRAnchorSubsystemDescriptor> anchorSubsystemDescriptors = new List<XRAnchorSubsystemDescriptor>();
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
if (isAnchorSubsystem)
{
CreateSubsystem<XRAnchorSubsystemDescriptor, XRAnchorSubsystem>(
anchorSubsystemDescriptors,
PXR_AnchorSubsystem.k_SubsystemId);
}
}
protected override void OnSubsystemStart()
{
if (isAnchorSubsystem)
{
StartSubsystem<XRAnchorSubsystem>();
}
}
protected override void OnSubsystemStop()
{
if (isAnchorSubsystem)
{
StopSubsystem<XRAnchorSubsystem>();
}
}
protected override void OnSubsystemDestroy()
{
if (isAnchorSubsystem)
{
DestroySubsystem<XRAnchorSubsystem>();
}
}
#endif
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a8b7731b990240c0b289e41fb880787b
timeCreated: 1721806849

View File

@@ -0,0 +1,72 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
// using Unity.XR.CoreUtils;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "PICO Spatial Mesh",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = "1.0.0",
FeatureId = featureId)]
#endif
public class PICOSpatialMesh: OpenXRFeature
{
public const string featureId = "com.pico.openxr.feature.spatialmesh";
public const string extensionString = "XR_PICO_spatial_mesh XR_PICO_spatial_sensing XR_EXT_future";
private static List<XRMeshSubsystemDescriptor> meshSubsystemDescriptors = new List<XRMeshSubsystemDescriptor>();
public PxrMeshLod LOD;
private XRMeshSubsystem subsystem;
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_spatial_mesh");
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
PXR_Plugin.Pxr_SetMeshLOD(Convert.ToUInt16(LOD));
}
protected override void OnSessionCreate(ulong xrSession)
{
base.OnSessionCreate(xrSession);
CreateSubsystem<XRMeshSubsystemDescriptor, XRMeshSubsystem>(meshSubsystemDescriptors, "PICO Mesh");
}
protected override void OnSubsystemStop()
{
base.OnSubsystemStop();
StopSubsystem<XRMeshSubsystem>();
}
protected override void OnSubsystemDestroy()
{
base.OnSubsystemDestroy();
PXR_Plugin.MixedReality.UPxr_DisposeMesh();
DestroySubsystem<XRMeshSubsystem>();
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b1248416ce414cd0a788c5240bec5766
timeCreated: 1721806849

View File

@@ -0,0 +1,541 @@
#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Unity.XR.CoreUtils;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
#if AR_FOUNDATION_5||AR_FOUNDATION_6
using UnityEngine.XR.ARSubsystems;
#endif
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using UnityEngine.XR.OpenXR.NativeTypes;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "OpenXR Passthrough",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class PassthroughFeature : OpenXRFeatureBase
{
public const string featureId = "com.pico.openxr.feature.passthrough";
public const string extensionString = "XR_FB_passthrough";
public const int XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB = 256;
private static byte[] colorData;
private static uint Size = 0;
private static bool isInit = false;
private static bool isPause = false;
private static int _enableVideoSeeThrough=-1;
public static event Action<bool> EnableVideoSeeThroughAction;
private static bool isRefreshRecenterSpace = false;
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
[HideInInspector]
public static bool EnableVideoSeeThrough
{
get => _enableVideoSeeThrough==1;
set
{
if (value)
{
if (_enableVideoSeeThrough != 1)
{
_enableVideoSeeThrough = 1;
EnableSeeThroughManual(value);
if (EnableVideoSeeThroughAction != null)
{
EnableVideoSeeThroughAction(value);
}
}
}
else
{
if (_enableVideoSeeThrough == 1)
{
_enableVideoSeeThrough = 0;
EnableSeeThroughManual(value);
if (EnableVideoSeeThroughAction != null)
{
EnableVideoSeeThroughAction(value);
}
}
}
}
}
protected override void OnSessionBegin(ulong xrSessionId)
{
if (!isRefreshRecenterSpace)
{
OpenXRSettings.RefreshRecenterSpace();
isRefreshRecenterSpace = true;
}
}
public override string GetExtensionString()
{
return extensionString;
}
public static void PassthroughStart()
{
passthroughStart();
isPause = false;
}
public static void PassthroughPause()
{
passthroughPause();
isPause = true;
}
//This interface has been changed to a private interface.
//Please use the EnableVideoSeeThrough .
private static bool EnableSeeThroughManual(bool value)
{
if (!isExtensionEnable)
{
return false;
}
if (!isInit)
{
isInit = initializePassthrough();
}
if (value)
{
createFullScreenLayer();
if (!isPause)
{
passthroughStart();
}
}
else
{
passthroughPause();
}
return true;
}
public static void Destroy()
{
if (!isExtensionEnable)
{
return;
}
Passthrough_Destroy();
}
private void OnDestroy()
{
Destroy();
}
private static void AllocateColorMapData(uint size)
{
if (colorData != null && size != colorData.Length)
{
Clear();
}
if (colorData == null)
{
colorData = new byte[size];
}
}
private static void Clear()
{
if (colorData != null)
{
colorData = null;
}
}
private static void WriteVector3ToColorMap(int colorIndex, ref Vector3 color)
{
for (int c = 0; c < 3; c++)
{
byte[] bytes = BitConverter.GetBytes(color[c]);
Buffer.BlockCopy(bytes, 0, colorData, colorIndex * 12 + c * 4, 4);
}
}
private static void WriteFloatToColorMap(int index, float value)
{
byte[] bytes = BitConverter.GetBytes(value);
Buffer.BlockCopy(bytes, 0, colorData, index * sizeof(float), sizeof(float));
}
private static void WriteColorToColorMap(int colorIndex, ref Color color)
{
for (int c = 0; c < 4; c++)
{
byte[] bytes = BitConverter.GetBytes(color[c]);
Buffer.BlockCopy(bytes, 0, colorData, colorIndex * 16 + c * 4, 4);
}
}
public static unsafe void SetBrightnessContrastSaturation(ref PassthroughStyle style, float brightness = 0.0f,
float contrast = 0.0f, float saturation = 0.0f)
{
style.enableColorMap = true;
style.TextureColorMapType = PassthroughColorMapType.BrightnessContrastSaturation;
Size = 3 * sizeof(float);
AllocateColorMapData(Size);
WriteFloatToColorMap(0, brightness);
WriteFloatToColorMap(1, contrast);
WriteFloatToColorMap(2, saturation);
fixed (byte* p = colorData)
{
style.TextureColorMapData = (IntPtr)p;
}
style.TextureColorMapDataSize = Size;
StringBuilder str = new StringBuilder();
for (int i = 0; i < Size; i++)
{
str.Append(colorData[i]);
}
Debug.Log("SetPassthroughStyle SetBrightnessContrastSaturation colorData" + str);
}
public static unsafe void SetColorMapbyMonoToMono(ref PassthroughStyle style, int[] values)
{
if (values.Length != XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB)
throw new ArgumentException("Must provide exactly 256 values");
style.enableColorMap = true;
style.TextureColorMapType = PassthroughColorMapType.MonoToMono;
Size = XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB * 4;
AllocateColorMapData(Size);
Buffer.BlockCopy(values, 0, colorData, 0, (int)Size);
fixed (byte* p = colorData)
{
style.TextureColorMapData = (IntPtr)p;
}
style.TextureColorMapDataSize = Size;
}
public static unsafe void SetColorMapbyMonoToRgba(ref PassthroughStyle style, Color[] values)
{
if (values.Length != XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB)
throw new ArgumentException("Must provide exactly 256 colors");
style.TextureColorMapType = PassthroughColorMapType.MonoToRgba;
style.enableColorMap = true;
Size = XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB * 4 * 4;
AllocateColorMapData(Size);
for (int i = 0; i < XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; i++)
{
WriteColorToColorMap(i, ref values[i]);
}
fixed (byte* p = colorData)
{
style.TextureColorMapData = (IntPtr)p;
}
style.TextureColorMapDataSize = Size;
}
public static _PassthroughStyle ToPassthroughStyle(PassthroughStyle c)
{
_PassthroughStyle mPassthroughStyle = new _PassthroughStyle();
mPassthroughStyle.enableEdgeColor = (uint)(c.enableEdgeColor ? 1 : 0);
mPassthroughStyle.enableColorMap = (uint)(c.enableColorMap ? 1 : 0);
mPassthroughStyle.TextureOpacityFactor = c.TextureOpacityFactor;
mPassthroughStyle.TextureColorMapType = c.TextureColorMapType;
mPassthroughStyle.TextureColorMapDataSize = c.TextureColorMapDataSize;
mPassthroughStyle.TextureColorMapData = c.TextureColorMapData;
mPassthroughStyle.EdgeColor = new Colorf()
{ r = c.EdgeColor.r, g = c.EdgeColor.g, b = c.EdgeColor.b, a = c.EdgeColor.a };
return mPassthroughStyle;
}
public static void SetPassthroughStyle(PassthroughStyle style)
{
setPassthroughStyle(ToPassthroughStyle(style));
}
public static bool IsPassthroughSupported()
{
return isPassthroughSupported();
}
public static unsafe bool CreateTriangleMesh(int id, Vector3[] vertices, int[] triangles,
GeometryInstanceTransform transform)
{
if (vertices == null || triangles == null || vertices.Length == 0 || triangles.Length == 0)
{
return false;
}
if (!isInit)
{
isInit = initializePassthrough();
}
int vertexCount = vertices.Length;
int triangleCount = triangles.Length;
Size = (uint)vertexCount * 3 * 4;
AllocateColorMapData(Size);
for (int i = 0; i < vertexCount; i++)
{
WriteVector3ToColorMap(i, ref vertices[i]);
}
IntPtr vertexDataPtr = IntPtr.Zero;
fixed (byte* p = colorData)
{
vertexDataPtr = (IntPtr)p;
}
StringBuilder str = new StringBuilder();
for (int i = 0; i < 3 * 4; i++)
{
str.Append(colorData[i]);
}
Debug.Log("CreateTriangleMesh vertexDataPtr colorData" + str);
str.Clear();
Size = (uint)triangleCount * 4;
AllocateColorMapData(Size);
Buffer.BlockCopy(triangles, 0, colorData, 0, (int)Size);
IntPtr triangleDataPtr = IntPtr.Zero;
fixed (byte* p = colorData)
{
triangleDataPtr = (IntPtr)p;
}
for (int i = 0; i < colorData.Length; i++)
{
str.Append(colorData[i]);
}
// Debug.Log("CreateTriangleMesh triangleDataPtr colorData" + str);
//
// Debug.Log("CreateTriangleMesh vertexDataPtr=" + vertexDataPtr + " vertexCount=" + vertexCount);
// Debug.Log("CreateTriangleMesh triangleDataPtr=" + triangleDataPtr + " triangleCount=" + triangleCount);
XrResult result =
createTriangleMesh(id, vertexDataPtr, vertexCount, triangleDataPtr, triangleCount, transform);
Clear();
if (result == XrResult.Success)
{
return true;
}
return false;
}
public static void UpdateMeshTransform(int id, GeometryInstanceTransform transform)
{
updatePassthroughMeshTransform(id, transform);
}
#if UNITY_EDITOR
/// <summary>
/// Validation Rules for ARCameraFeature.
/// </summary>
protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
{
var AdditionalRules = new ValidationRule[]
{
new ValidationRule(this)
{
message = "Passthrough requires Camera clear flags set to solid color with alpha value zero.",
checkPredicate = () =>
{
var xrOrigin = FindObjectsOfType<XROrigin>();
if (xrOrigin != null && xrOrigin.Length > 0)
{
if (!xrOrigin[0].enabled) return true;
}
else
{
return true;
}
var camera = xrOrigin[0].Camera;
if (camera == null) return true;
return camera.clearFlags == CameraClearFlags.SolidColor && Mathf.Approximately(camera.backgroundColor.a, 0);
},
fixItAutomatic = true,
fixItMessage = "Set your XR Origin camera's Clear Flags to solid color with alpha value zero.",
fixIt = () =>
{
var xrOrigin = FindObjectsOfType<XROrigin>();
if (xrOrigin!=null&&xrOrigin.Length>0)
{
if (xrOrigin[0].enabled)
{
var camera = xrOrigin[0].Camera;
if (camera != null )
{
camera.clearFlags = CameraClearFlags.SolidColor;
Color clearColor = camera.backgroundColor;
clearColor.a = 0;
camera.backgroundColor = clearColor;
}
}
}
},
error = false
}
};
rules.AddRange(AdditionalRules);
}
#endif
#if AR_FOUNDATION_5||AR_FOUNDATION_6
public bool isCameraSubsystem=false;
static List<XRCameraSubsystemDescriptor> s_CameraDescriptors = new List<XRCameraSubsystemDescriptor>();
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
if (isCameraSubsystem)
{
CreateSubsystem<XRCameraSubsystemDescriptor, XRCameraSubsystem>(
s_CameraDescriptors,
PXR_CameraSubsystem.k_SubsystemId);
}
}
protected override void OnSubsystemStart()
{
if (isCameraSubsystem)
{
StartSubsystem<XRCameraSubsystem>();
}
}
protected override void OnSubsystemStop()
{
if (isCameraSubsystem)
{
StopSubsystem<XRCameraSubsystem>();
}
}
protected override void OnSubsystemDestroy()
{
if (isCameraSubsystem)
{
DestroySubsystem<XRCameraSubsystem>();
}
}
#endif
protected override void OnSessionStateChange(int oldState, int newState)
{
base.OnSessionStateChange(oldState, newState);
if (newState == 1)
{
#if AR_FOUNDATION_5||AR_FOUNDATION_6
if (isCameraSubsystem)
{
StopSubsystem<XRCameraSubsystem>();
}else{
if (_enableVideoSeeThrough!=-1)
{
EnableSeeThroughManual(false);
}
}
#else
if (_enableVideoSeeThrough!=-1)
{
EnableSeeThroughManual(false);
}
#endif
}
else if (newState == 5)
{
#if AR_FOUNDATION_5||AR_FOUNDATION_6
if (isCameraSubsystem)
{
StartSubsystem<XRCameraSubsystem>();
}else{
if (_enableVideoSeeThrough!=-1)
{
EnableSeeThroughManual(EnableVideoSeeThrough);
}
}
#else
if (_enableVideoSeeThrough!=-1)
{
EnableSeeThroughManual(EnableVideoSeeThrough);
}
#endif
}
}
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_InitializePassthrough", CallingConvention = CallingConvention.Cdecl)]
private static extern bool initializePassthrough();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_CreateFullScreenLayer", CallingConvention = CallingConvention.Cdecl)]
private static extern bool createFullScreenLayer();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_PassthroughStart", CallingConvention = CallingConvention.Cdecl)]
private static extern void passthroughStart();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_PassthroughPause", CallingConvention = CallingConvention.Cdecl)]
private static extern void passthroughPause();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_SetPassthroughStyle", CallingConvention = CallingConvention.Cdecl)]
private static extern void setPassthroughStyle(_PassthroughStyle style);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_IsPassthroughSupported", CallingConvention = CallingConvention.Cdecl)]
private static extern bool isPassthroughSupported();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_Passthrough_Destroy", CallingConvention = CallingConvention.Cdecl)]
private static extern void Passthrough_Destroy();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_CreateTriangleMesh", CallingConvention = CallingConvention.Cdecl)]
private static extern XrResult createTriangleMesh(int id, IntPtr vertices, int vertexCount, IntPtr triangles,
int triangleCount, GeometryInstanceTransform transform);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_UpdatePassthroughMeshTransform",
CallingConvention = CallingConvention.Cdecl)]
private static extern void updatePassthroughMeshTransform(int id, GeometryInstanceTransform transform);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25fd7afe1de6d1545bfb5621a8e3aad5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
#if PICO_OPENXR_SDK
using System;
using Unity.XR.PXR;
using UnityEngine;
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public class PassthroughLayerFeature : LayerBase
{
private int id = 0;
private Vector3[] vertices;
private int[] triangles;
private Mesh mesh;
private bool isPassthroughSupported = false;
private bool isCreateTriangleMesh = false;
private void Awake()
{
base.Awake();
id = ID;
}
private void Start()
{
MeshFilter meshFilter = this.gameObject.GetComponent<MeshFilter>();
if (meshFilter == null)
{
Debug.LogError("Passthrough GameObject does not have a mesh component.");
return;
}
mesh = meshFilter.sharedMesh;
vertices = mesh.vertices;
triangles = mesh.triangles;
isPassthroughSupported = PassthroughFeature.IsPassthroughSupported();
}
private void Update()
{
if (isPassthroughSupported && !isCreateTriangleMesh)
{
GeometryInstanceTransform Transform = new GeometryInstanceTransform();
UpdateCoords(true);
GetCurrentTransform(ref Transform);
isCreateTriangleMesh = PassthroughFeature.CreateTriangleMesh(id, vertices, triangles, Transform);
}
}
private void OnEnable()
{
Camera.onPostRender += OnPostRenderCallBack;
}
private void OnDisable()
{
Camera.onPostRender -= OnPostRenderCallBack;
}
private void OnPostRenderCallBack(Camera cam)
{
GeometryInstanceTransform Transform = new GeometryInstanceTransform();
UpdateCoords();
GetCurrentTransform(ref Transform);
PassthroughFeature.UpdateMeshTransform(id, Transform);
}
void OnApplicationPause(bool pause)
{
if (isCreateTriangleMesh)
{
if (pause)
{
PassthroughFeature.PassthroughPause();
}
else
{
PassthroughFeature.PassthroughStart();
}
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d56a853c0545c25418b6e768fdff0d71
timeCreated: 1694522562