diff --git a/Packages/webxr/CHANGELOG.md b/Packages/webxr/CHANGELOG.md index a99c15cc..4da70703 100644 --- a/Packages/webxr/CHANGELOG.md +++ b/Packages/webxr/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Hands tracking update. - Flickering on touch input in immersive WebXR sessions by queueing synthesized touch events and dispatching them during the XR animation frame. +### Added +- WebXR Anchors: Session anchor support for immersive AR sessions, including creating anchors from viewer hit-test results or Unity poses and receiving per-frame anchor pose updates. +- WebXR Anchors: To use anchors, enable the `anchors` optional feature in WebXR AR settings and see samples for usage. + ## [0.22.1] - 2024-11-09 ### Added - Support for WebAssembly Table, to support newer Unity versions features. diff --git a/Packages/webxr/Runtime/Plugins/WebGL/webxr.jslib b/Packages/webxr/Runtime/Plugins/WebGL/webxr.jslib index 4a007e19..d7404f41 100644 --- a/Packages/webxr/Runtime/Plugins/WebGL/webxr.jslib +++ b/Packages/webxr/Runtime/Plugins/WebGL/webxr.jslib @@ -29,6 +29,35 @@ var LibraryWebXR = { Module.HandsArrayOffset = byteOffset / 4; }, + InitAnchorsArray: function(byteOffset) { + Module.AnchorsArrayOffset = byteOffset / 4; + }, + + SetWebXRAnchorEvents: function(onAnchorCreatedPtr, onAnchorDeletedPtr) { + Module.WebXR.onAnchorCreatedPtr = onAnchorCreatedPtr; + Module.WebXR.onAnchorDeletedPtr = onAnchorDeletedPtr; + }, + + CreateAnchorFromViewerHitTest: function() { + Module.WebXR.createAnchorFromViewerHitTest(); + }, + + CreateAnchorFromWaitingForViewerHitTest: function() { + Module.WebXR.createAnchorFromWaitingForViewerHitTest(); + }, + + CreateAnchorFromPose: function(px, py, pz, qx, qy, qz, qw) { + Module.WebXR.createAnchorFromPose(px, py, pz, qx, qy, qz, qw); + }, + + DeleteAnchor: function(anchorId) { + Module.WebXR.deleteAnchor(anchorId); + }, + + DeleteAllAnchors: function() { + Module.WebXR.deleteAllAnchors(); + }, + InitViewerHitTestPoseArray: function(byteOffset) { Module.ViewerHitTestPoseArrayOffset = byteOffset / 4; }, diff --git a/Packages/webxr/Runtime/Plugins/WebGL/webxr.jspre b/Packages/webxr/Runtime/Plugins/WebGL/webxr.jspre index 61b3da67..ba1d8e81 100644 --- a/Packages/webxr/Runtime/Plugins/WebGL/webxr.jspre +++ b/Packages/webxr/Runtime/Plugins/WebGL/webxr.jspre @@ -105,6 +105,11 @@ void main() this.touchIDs = []; this.touches = []; this.eventsNamesToIDs = {}; + this.maxAnchors = 32; + this.anchors = []; + for (var anchorIndex = 0; anchorIndex < this.maxAnchors; anchorIndex++) { + this.anchors.push(new XRAnchorData()); + } this.CreateTouch = function (pageElement, xPercentage, yPercentage) { var touchID = 0; while (this.touchIDs.includes(touchID)) @@ -264,6 +269,27 @@ void main() this.rotationIndices[3] = index; } } + + function XRAnchorData() { + this.frameIndex = 0; + this.idIndex = 0; + this.trackedIndex = 0; + this.positionIndices = [0, 0, 0]; + this.rotationIndices = [0, 0, 0, 0]; + + this.setIndices = function(index) { + this.frameIndex = index++; + this.idIndex = index++; + this.trackedIndex = index++; + this.positionIndices[0] = index++; + this.positionIndices[1] = index++; + this.positionIndices[2] = index++; + this.rotationIndices[0] = index++; + this.rotationIndices[1] = index++; + this.rotationIndices[2] = index++; + this.rotationIndices[3] = index; + } + } function lerp(start, end, percentage) { @@ -346,6 +372,11 @@ void main() this.onSessionVisibilityEvent = null; this.BrowserObject = null; this.JSEventsObject = null; + this.webXRAnchors = {}; + this.webXRAnchorIds = new Map(); + this.nextAnchorId = 1; + this.pendingAnchorRequests = []; + this.lastViewerHitTestResult = null; this.touchEventQueue = []; this.init(); } @@ -405,7 +436,6 @@ void main() }); } - XRManager.prototype.attachEventListeners = function () { var onToggleAr = this.toggleAr.bind(this); var onToggleVr = this.toggleVr.bind(this); @@ -418,6 +448,11 @@ void main() Module.WebXR.toggleVR = onToggleVr; Module.WebXR.toggleHitTest = onToggleHitTest; Module.WebXR.callHapticPulse = onCallHapticPulse; + Module.WebXR.createAnchorFromViewerHitTest = this.createAnchorFromViewerHitTest.bind(this); + Module.WebXR.createAnchorFromWaitingForViewerHitTest = this.createAnchorFromWaitingForViewerHitTest.bind(this); + Module.WebXR.createAnchorFromPose = this.createAnchorFromPose.bind(this); + Module.WebXR.deleteAnchor = this.deleteAnchor.bind(this); + Module.WebXR.deleteAllAnchors = this.deleteAllAnchors.bind(this); } XRManager.prototype.onRequestARSession = function () { @@ -505,6 +540,10 @@ void main() this.viewerHitTestSource.cancel(); this.viewerHitTestSource = null; } + + this.deleteAllAnchors(); + this.pendingAnchorRequests = []; + this.lastViewerHitTestResult = null; this.removeRemainingTouches(); this.touchEventQueue.length = 0; @@ -1044,6 +1083,13 @@ void main() this.xrData.handLeft.setIndices(Module.HandsArrayOffset); this.xrData.handRight.setIndices(Module.HandsArrayOffset + 212); this.xrData.viewerHitTestPose.setIndices(Module.ViewerHitTestPoseArrayOffset); + if (Module.AnchorsArrayOffset !== undefined) { + for (var anchorIndex = 0; anchorIndex < this.xrData.maxAnchors; anchorIndex++) { + var anchorData = this.xrData.anchors[anchorIndex]; + anchorData.setIndices(Module.AnchorsArrayOffset + anchorIndex * 10); + this.clearAnchorSlot(anchorIndex); + } + } this.xrData.controllerA.updatedProfiles = 0; this.xrData.controllerB.updatedProfiles = 0; this.xrData.controllerA.profiles = []; @@ -1071,8 +1117,246 @@ void main() session.requestAnimationFrame(tempRaf); }); } + + XRManager.prototype.callAnchorCreated = function(anchorId) { + if (Module.WebXR.onAnchorCreatedPtr) { + Module.dynCall_vi(Module.WebXR.onAnchorCreatedPtr, anchorId); + } + } + + XRManager.prototype.callAnchorDeleted = function(anchorId) { + if (Module.WebXR.onAnchorDeletedPtr) { + Module.dynCall_vi(Module.WebXR.onAnchorDeletedPtr, anchorId); + } + } + + XRManager.prototype.clearAnchorSlot = function(slot) { + if (Module.AnchorsArrayOffset === undefined || !this.xrData.anchors[slot]) { + return; + } + + var anchorData = this.xrData.anchors[slot]; + Module.HEAPF32[anchorData.frameIndex] = this.xrData.frameNumber; + Module.HEAPF32[anchorData.idIndex] = -1; + Module.HEAPF32[anchorData.trackedIndex] = 0; + } + + XRManager.prototype.findFreeAnchorSlot = function() { + for (var i = 0; i < this.xrData.maxAnchors; i++) { + var used = false; + for (var anchorId in this.webXRAnchors) { + if (this.webXRAnchors[anchorId].slot == i) { + used = true; + break; + } + } + if (!used) { + return i; + } + } + return -1; + } + + XRManager.prototype.registerAnchor = function(anchor) { + if (!anchor || !anchor.anchorSpace) { + console.warn('WebXR anchor has no anchorSpace.'); + return; + } + + var slot = this.findFreeAnchorSlot(); + if (slot < 0) { + console.warn('No free WebXR anchor slot available.'); + if (anchor.delete) { + anchor.delete(); + } + return; + } + + var anchorId = this.nextAnchorId++; + var entry = { + id: anchorId, + slot: slot, + anchor: anchor + }; + + this.webXRAnchors[anchorId] = entry; + this.webXRAnchorIds.set(anchor, anchorId); + this.clearAnchorSlot(slot); + this.callAnchorCreated(anchorId); + } + + XRManager.prototype.createAnchorFromViewerHitTest = function() { + this.pendingAnchorRequests.push({ type: 'viewer-hit-test' }); + } + + XRManager.prototype.createAnchorFromWaitingForViewerHitTest = function() { + this.pendingAnchorRequests.push({ type: 'wait-viewer-hit-test' }); + } + + XRManager.prototype.createAnchorFromPose = function(px, py, pz, qx, qy, qz, qw) { + this.pendingAnchorRequests.push({ + type: 'pose', + position: { x: px, y: py, z: pz }, + rotation: { x: qx, y: qy, z: qz, w: qw } + }); + } + + XRManager.prototype.deleteAnchor = function(anchorId) { + var entry = this.webXRAnchors[anchorId]; + if (!entry) { + return; + } + + if (entry.anchor && entry.anchor.delete) { + try { + entry.anchor.delete(); + } catch (error) { + console.warn('Could not delete WebXR anchor:', error); + } + } + + this.webXRAnchorIds.delete(entry.anchor); + delete this.webXRAnchors[anchorId]; + this.clearAnchorSlot(entry.slot); + this.callAnchorDeleted(anchorId); + } + + XRManager.prototype.deleteAllAnchors = function() { + var ids = []; + for (var anchorId in this.webXRAnchors) { + ids.push(parseInt(anchorId)); + } + for (var i = 0; i < ids.length; i++) { + this.deleteAnchor(ids[i]); + } + } + + XRManager.prototype.processAnchorRequests = function(frame, session) { + if (!session || !session.isAR || this.pendingAnchorRequests.length == 0) { + return; + } + + if (!frame.trackedAnchors) { + console.warn('WebXR anchors are not available in this session. Add anchors to AR optional or required features.'); + this.pendingAnchorRequests = []; + return; + } + + var requests = this.pendingAnchorRequests; + this.pendingAnchorRequests = []; + + for (var i = 0; i < requests.length; i++) { + var request = requests[i]; + var thisXRMananger = this; + + if (request.type == 'viewer-hit-test') { + if (!this.lastViewerHitTestResult) { + console.warn('Cannot create WebXR anchor: no viewer hit-test result available.'); + continue; + } + + if (!this.lastViewerHitTestResult.createAnchor) { + console.warn('Cannot create WebXR anchor: XRHitTestResult.createAnchor is unavailable.'); + continue; + } + + this.lastViewerHitTestResult.createAnchor().then(function(anchor) { + thisXRMananger.registerAnchor(anchor); + }).catch(function(error) { + console.warn('Could not create WebXR anchor from hit-test result:', error); + }); + } else if (request.type == 'wait-viewer-hit-test') { + if (!this.lastViewerHitTestResult) { + console.info('Cannot create WebXR anchor now will try again.'); + this.pendingAnchorRequests.push(request); + continue; + } + + if (!this.lastViewerHitTestResult.createAnchor) { + console.warn('Cannot create WebXR anchor: XRHitTestResult.createAnchor is unavailable.'); + continue; + } + + this.lastViewerHitTestResult.createAnchor().then(function(anchor) { + thisXRMananger.registerAnchor(anchor); + }).catch(function(error) { + console.warn('Could not create WebXR anchor from hit-test result:', error); + }); + } else if (request.type == 'pose') { + if (!frame.createAnchor || !window.XRRigidTransform) { + console.warn('Cannot create WebXR anchor: XRFrame.createAnchor or XRRigidTransform is unavailable.'); + continue; + } + + var transform = new XRRigidTransform( + { + x: request.position.x, + y: request.position.y, + z: -request.position.z + }, + { + x: -request.rotation.x, + y: -request.rotation.y, + z: request.rotation.z, + w: request.rotation.w + } + ); + + frame.createAnchor(transform, session.refSpace).then(function(anchor) { + thisXRMananger.registerAnchor(anchor); + }).catch(function(error) { + console.warn('Could not create WebXR anchor from pose:', error); + }); + } + } + } + + XRManager.prototype.updateAnchors = function(frame, session) { + if (!session || !session.isAR || !frame.trackedAnchors || Module.AnchorsArrayOffset === undefined) { + return; + } + + for (var anchorId in this.webXRAnchors) { + var inactiveEntry = this.webXRAnchors[anchorId]; + var inactiveData = this.xrData.anchors[inactiveEntry.slot]; + Module.HEAPF32[inactiveData.frameIndex] = this.xrData.frameNumber; + Module.HEAPF32[inactiveData.idIndex] = inactiveEntry.id; + Module.HEAPF32[inactiveData.trackedIndex] = 0; + } + + var baseSpace = session.localRefSpace || session.refSpace; + for (var anchor of frame.trackedAnchors) { + var id = this.webXRAnchorIds.get(anchor); + if (!id) { + continue; + } + + var entry = this.webXRAnchors[id]; + if (!entry) { + continue; + } + + var pose = frame.getPose(anchor.anchorSpace, baseSpace); + if (!pose) { + continue; + } + + var data = this.xrData.anchors[entry.slot]; + Module.HEAPF32[data.frameIndex] = this.xrData.frameNumber; + Module.HEAPF32[data.idIndex] = entry.id; + Module.HEAPF32[data.trackedIndex] = 1; + Module.HEAPF32[data.positionIndices[0]] = pose.transform.position.x; + Module.HEAPF32[data.positionIndices[1]] = pose.transform.position.y; + Module.HEAPF32[data.positionIndices[2]] = -pose.transform.position.z; + Module.HEAPF32[data.rotationIndices[0]] = -pose.transform.orientation.x; + Module.HEAPF32[data.rotationIndices[1]] = -pose.transform.orientation.y; + Module.HEAPF32[data.rotationIndices[2]] = pose.transform.orientation.z; + Module.HEAPF32[data.rotationIndices[3]] = pose.transform.orientation.w; + } + } XRManager.prototype.animate = function (frame) { + this.lastViewerHitTestResult = null; var session = frame.session; if (!session) { return this.didNotifyUnity; @@ -1143,6 +1427,7 @@ void main() Module.HEAPF32[xrData.viewerHitTestPose.frameIndex] = xrData.frameNumber; // XRHitPoseData.frame var viewerHitTestResults = frame.getHitTestResults(this.viewerHitTestSource); if (viewerHitTestResults.length > 0) { + this.lastViewerHitTestResult = viewerHitTestResults[0]; var hitTestPose = viewerHitTestResults[0].getPose(session.localRefSpace); Module.HEAPF32[xrData.viewerHitTestPose.availableIndex] = 1; // XRHitPoseData.available Module.HEAPF32[xrData.viewerHitTestPose.positionIndices[0]] = hitTestPose.transform.position.x; // XRHitPoseData.position[0] @@ -1157,6 +1442,9 @@ void main() Module.HEAPF32[xrData.viewerHitTestPose.availableIndex] = 0; // XRHitPoseData.available } } + + this.processAnchorRequests(frame, session); + this.updateAnchors(frame, session); if (xrData.controllerA.updatedProfiles == 1 || xrData.controllerB.updatedProfiles == 1) { diff --git a/Packages/webxr/Runtime/Scripts/WebXRControllerData.cs b/Packages/webxr/Runtime/Scripts/WebXRControllerData.cs index d3b87bb4..d7e46541 100644 --- a/Packages/webxr/Runtime/Scripts/WebXRControllerData.cs +++ b/Packages/webxr/Runtime/Scripts/WebXRControllerData.cs @@ -97,6 +97,16 @@ public class WebXRHitPoseData public Quaternion rotation; } + [System.Serializable] + public class WebXRAnchorData + { + public int frame; + public int id; + public bool tracked; + public Vector3 position; + public Quaternion rotation; + } + public enum WebXRControllerHand { NONE = 0, diff --git a/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs b/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs new file mode 100644 index 00000000..f2f1e60f --- /dev/null +++ b/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace WebXR +{ + public partial class WebXRManager + { + public static event WebXRSubsystem.AnchorCreated OnAnchorCreated + { + add => WebXRSubsystem.OnAnchorCreated += value; + remove => WebXRSubsystem.OnAnchorCreated -= value; + } + + public static event WebXRSubsystem.AnchorDeleted OnAnchorDeleted + { + add => WebXRSubsystem.OnAnchorDeleted += value; + remove => WebXRSubsystem.OnAnchorDeleted -= value; + } + + public static event WebXRSubsystem.AnchorUpdate OnAnchorUpdate + { + add => WebXRSubsystem.OnAnchorUpdate += value; + remove => WebXRSubsystem.OnAnchorUpdate -= value; + } + + public void CreateAnchorFromViewerHitTest() + { + subsystem?.CreateAnchorFromViewerHitTest(); + } + + public void CreateAnchorFromWaitingForViewerHitTest() + { + subsystem?.CreateAnchorFromWaitingForViewerHitTest(); + } + + public void CreateAnchorFromPose(Vector3 position, Quaternion rotation) + { + subsystem?.CreateAnchorFromPose(position, rotation); + } + + public void DeleteAnchor(int anchorId) + { + subsystem?.DeleteAnchor(anchorId); + } + + public void DeleteAllAnchors() + { + subsystem?.DeleteAllAnchors(); + } + } +} \ No newline at end of file diff --git a/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs.meta b/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs.meta new file mode 100644 index 00000000..a3880efb --- /dev/null +++ b/Packages/webxr/Runtime/Scripts/WebXRManager.Anchors.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2229e54e1166e445d955314701f4f554 \ No newline at end of file diff --git a/Packages/webxr/Runtime/Scripts/WebXRManager.cs b/Packages/webxr/Runtime/Scripts/WebXRManager.cs index a7d19a57..684b16f5 100644 --- a/Packages/webxr/Runtime/Scripts/WebXRManager.cs +++ b/Packages/webxr/Runtime/Scripts/WebXRManager.cs @@ -12,9 +12,9 @@ public enum WebXRVisibilityState [DefaultExecutionOrder(-2020)] #if UNITY_XR_MANAGEMENT_4_3_1_OR_NEWER - public class WebXRManager : SubsystemLifecycleManager + public partial class WebXRManager : SubsystemLifecycleManager #else - public class WebXRManager : SubsystemLifecycleManager + public partial class WebXRManager : SubsystemLifecycleManager #endif { private static readonly Rect defaultRect = new Rect(0, 0, 1, 1); diff --git a/Packages/webxr/Runtime/XRPlugin/WebXRSettings.cs b/Packages/webxr/Runtime/XRPlugin/WebXRSettings.cs index 3108dc68..83e57dbb 100644 --- a/Packages/webxr/Runtime/XRPlugin/WebXRSettings.cs +++ b/Packages/webxr/Runtime/XRPlugin/WebXRSettings.cs @@ -21,7 +21,8 @@ public enum ReferenceSpaceTypes public enum ExtraFeatureTypes { hit_test = 1, - hand_tracking = 2 + hand_tracking = 2, + anchors = 4 } [Header("VR Settings")] diff --git a/Packages/webxr/Runtime/XRPlugin/WebXRSubsystem.cs b/Packages/webxr/Runtime/XRPlugin/WebXRSubsystem.cs index fefc6189..4469e4f5 100644 --- a/Packages/webxr/Runtime/XRPlugin/WebXRSubsystem.cs +++ b/Packages/webxr/Runtime/XRPlugin/WebXRSubsystem.cs @@ -213,6 +213,10 @@ internal void OnUpdate() OnViewerHitTestUpdate?.Invoke(viewerHitTestPose); } } + if (OnAnchorUpdate != null && this.xrState == WebXRState.AR) + { + UpdateAnchors(); + } } private void UpdateXRCameras() @@ -228,6 +232,69 @@ private void UpdateXRCameras() } } + private static bool AnchorsFeatureEnabled() + { + WebXRSettings settings = WebXRSettings.GetSettings(); + return settings != null + && settings.AROptionalFeatures.HasFlag(WebXRSettings.ExtraFeatureTypes.anchors); + } + + private void UpdateAnchors() + { + if (!AnchorsFeatureEnabled()) + { + return; + } + for (int i = 0; i < MaxWebXRAnchors; i++) + { + if (GetAnchorFromAnchorsArray(i, anchors[i])) + { + OnAnchorUpdate?.Invoke(anchors[i]); + } + } + } + + private bool GetAnchorFromAnchorsArray(int anchorIndex, WebXRAnchorData anchorData) + { + int arrayAnchorDataStartPosition = anchorIndex * WebXRAnchorArrayStride; + + int frameNumber = (int)anchorsDataArray[arrayAnchorDataStartPosition++]; + if (anchorData.frame == frameNumber) + { + return false; + } + + int anchorId = (int)anchorsDataArray[arrayAnchorDataStartPosition++]; + bool tracked = anchorsDataArray[arrayAnchorDataStartPosition++] != 0; + + anchorData.frame = frameNumber; + anchorData.id = anchorId; + anchorData.tracked = tracked; + + if (anchorId < 0) + { + return false; + } + + if (!tracked) + { + return true; + } + + anchorData.position = new Vector3( + anchorsDataArray[arrayAnchorDataStartPosition++], + anchorsDataArray[arrayAnchorDataStartPosition++], + anchorsDataArray[arrayAnchorDataStartPosition++]); + + anchorData.rotation = new Quaternion( + anchorsDataArray[arrayAnchorDataStartPosition++], + anchorsDataArray[arrayAnchorDataStartPosition++], + anchorsDataArray[arrayAnchorDataStartPosition++], + anchorsDataArray[arrayAnchorDataStartPosition++]); + + return true; + } + private float CheckViewsDistance() { if (viewsCount == 1) @@ -248,11 +315,17 @@ private float CheckViewsDistance() private void InternalStart() { + for (int i = 0; i < MaxWebXRAnchors; i++) + { + anchors[i] = new WebXRAnchorData { frame = -1, id = -1 }; + } #if UNITY_WEBGL Native.SetWebXREvents(OnStartAR, OnStartVR, UpdateVisibilityState, OnEndXR, OnXRCapabilities, OnInputProfiles); Native.InitControllersArray(controllersArray); Native.InitHandsArray(handsArray); Native.InitViewerHitTestPoseArray(viewerHitTestPoseArray); + Native.SetWebXRAnchorEvents(OnAnchorCreatedInternal, OnAnchorDeletedInternal); + Native.InitAnchorsArray(anchorsDataArray); Native.InitXRSharedArray(sharedArray); #endif } @@ -294,6 +367,31 @@ public static extern void SetWebXREvents(StartXREvent on_start_ar, EndXREvent on_end_xr, XRCapabilitiesEvent on_xr_capabilities, InputProfilesEvent on_input_profiles); + + [DllImport("__Internal")] + public static extern void InitAnchorsArray(float[] array); + + [DllImport("__Internal")] + public static extern void SetWebXRAnchorEvents( + AnchorCreatedEvent on_anchor_created, + AnchorDeletedEvent on_anchor_deleted); + + [DllImport("__Internal")] + public static extern void CreateAnchorFromViewerHitTest(); + + [DllImport("__Internal")] + public static extern void CreateAnchorFromWaitingForViewerHitTest(); + + [DllImport("__Internal")] + public static extern void CreateAnchorFromPose( + float px, float py, float pz, + float qx, float qy, float qz, float qw); + + [DllImport("__Internal")] + public static extern void DeleteAnchor(int anchorId); + + [DllImport("__Internal")] + public static extern void DeleteAllAnchors(); } #endif @@ -340,6 +438,18 @@ public delegate void HeadsetUpdate( internal static event HitTestUpdate OnViewerHitTestUpdate; + public delegate void AnchorCreated(int anchorId); + internal static event AnchorCreated OnAnchorCreated; + + public delegate void AnchorDeleted(int anchorId); + internal static event AnchorDeleted OnAnchorDeleted; + + public delegate void AnchorUpdate(WebXRAnchorData anchorData); + internal static event AnchorUpdate OnAnchorUpdate; + + internal delegate void AnchorCreatedEvent(int anchorId); + internal delegate void AnchorDeletedEvent(int anchorId); + internal delegate void StartXREvent(int viewsCount, float left_x, float left_y, float left_w, float left_h, float right_x, float right_y, float right_w, float right_h); @@ -363,6 +473,14 @@ internal delegate void StartXREvent(int viewsCount, // 2 XRViewports, views count, is transparent, framebuffer width height, stored linearly. float[] sharedArray = new float[(2 * 16) + (2 * 7) + (2 * 4) + 1 + 1 + 2]; + private const int MaxWebXRAnchors = 32; + + private const int WebXRAnchorArrayStride = 10; + + float[] anchorsDataArray = new float[MaxWebXRAnchors * WebXRAnchorArrayStride]; + + private readonly WebXRAnchorData[] anchors = new WebXRAnchorData[MaxWebXRAnchors]; + // Shared array for controllers data float[] controllersArray = new float[2 * 34]; @@ -472,6 +590,18 @@ public static void OnEndXR() Instance.setXrState(WebXRState.NORMAL, 1, new Rect(), new Rect()); } + [MonoPInvokeCallback(typeof(AnchorCreatedEvent))] + public static void OnAnchorCreatedInternal(int anchorId) + { + OnAnchorCreated?.Invoke(anchorId); + } + + [MonoPInvokeCallback(typeof(AnchorDeletedEvent))] + public static void OnAnchorDeletedInternal(int anchorId) + { + OnAnchorDeleted?.Invoke(anchorId); + } + public void ToggleAR() { #if UNITY_WEBGL @@ -652,5 +782,82 @@ bool GetHitTestPoseFromViewerHitTestPoseArray(ref WebXRHitPoseData hitPoseData) viewerHitTestPoseArray[arrayPosition++], viewerHitTestPoseArray[arrayPosition++]); return true; } + + public void CreateAnchorFromViewerHitTest() + { +#if UNITY_WEBGL + if (xrState != WebXRState.AR) + { + return; + } + if (!AnchorsFeatureEnabled()) + { + return; + } + Native.CreateAnchorFromViewerHitTest(); +#endif + } + + public void CreateAnchorFromWaitingForViewerHitTest() + { +#if UNITY_WEBGL + if (xrState != WebXRState.AR) + { + return; + } + if (!AnchorsFeatureEnabled()) + { + return; + } + Native.CreateAnchorFromWaitingForViewerHitTest(); +#endif + } + + public void CreateAnchorFromPose(Vector3 position, Quaternion rotation) + { +#if UNITY_WEBGL + if (xrState != WebXRState.AR) + { + return; + } + if (!AnchorsFeatureEnabled()) + { + return; + } + Native.CreateAnchorFromPose( + position.x, position.y, position.z, + rotation.x, rotation.y, rotation.z, rotation.w); +#endif + } + + public void DeleteAnchor(int anchorId) + { +#if UNITY_WEBGL + if (xrState != WebXRState.AR) + { + return; + } + if (!AnchorsFeatureEnabled()) + { + return; + } + Native.DeleteAnchor(anchorId); +#endif + } + + public void DeleteAllAnchors() + { +#if UNITY_WEBGL + if (xrState != WebXRState.AR) + { + return; + } + if (!AnchorsFeatureEnabled()) + { + return; + } + Native.DeleteAllAnchors(); +#endif + } } } diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab b/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab new file mode 100644 index 00000000..71932311 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab @@ -0,0 +1,491 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &186481346483102803 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8971202239850332909} + - component: {fileID: 7802920332531909973} + - component: {fileID: 1992713582359565122} + - component: {fileID: 6890298623029420764} + m_Layer: 0 + m_Name: AxisZ + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8971202239850332909 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186481346483102803} + serializedVersion: 2 + m_LocalRotation: {x: 0.70710707, y: -0, z: -0, w: 0.7071066} + m_LocalPosition: {x: 0, y: 0, z: 0.75} + m_LocalScale: {x: 0.05, y: 0.75, z: 0.05} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4196391294288101103} + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!33 &7802920332531909973 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186481346483102803} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1992713582359565122 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186481346483102803} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 07bc01a61745c4456847de19a0a08da1, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!136 &6890298623029420764 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186481346483102803} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!1 &2678738213269342726 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4196391294288101103} + - component: {fileID: 5884933614345139448} + - component: {fileID: 1671750000665188811} + - component: {fileID: 2636517920994574474} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4196391294288101103 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2678738213269342726} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.05, y: 0.05, z: 0.05} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 8971202239850332909} + - {fileID: 4120173779939497730} + - {fileID: 3396652751079388407} + m_Father: {fileID: 3345775371870950389} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &5884933614345139448 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2678738213269342726} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1671750000665188811 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2678738213269342726} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9e4f8d2e35ef5472a83b6077130cb51e, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &2636517920994574474 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2678738213269342726} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &7346354743300970381 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3396652751079388407} + - component: {fileID: 3677326710678424955} + - component: {fileID: 5526121050161511356} + - component: {fileID: 8376316236685843477} + m_Layer: 0 + m_Name: AxisY + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3396652751079388407 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7346354743300970381} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.75, z: 0} + m_LocalScale: {x: 0.05, y: 0.75, z: 0.05} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4196391294288101103} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &3677326710678424955 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7346354743300970381} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5526121050161511356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7346354743300970381} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 83216b7817d6b4f5db75c534988ccb26, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!136 &8376316236685843477 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7346354743300970381} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!1 &7418316785324538391 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3345775371870950389} + m_Layer: 0 + m_Name: Anchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3345775371870950389 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7418316785324538391} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 4196391294288101103} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8744828765488003652 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4120173779939497730} + - component: {fileID: 120220627702371309} + - component: {fileID: 8630198480999416374} + - component: {fileID: 7495224800854054248} + m_Layer: 0 + m_Name: AxisX + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4120173779939497730 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8744828765488003652} + serializedVersion: 2 + m_LocalRotation: {x: 0.5, y: 0.5, z: -0.5, w: 0.5} + m_LocalPosition: {x: 0.75, y: 0, z: 0} + m_LocalScale: {x: 0.05, y: 0.75, z: 0.05} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4196391294288101103} + m_LocalEulerAnglesHint: {x: 90, y: 90, z: 0} +--- !u!33 &120220627702371309 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8744828765488003652} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8630198480999416374 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8744828765488003652} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cd5ab9304d6ab4f858d818b0cc3feffd, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!136 &7495224800854054248 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8744828765488003652} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab.meta b/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab.meta new file mode 100644 index 00000000..cbff7250 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Anchor.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b5a85fd60a6b14f28b4cb5f7adfa86b6 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat b/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat new file mode 100644 index 00000000..80a8f75e --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1536827106776506223 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Blue + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 1, a: 1} + - _Color: {r: 0, g: 0, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat.meta b/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat.meta new file mode 100644 index 00000000..cf846321 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Blue.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 07bc01a61745c4456847de19a0a08da1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat b/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat new file mode 100644 index 00000000..fedd4d9d --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1536827106776506223 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Green + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0, g: 1, b: 0, a: 1} + - _Color: {r: 0, g: 1, b: 0, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat.meta b/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat.meta new file mode 100644 index 00000000..69e84cb3 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Green.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83216b7817d6b4f5db75c534988ccb26 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat b/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat new file mode 100644 index 00000000..e6d43ec0 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1536827106776506223 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Red + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 0, b: 0, a: 1} + - _Color: {r: 1, g: 0, b: 0, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat.meta b/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat.meta new file mode 100644 index 00000000..a3164fcd --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Red.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cd5ab9304d6ab4f858d818b0cc3feffd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat b/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat new file mode 100644 index 00000000..0c73d220 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat @@ -0,0 +1,141 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Transparent + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHAPREMULTIPLY_ON + - _SURFACE_TYPE_TRANSPARENT + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: + - MOTIONVECTORS + - DepthOnly + - SHADOWCASTER + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _DstBlendAlpha: 10 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 1 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 0 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 0.5019608} + - _Color: {r: 1, g: 1, b: 1, a: 0.5019608} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &7883437871751797079 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat.meta b/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat.meta new file mode 100644 index 00000000..55ca9f23 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/Transparent.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e4f8d2e35ef5472a83b6077130cb51e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab b/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab new file mode 100644 index 00000000..e79cb59c --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7080766884625336350 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1237885867817271649} + - component: {fileID: 2520011617434627279} + m_Layer: 0 + m_Name: WebXRAnchor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1237885867817271649 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7080766884625336350} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 270, y: 480, z: 0.025} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2520011617434627279 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7080766884625336350} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6185a19b483ff4f42a1ad0172c19eb0b, type: 3} + m_Name: + m_EditorClassIdentifier: WebXRAnchorSample::WebXRAnchorExample + anchoredPrefab: {fileID: 3345775371870950389, guid: b5a85fd60a6b14f28b4cb5f7adfa86b6, + type: 3} diff --git a/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab.meta b/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab.meta new file mode 100644 index 00000000..29b06943 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Prefabs/WebXRAnchor.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7ca39775fb9b5429897891dd3a1b2274 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Scripts.meta b/Packages/webxr/Samples~/Anchors/Scripts.meta new file mode 100644 index 00000000..38986fa0 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 01c8a24bdbc0f46e989bc8621a7fa9cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs b/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs new file mode 100644 index 00000000..1d8eb5bd --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using UnityEngine; +using WebXR; + +public class WebXRAnchorExample : MonoBehaviour +{ + [SerializeField] + private Transform anchoredPrefab; + + private readonly Dictionary instances = new Dictionary(); + + private void OnEnable() + { + WebXRManager.OnAnchorUpdate += OnAnchorUpdate; + WebXRManager.OnAnchorDeleted += OnAnchorDeleted; + } + + private void OnDisable() + { + WebXRManager.OnAnchorUpdate -= OnAnchorUpdate; + WebXRManager.OnAnchorDeleted -= OnAnchorDeleted; + } + + public void StartHitTest() + { + WebXRManager.Instance.StartViewerHitTest(); + } + + /// + /// Creates an anchor at the current hit test result. The anchor will be created at the position and rotation of the current hit test result, which is updated every frame when a hit test result is available. If no hit test result is available, no anchor will be created.
+ /// This method does not work reliably because of timing.. better use + ///
+ public void PlaceAnchorAtCurrentHitTest() + { + WebXRManager.Instance.CreateAnchorFromViewerHitTest(); + } + + /// + /// Creates an anchor at the next hit test result. The anchor will be created at the position and rotation of the next hit test result, which is updated every frame when a hit test result is available. + /// + public void PlaceAnchorAtNextHitTest() + { + WebXRManager.Instance.CreateAnchorFromWaitingForViewerHitTest(); + } + + /// + /// Creates an anchor at the position and rotation of the given transform. The anchor will be created at the position and rotation of the given transform.
+ /// Anchors are more reliable when created from hit test results, so prefer the other methods if possible. + ///
+ /// Any Transform (this method will just read its position and rotation) + public void PlaceAnchorAtTransform(Transform source) + { + WebXRManager.Instance.CreateAnchorFromPose(source.position, source.rotation); + } + + private void OnAnchorUpdate(WebXRAnchorData anchor) + { + if (!anchor.tracked) + return; + + if (!instances.TryGetValue(anchor.id, out Transform instance)) + { + instance = Instantiate(anchoredPrefab); + instances.Add(anchor.id, instance); + } + + instance.SetPositionAndRotation(anchor.position, anchor.rotation); + } + + private void OnAnchorDeleted(int anchorId) + { + if (instances.TryGetValue(anchorId, out Transform instance)) + { + Destroy(instance.gameObject); + instances.Remove(anchorId); + } + } +} \ No newline at end of file diff --git a/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs.meta b/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs.meta new file mode 100644 index 00000000..96c6dde3 --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/Scripts/WebXRAnchorExample.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6185a19b483ff4f42a1ad0172c19eb0b \ No newline at end of file diff --git a/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef b/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef new file mode 100644 index 00000000..c6e588ce --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef @@ -0,0 +1,18 @@ +{ + "name": "WebXRAnchorSample", + "rootNamespace": "", + "references": [ + "GUID:fd4abe4ffe74ef1448afe15c6cb36bb7" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [ + "" + ], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef.meta b/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef.meta new file mode 100644 index 00000000..aa8ff63e --- /dev/null +++ b/Packages/webxr/Samples~/Anchors/WebXRAnchorSample.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 11ffbc57b92314805bf3dffb5d12b852 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/webxr/package.json b/Packages/webxr/package.json index 91613da7..42a177c8 100644 --- a/Packages/webxr/package.json +++ b/Packages/webxr/package.json @@ -17,6 +17,13 @@ "name": "De-Panther", "url": "https://github.com/De-Panther/unity-webxr-export" }, + "samples": [ + { + "displayName": "XR Anchors Sample", + "description": "Sample Class to work with XR Anchors in WebXR", + "path": "Samples~/Anchors" + } + ], "dependencies": { "com.unity.xr.management": "3.2.13" }