diff --git a/package/CHANGELOG.md b/package/CHANGELOG.md index 9f828f20f..7ea9bd987 100755 --- a/package/CHANGELOG.md +++ b/package/CHANGELOG.md @@ -1,128 +1,137 @@ -# Changelog -All notable changes to this package will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## [1.1.0-preview.6] - 2019-03-12 -### Fixes -- Add dependency on Legacy Input Helpers, which were moved from Unity to a package in 2019.1. - -## [1.0.0-preview.22] - 2018-12-13 - -- Fix package dependency - -## [1.0.0-preview.21] - 2018-12-13 - -### New -- Added Face Tracking support: `ARFaceManager`, `ARFace`, `ARFaceMeshVisualizer` and related scripts. See documentation for usage. - -### Improvements -- Plane detection modes: Add ability to selectively enable detection for horizontal, vertical, or both types of planes. The `ARPlaneManager` includes a new setting, which defaults to both. -- Add support for setting the camera focus mode. Added a new component, `ARCameraOptions`, which lets you set the focus mode. - -### Changes -- The light estimation option, which was previously on the `ARSession` component, has been moved to the new `ARCameraOptions` component. - -## [1.0.0-preview.20] - 2018-11-06 -### Improvements -- Support reference points reported without a corresponding `TryAddReferencePoint` call. This handles reference points that are added by some other means, e.g., loaded from a serialized session. - -## [1.0.0-preview.19] - 2018-10-10 -- Added support for `XRCameraExtensions` API to get the raw camera image data on the CPU. See the [manual documentation](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/manual/cpu-camera-image.html) for more information. - -## [1.0.0-preview.18] - 2018-09-13 -### Fixes -- The `ARPlaneMeshVisualizer` did not disable its visible components (`MeshRenderer` and `LineRenderer`) when disabled. This has been fixed. - -### Changes -- The `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager` all instantiate either prefabs that you specify or `GameObject`s with at least an `ARPlane`, `ARPointCloud`, or `ARReferencePoint`, respectively, on them. The instantiated `GameObject`'s layer was set to match the `ARSessionOrigin`, overwriting the layer specified in the prefab. This has been changed so that if a prefab is specified, no changes to the layer are made. If no prefab is specified, then a new `GameObject` is created, and its layer will match that of the `ARSessionOrigin`'s `GameObject`. - -### New -- Added `ARPlane.normal` to get the `ARPlane`'s normal in world space. - -### LWRP support -Added LWRP support by allowing `ARCameraBackground` to use a background renderer that overrides the default functionality. This works in conjunction with some *LWRPSupport* files (see [arfoundation-samples](https://github.com/Unity-Technologies/arfoundation-samples)) that will live in your LWRP project. - -## [1.0.0-preview.17] - 2018-08-02 -### Fixes -- Add `FormerlySerializedAs` attribute to serialized field changes to `ARCameraBackground`. - -## [1.0.0-preview.16] - 2018-07-26 -### Change -- Removed static constructor from `ARSubsystemManager`. This allows access to the manager without forcing the creation of the subsystems, making the initialization more flexible. - -## [1.0.0-preview.15] - 2018-07-26 -### Fixes -- `ARPlane.vertexChangedThreshold` is no longer allowed to be negative. -- The `ARCameraBackground` component did not reset the projection matrix on disable, leading to stretching or other distortion. This has been fixed. -- The `ARCameraBackground` component did not properly handle an overriden material. This has been fixed (see API Changes below). -- The `ARPlaneMeshGenerators` was meant to generate a triangle fan about the center of the plane. However, indices were instead generated as a fan about one of the bounary points. The visual result is similar, but can lead to long thin triangles. This has been fixed to use the plane's center point as intended. -- Update for compatibility with 2018.3 -- If the `ARPlaneMeshVisualizer` has a `LineRenderer` on it, then it will be scaled to match the `ARPlane`'s scale, making the visual width invariant under differing `ARSessionOrigin` scales. -- When the `ARPointCloudManager` instantiated a point cloud prefab, it did not change its transform. If it was not identity, then feature points would appear in unexpected places. It now instantiates the point cloud prefab with identity transform. -- The menu item "GameObject > XR > AR Default Point Cloud" created a `GameObject` which used a particle system whose "Scaling Mode" was set to "Local". If used as the `ARPointCloudManager`'s point cloud prefab, this would produce odd results when the `ARSessionOrigin` was scaled. The correct setting is "Hierarchy", and the utility now creates a particle system with the correct setting. - -### API Changes -#### ARCameraBackground -The API for overriding the material has been refactored. Previously, a custom material could be set with the `ARCameraBackground.material` setter, but this might be overwritten later if the option to override was disabled. -- Rename: `overrideMaterial` is now `useCustomMaterial` -- New member: `customMaterial` -- The following properties are now private: - - `material` setter (getter is still public) - - `backgroundRenderer` - -Use the `ARCameraBackground.material` getter to get the currently active material. - -## [1.0.0-preview.14] - 2018-07-17 -### Fixes -- Fixed a bug in the `ARCameraBackground` which would not render the camera texture properly if the `ARSession` had been destroyed and then recreated or if the `ARCameraBackground` had been disabled and then re-enabled. -- `ARSubsystemManager.systemState`'s setter was not private, allowing user code to change the system state. The setter is now private. -- `ARPlane.trackingState` returned a cached value, which was incorrect if the `ARSession` was no longer active. - -### Improvements -- Added `ARSession.Reset()` to destroy the current AR Session and establish a new one. This destroys all trackables, such as planes. -- Added an `ARSubsystemManager.sessionDestroyed` event. The `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager` subscribe to this event, and they remove their trackables when the `ARSession` is destroyed. - -## [1.0.0-preview.13] - 2018-07-03 -- Fixed a bug where point clouds did not stop rendering when disabled. -- Added a getter on the `ARPointCloudManager` for the instantiated `ARPointCloud`. -- Added UVs to the `Mesh` generated by the `ARPlaneMeshVisualizer`. -- Refactored out plane mesh generation functionality into a new static class `ARPlaneMeshGenerators`. -- Added a `meshUpdated` event to the `ARPlaneMeshVisualizer`, which lets you customize the generated `Mesh`. -- Added AR Icons. - -## [1.0.0-preview.12] - 2018-06-14 -- Add color correction value to `LightEstimationData`. - -## [1.0.0-preview.11] - 2018-06-08 -- Improve lifecycle reporting: remove public members `ARSubsystemManager.availability` and `ARSubsystemManager.trackingState`. Combine with `ARSubsystemManager.systemState` and the public event `ARSubsystemManager.systemStateChanged`. -- Docs improvements -- Move `ParticleSystem` to the top of the `ARDebugPointCloudVisualizer` - -## [1.0.0-preview.10] - 2018-06-06 - -- Update documentation: ARSession image and written description. - -## [1.0.0-preview.9] - 2018-06-06 - -- Rename `ARBackgroundRenderer` to `ARCameraBackground` -- Unify `ARSessionState` & `ARSystemState` enums - -## [1.0.0-preview.8] - 2018-05-23 -- Change dependency to `ARExtension` 1.0.0-preview.2 - -## [1.0.0-preview.7] - 2018-05-23 -- Remove "timeout" from AR Session -- Add availability and AR install support -- Significant rework to startup lifecycle & asynchronous availability check - -## [1.0.0-preview.6] - 2018-04-25 - -### Rename ARUtilities to ARFoundation - -- This package is now called `ARFoundation`. -- Removed `ARPlaceOnPlane`, `ARMakeAppearOnPlane`, `ARPlaneMeshVisualizer`, and `ARPointCloudParticleVisualizer` as these were deemed sample content. -- Removed setup wizard. -- Renamed `ARRig` to `ARSessionOrigin`. -- `ARSessionOrigin` no longer requires its `Camera` to be a child of itself. +# Changelog +All notable changes to this package will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [2.0.1] - 2019-03-05 +## Changes + +- See the [Migration Guide](Documentation~/migration-guide.md). + +## [1.1.0-preview.1] - 2019-??-?? +### Fixes +- Add dependency on Legacy Input Helpers, which were moved from Unity to a package in 2019.1. + +## [1.0.0-preview.23] - 2019-??-?? +### New +- Add a generic base class for future tracking subsystems. + +## [1.0.0-preview.22] - 2018-12-13 + +- Fix package dependency + +## [1.0.0-preview.21] - 2018-12-13 + +### New +- Added Face Tracking support: `ARFaceManager`, `ARFace`, `ARFaceMeshVisualizer` and related scripts. See documentation for usage. + +### Improvements +- Plane detection modes: Add ability to selectively enable detection for horizontal, vertical, or both types of planes. The `ARPlaneManager` includes a new setting, which defaults to both. +- Add support for setting the camera focus mode. Added a new component, `ARCameraOptions`, which lets you set the focus mode. + +### Changes +- The light estimation option, which was previously on the `ARSession` component, has been moved to the new `ARCameraOptions` component. + +## [1.0.0-preview.20] - 2018-11-06 +### Improvements +- Support reference points reported without a corresponding `TryAddReferencePoint` call. This handles reference points that are added by some other means, e.g., loaded from a serialized session. + +## [1.0.0-preview.19] - 2018-10-10 +- Added support for `XRCameraExtensions` API to get the raw camera image data on the CPU. See the [manual documentation](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/manual/cpu-camera-image.html) for more information. + +## [1.0.0-preview.18] - 2018-09-13 +### Fixes +- The `ARPlaneMeshVisualizer` did not disable its visible components (`MeshRenderer` and `LineRenderer`) when disabled. This has been fixed. + +### Changes +- The `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager` all instantiate either prefabs that you specify or `GameObject`s with at least an `ARPlane`, `ARPointCloud`, or `ARReferencePoint`, respectively, on them. The instantiated `GameObject`'s layer was set to match the `ARSessionOrigin`, overwriting the layer specified in the prefab. This has been changed so that if a prefab is specified, no changes to the layer are made. If no prefab is specified, then a new `GameObject` is created, and its layer will match that of the `ARSessionOrigin`'s `GameObject`. + +### New +- Added `ARPlane.normal` to get the `ARPlane`'s normal in world space. + +### LWRP support +Added LWRP support by allowing `ARCameraBackground` to use a background renderer that overrides the default functionality. This works in conjunction with some *LWRPSupport* files (see [arfoundation-samples](https://github.com/Unity-Technologies/arfoundation-samples)) that will live in your LWRP project. + +## [1.0.0-preview.17] - 2018-08-02 +### Fixes +- Add `FormerlySerializedAs` attribute to serialized field changes to `ARCameraBackground`. + +## [1.0.0-preview.16] - 2018-07-26 +### Change +- Removed static constructor from `ARSubsystemManager`. This allows access to the manager without forcing the creation of the subsystems, making the initialization more flexible. + +## [1.0.0-preview.15] - 2018-07-26 +### Fixes +- `ARPlane.vertexChangedThreshold` is no longer allowed to be negative. +- The `ARCameraBackground` component did not reset the projection matrix on disable, leading to stretching or other distortion. This has been fixed. +- The `ARCameraBackground` component did not properly handle an overriden material. This has been fixed (see API Changes below). +- The `ARPlaneMeshGenerators` was meant to generate a triangle fan about the center of the plane. However, indices were instead generated as a fan about one of the bounary points. The visual result is similar, but can lead to long thin triangles. This has been fixed to use the plane's center point as intended. +- Update for compatibility with 2018.3 +- If the `ARPlaneMeshVisualizer` has a `LineRenderer` on it, then it will be scaled to match the `ARPlane`'s scale, making the visual width invariant under differing `ARSessionOrigin` scales. +- When the `ARPointCloudManager` instantiated a point cloud prefab, it did not change its transform. If it was not identity, then feature points would appear in unexpected places. It now instantiates the point cloud prefab with identity transform. +- The menu item "GameObject > XR > AR Default Point Cloud" created a `GameObject` which used a particle system whose "Scaling Mode" was set to "Local". If used as the `ARPointCloudManager`'s point cloud prefab, this would produce odd results when the `ARSessionOrigin` was scaled. The correct setting is "Hierarchy", and the utility now creates a particle system with the correct setting. + +### API Changes +#### ARCameraBackground +The API for overriding the material has been refactored. Previously, a custom material could be set with the `ARCameraBackground.material` setter, but this might be overwritten later if the option to override was disabled. +- Rename: `overrideMaterial` is now `useCustomMaterial` +- New member: `customMaterial` +- The following properties are now private: + - `material` setter (getter is still public) + - `backgroundRenderer` + +Use the `ARCameraBackground.material` getter to get the currently active material. + +## [1.0.0-preview.14] - 2018-07-17 +### Fixes +- Fixed a bug in the `ARCameraBackground` which would not render the camera texture properly if the `ARSession` had been destroyed and then recreated or if the `ARCameraBackground` had been disabled and then re-enabled. +- `ARSubsystemManager.systemState`'s setter was not private, allowing user code to change the system state. The setter is now private. +- `ARPlane.trackingState` returned a cached value, which was incorrect if the `ARSession` was no longer active. + +### Improvements +- Added `ARSession.Reset()` to destroy the current AR Session and establish a new one. This destroys all trackables, such as planes. +- Added an `ARSubsystemManager.sessionDestroyed` event. The `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager` subscribe to this event, and they remove their trackables when the `ARSession` is destroyed. + +## [1.0.0-preview.13] - 2018-07-03 +- Fixed a bug where point clouds did not stop rendering when disabled. +- Added a getter on the `ARPointCloudManager` for the instantiated `ARPointCloud`. +- Added UVs to the `Mesh` generated by the `ARPlaneMeshVisualizer`. +- Refactored out plane mesh generation functionality into a new static class `ARPlaneMeshGenerators`. +- Added a `meshUpdated` event to the `ARPlaneMeshVisualizer`, which lets you customize the generated `Mesh`. +- Added AR Icons. + +## [1.0.0-preview.12] - 2018-06-14 +- Add color correction value to `LightEstimationData`. + +## [1.0.0-preview.11] - 2018-06-08 +- Improve lifecycle reporting: remove public members `ARSubsystemManager.availability` and `ARSubsystemManager.trackingState`. Combine with `ARSubsystemManager.systemState` and the public event `ARSubsystemManager.systemStateChanged`. +- Docs improvements +- Move `ParticleSystem` to the top of the `ARDebugPointCloudVisualizer` + +## [1.0.0-preview.10] - 2018-06-06 + +- Update documentation: ARSession image and written description. + +## [1.0.0-preview.9] - 2018-06-06 + +- Rename `ARBackgroundRenderer` to `ARCameraBackground` +- Unify `ARSessionState` & `ARSystemState` enums + +## [1.0.0-preview.8] - 2018-05-23 +- Change dependency to `ARExtension` 1.0.0-preview.2 + +## [1.0.0-preview.7] - 2018-05-23 +- Remove "timeout" from AR Session +- Add availability and AR install support +- Significant rework to startup lifecycle & asynchronous availability check + +## [1.0.0-preview.6] - 2018-04-25 + +### Rename ARUtilities to ARFoundation + +- This package is now called `ARFoundation`. +- Removed `ARPlaceOnPlane`, `ARMakeAppearOnPlane`, `ARPlaneMeshVisualizer`, and `ARPointCloudParticleVisualizer` as these were deemed sample content. +- Removed setup wizard. +- Renamed `ARRig` to `ARSessionOrigin`. +- `ARSessionOrigin` no longer requires its `Camera` to be a child of itself. diff --git a/package/CHANGELOG.md.meta b/package/CHANGELOG.md.meta index a1fc8a6a0..c058bf074 100755 --- a/package/CHANGELOG.md.meta +++ b/package/CHANGELOG.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: b5c2bae8918810248a6f4832c52cc7cd -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: b5c2bae8918810248a6f4832c52cc7cd +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Documentation~/com.unity.xr.arfoundation.md b/package/Documentation~/com.unity.xr.arfoundation.md index 1fda86bc9..763293a62 100755 --- a/package/Documentation~/com.unity.xr.arfoundation.md +++ b/package/Documentation~/com.unity.xr.arfoundation.md @@ -1,242 +1,272 @@ -# About AR Foundation - -Use the AR Foundation package to add high-level functionality for working with augmented reality. Unity 2018.1 includes built-in multi-platform support for AR. These APIs are in the `UnityEngine.Experimental.XR` namespace, and consist of a number of `Subsystem`s, e.g., `XRPlaneSubsystem`. Several XR Subsystems comprise the low-level API for interacting with AR. The **AR Foundation** package wraps this low-level API into a cohesive whole and enhances it with additional utilities, such as AR session lifecycle management and the creation of `GameObject`s to represent detected features in the environment. - -AR Foundation is a set of `MonoBehaviour`s for dealing with devices that support following concepts: -- Planar surface detection -- Point clouds, also known as feature points -- Reference points: an arbitrary position and orientation that the device tracks -- Light estimation: estimates for average color temperature and brightness in physical space. -- World tracking: tracking the device's position and orientation in physical space. - -# Installing AR Foundation - -To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html). - -In addition, you need to install at least one platform-specific AR package (*Window > Package Manager*): - - - ARKit XR Plugin - - ARCore XR Plugin - -# Glossary - -| Term | Meaning | -|-|-| -| Tracking | The ability of the AR device to determine its relative position and orientation in the world. If the environment is too dark, for example, the device may "lose tracking", which means it can no longer accurately report its position. | -| Trackable | A real-world feature detected and/or tracked by the AR device, e.g., a planar surface. | -| Feature Point | A specific point in a point cloud. AR devices use a camera and image analysis to track specific points in the world which are used to build a map of its environment. These are usually high frequency elements, such as a knot in a wood-grain surface.| -| Session | Refers to an AR instance. | -| Session Space | The coordinate system relative to the beginning of the AR session. For example, session space (0, 0, 0) refers to the position at which the AR session was created. An AR device typically reports trackables and tracking information relative to its session origin.| - -# Using AR Foundation - -## Basic Setup - -A basic AR scene hierarchy looks like this: - -![alt text](images/simple_scene_graph.png "Scene graph") - -Required components are explained below. - -### ARSession -An AR scene should include an `ARSession` component. The AR Session controls the lifecycle of an AR experience, enabling or disabling AR on the target platform. The `ARSession` can be on any `GameObject`. - -![alt text](images/ar_session.png "ARSession component") - -An AR Session can be started, paused, resumed, and stopped entirely. Enabling or disabling the component will start/resume or pause the session, respectively. If a session is "paused", the system no longer tracks features in its environment, but if it is resumed at a later time, the system will attempt to recover and maintain previously detected features. - -A session has the following options, each of which may be changed at runtime: - -| Option | Meaning | -|-|-| -| Light Estimation | Whether to enable light estimation information. This can be used to correctly light virtual content in the scene. | -| Try to Install Update If Needed | Will try to install AR software if possible. | - -**Note:** An AR session is a global construct. An `ARSession` component manages this global session, so multiple `ARSession` components will all try to manage the same global session. - -### AR Subsystem Manager -Included in any AR Session is a static class called `ARSubsystemManager`. This manager governs the lifecycles of multiple AR-related subsystems and provides higher level abstractions and utilities for managing and using the AR-related subsystems. - -The AR Subsystem Manager also maintains the current state of the session. The state of the current session can be queried through the `ARSubsystemManager.systemState` variable and compared against the values of the `ARSystemState` enumeration. There is also a callback that can be subscribed to within the `ARSubsystemManager` named `systemStateChanged`. - -A session can be in one of the following states and can change during runtime: - -|State|Meaning| -|-|-| -|None|The AR System has not been initialized and availability is unknown.| -|Unsupported|AR is not supported on the current device.| -|CheckingAvailability|The system is checking the availability of AR on the current device.| -|NeedsInstall|AR is supported on the current device, but requires an additional install.| -|Installing|AR software is being installed| -|Ready|AR is supported and ready| -|SessionInitialized|An AR session is initializing (i.e., starting up). This usually means AR is working but has not gathered enough information about the environment| -|SessionTracking|An AR session is running and is tracking (i.e., the device is able to determine its position and orientation in the world).| - -### ARSessionOrigin - -![alt text](images/ar_session_origin.png "AR Session Origin") - -The purpose of the `ARSessionOrigin` is to transform trackable features (such as planar surfaces and feature points) into their final position, orientation, and scale in the Unity scene. Because AR devices provide their data in "session space", an unscaled space relative to the beginning of the AR session, the `ARSessionOrigin` performs the appropriate transformation into Unity space. - -This concept is similar to the difference between "model" or "local" space and world space when working with other assets in Unity. For instance, if you import a house asset from a DCC tool, then the door will have a position relative to the modeler's origin. This is commonly called "model space" or "local space". When it is instantiated in Unity, it will also have a world space, relative to Unity's origin. - -Likewise, trackables produced by an AR device, such as planes, are provided in "session space", relative to the device's coordinate system. When instantiated in Unity as `GameObject`s, they also have a world space. In order to instantiate them in the correct place, Unity needs to know where the session origin should be in the Unity scene. - -The `ARSessionOrigin` also allows you to scale virtual content and apply an offset to the camera. If you are scaling or offseting the `ARSessionOrigin`, then its `Camera` should be a child of the `ARSessionOrigin`. Since the `Camera` is driven by the session, the `Camera` and detected trackables will move together in this setup. - -#### Scale - -To apply scale to the `ARSessionOrigin`, simply set its `transform`'s scale. This has the effect of scaling all the data coming from the device, including the `AR Camera`'s position and any detected trackables. Larger values will make AR content appear smaller, so, for example, a scale of 10 would make your content appear 10 times smaller, while 0.1 would make your content appear 10 times larger. - -### TrackedPoseDriver - -Parented to the `ARSessionOrigin`'s' `GameObject` should be (at least) one camera, which will be used to render any trackables you wish to visualize. The camera should also have a `TrackedPoseDriver` component on it, which will drive the camera's local position and rotation according to the device's tracking information. This setup allows the camera's local space to match the AR "session space". - -![alt text](images/tracked_pose_driver.png "TrackedPoseDriver") - -The `Camera` must be a child of the `ARSessionOrigin`. - -### ARCameraBackground - -If you want to render the device's color camera texture to the background, you need to add an `ARCameraBackground` component to a camera. This will subscribe to AR camera events and blit the camera texture to the screen. This is not required, but common for AR apps. - -![alt text](images/ar_background_renderer.png "ARCameraBackground") - -The `Custom Material` property is optional, and typically you do not need to set it. The platform-specific packages provided by Unity (e.g., `ARCore` and `ARKit`) provide their own shaders for background rendering. - -If `Use Custom Material` is `true`, then the `ARCameraBackground` will use the `Material` you specify for background rendering. - -If you have exactly one `ARSessionOrigin`, then you can simply add the `ARCameraBackground` to that camera. If you have multiple `ARSessionOrigin`s (to selectively render different content at different scales, for instance), you should use separate cameras for each `ARSessionOrigin` and a separate, single camera for the `ARCameraBackground`. - -#### Copying the Camera Texture to a Render Texture - -The camera textures are likely [External Textures](https://docs.unity3d.com/ScriptReference/Texture2D.CreateExternalTexture.html) and may not last beyond a frame boundary. It can be useful to copy the camera image to a [Render Texture](https://docs.unity3d.com/Manual/class-RenderTexture.html) for persistence or further processing. This code will blit the camera image to a render texture of your choice: - -```csharp -Graphics.Blit(null, m_MyRenderTexture, m_ARBackgroundCamera.material); -``` - -### Accessing the Camera Image on the CPU - -See [Camera Image Manual Documentation](cpu-camera-image.md). - -### AR Managers - -The `ARSessionOrigin`'s' `GameObject` can also have a number of additional components on it, which manage the addition, updating, and removal of `GameObject`s to represent planes, point cloud, and reference points. These are the `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager`, respectively: - -![alt text](images/ar_session_origin_with_managers.png "AR Session Origin with Managers") - -Each manager subscribes to relevant AR events, such as `planeAdded`, `planeUpdated`, and `planeRemoved`, and creates `GameObject`s for each detected trackable. The generated `GameObject`s are parented to a special `GameObject` under the `ARSessionOrigin`, accessible via `ARSessionOrigin.trackablesParent`. - -Each manager also accepts an optional prefab, which will be instantiated to represent the trackable. If no prefab is specified, a `GameObject` is created with an appropriate trackable component: - -| Manager | Trackable Component | -|---------------------------|---------------------| -| `ARPlaneManager` | `ARPlane` | -| `ARPointCloudManager` | `ARPointCloud` | -| `ARReferencePointManager` | `ARReferencePoint` | - -Each trackable component stores information about the trackable, but does not visualize it. Its `Transform` is updated by its manager whenever the AR device reports an update. - -Most trackables have a session-unique `TrackableId` associated with them. You can access an individual trackable by id through its manager. - -**Note** A point cloud does not have a `TrackableId` (nor do the individual points within the cloud), and only one `GameObject` is created to represent the entire point cloud. - -### Visualizing Trackables - -To do something with the generated trackables, subscribe to the appropriate event on that trackable's component. - -An `ARPlane` has the following events: - -| Event | Description | -|-|-| -| `updated` | Invoked when a plane is updated | -| `removed` | Invoked when a plane is about to be removed.

**Note:** By default, the `ARPlane` (and its `GameObject`) will be removed immediately. You can suppress this behavior by setting `ARPlane.destroyOnRemoval` to `false`. You may wish to do this if, for example, you want the plane to fade out over time. | -| `boundaryChanged` | Invoked when the boundary points change by more than `ARPlane.vertexChangedThreshold`. If you want to visualize the mesh, subscribe to this event. | - -An `ARPointCloud` has the following event: - -| Event | Description | -|-|-| -| `updated` | Invoked when the point cloud is updated. | - -An `ARReferencePoint` has the following event: - -| Event | Description | -|-|-| -| `updated` | Invoked when the reference point's `Pose` or `TrackingState` changes. | - -#### ARPlaneMeshVisualizer - -To visualize planes, you'll need to create a prefab or `GameObject` which includes a component that subscribes to `ARPlane`'s `updated` or `boundaryChanged` event. `ARFoundation` includes such a component: `ARPlaneMeshVisualizer`. This component will generate a `Mesh` from the boundary vertices and assign it to a `MeshCollider`, `MeshFilter`, and `LineRenderer`, if present. - -There is a new menu item `GameObject > XR > AR Default Plane` which will create a new `GameObject` which you can use to create your prefab. - -![alt text](images/ar_default_plane.png "AR Default Plane") - -Once created, you should assign it to the `ARPlaneManager`'s `Plane Prefab` field. You can use it directly or create a prefab by dragging the `GameObject` into your Assets folder. It is recommended to save the `AR Default Plane` as a prefab first, delete the `AR Default Plane` GameObject, and then use that in the prefab field as leaving the plane in your scene will leave a zero scale plane artifact in the scene. - -![alt text](images/ar_default_plane_as_prefab.png "AR Default Plane Prefab") - -There is a similar menu item for point cloud visualization. - -These components are included for ease of use, but you may wish to create your own visualizers (or other logic) as you see fit. - -## Raycasting - -Also known as hit testing, raycasting allows you to determine where a ray (defined by an origin and direction) intersects with a trackable. The current raycast interface only tests against planes and points in the point cloud. The raycasting interface is similar to the one in the Physics module, but since AR trackables may not necessarily have a presence in the physics world, we provide a separate interface. - -The raycasting interface is on the `ARSessionOrigin`. This is because only the `ARSessionOrigin` can transform the raycast results from session space to Unity world space. There are two raycasting methods on the `ARSessionOrigin`: - -```csharp -public bool Raycast(Vector3 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All); -public bool Raycast(Ray ray, List hitResults, TrackableType trackableTypeMask = TrackableType.All, float pointCloudRaycastAngleInDegrees = 5f); -``` - -The first method takes a two dimensional position on the screen. You can, for example, pass a touch position directly: - -```csharp -rig.Raycast(Input.GetTouch(0).position, ...); -``` - -The second method takes an arbitrary `Ray` (a position and direction). - -The following table summarizes the other parameters: - -| Parameter | Description | -|-|-| -| `hitResults` | The results for both methods are stored in this `List`, which must not be `null` (this lets you reuse the same `List` object to avoid garbage-collected allocations). | -| `trackableTypeMask` | The type(s) of trackable(s) to hit test against. This is a flag, so multiple types can be bitwise OR'd together, e.g., `TrackableType.PlaneWithinPolygon` | `FeaturePoint` | -| `pointCloudRaycastAngleInDegrees` | Because feature points have no volume, a cone is used when casting against feature points instead of an infinitely thin ray. This parameter controls the width of the cone. | - -## Face Tracking - -See [Face Tracking Documentation](face-tracking.md). - -# Technical details -## Requirements - -This version of AR Foundation is compatible with the following versions of the Unity Editor: - -* 2018.1 and later (recommended) - -## Known limitations - -AR Foundation includes the following known limitations: - -* No known issues - -## Document revision history - -|Date|Reason| -|---|---| -|November 15, 2018|Face Tracking added.| -|July 25, 2018|Update `ARCameraBackground` image and description following refactor.
Add howto section for blitting the camera image to a render texture.| -|July 16, 2018|Additional explanation for `ARSessionOrigin`| -|June 14, 2018|Update `ARSessionOrigin` photos| -|June 12, 2018|Update `ARPlaneMeshVisualizer` and `ARPointCloudMeshVisualizer` with additional debug recommendations and standards.| -|June 7, 2018|Remove known issue.| -|June 6, 2018|Update ARSession image.| -|April 25, 2018|Updated docs and screen shots after package rename.| -|April 19, 2018|Updated screen shots and information after code changes. Added section on `ARBackgroundRenderer` component. | -|April 10, 2018|Document created.| +# About AR Foundation + +AR Foundation allows you to work with augmented reality platforms in a multi-platform way within Unity. + +AR Foundation is a set of `MonoBehaviour`s for dealing with devices that support following concepts: +- Planar surface detection +- Point clouds, also known as feature points +- Reference points: an arbitrary position and orientation that the device tracks +- Light estimation: estimates for average color temperature and brightness in physical space. +- World tracking: tracking the device's position and orientation in physical space. + +If you are migrating from AR Foundation 1.0, see the [Migration Guide](migration-guide.md). + +# Installing AR Foundation + +To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html). + +AR Foundation is an interface for working with AR platforms, so you will also need to install at least one platform-specific AR package (*Window > Package Manager*): + + - ARKit XR Plugin + - ARCore XR Plugin + +# Glossary + +| Term | Meaning | +|-|-| +| Tracking | The ability of the AR device to determine its relative position and orientation in the world. If the environment is too dark, for example, the device may "lose tracking", which means it can no longer accurately report its position. | +| Trackable | A real-world feature detected and/or tracked by the AR device, e.g., a planar surface. | +| Feature Point | A specific point in a point cloud. AR devices use a camera and image analysis to track specific points in the world which are used to build a map of its environment. These are usually high frequency elements, such as a knot in a wood-grain surface.| +| Session | Refers to an AR instance. | +| Session Space | The coordinate system relative to the beginning of the AR session. For example, session space (0, 0, 0) refers to the position at which the AR session was created. An AR device typically reports trackables and tracking information relative to its session origin.| + +# Using AR Foundation + +## Basic Setup + +A basic AR scene hierarchy looks like this: + +![alt text](images/simple_scene_graph.png "Scene graph") + +You can create these automatically by right-clicking in the scene hiearachy and selecting *XR > AR Session* and *XR > AR Session Origin*. + +![alt text](images/gameobject_context_menu.png "Context menu") + +The required components are explained in more detail below. + +### ARSession +An AR scene should include an `ARSession` component. The AR Session controls the lifecycle of an AR experience, enabling or disabling AR on the target platform. The `ARSession` can be on any `GameObject`. + +![alt text](images/ar_session.png "ARSession component") + +If the `ARSession` is disabled, the system no longer tracks features in its environment, but if it is enabled at a later time, the system will attempt to recover and maintain previously detected features. + +If "Attempt Update" is checked, the device will try to install AR software if possible. Support for this feature is platform dependent. + +**Note:** An AR session is a global construct. An `ARSession` component manages this global session, so multiple `ARSession` components will all try to manage the same global session. + +#### Checking for Device Support + +Some platforms may support a limited subset of devices. On platforms where this is true, you need to be able to detect support for AR Foundation so that you may provide an alternative experience when AR is not supported. + +The `ARSession` component has a static coroutine that you can use to determine whether AR is supported at runtime: + +```csharp +public class MyComponent { + [SerializeField] ARSession m_Session; + + IEnumerator Start() { + if ((ARSession.state == ARSessionState.None ||) + (ARSession.state == ARSessionState.CheckingAvailability)) + { + yield return ARSession.CheckAvailability(); + } + + if (ARSession.state == ARSessionState.Unsupported) + { + // Start some fallback experience for unsupported devices + } + else + { + // Start the AR session + m_Session.enabled = true; + } + } +} + +``` + +#### Session State + +To determine the current state of the session (for example, whether the device is supported, if AR software is being installed, and whether the session is working), use `ARSession.state`. You can also subscribe to an event when the session state changes: `ARSession.stateChanged`. + +|`ARSessionState`|Meaning| +|-|-| +|`None`|The AR System has not been initialized and availability is unknown.| +|`Unsupported`|AR is not supported on the current device.| +|`CheckingAvailability`|The system is checking the availability of AR on the current device.| +|`NeedsInstall`|AR is supported on the current device, but requires an additional install.| +|`Installing`|AR software is being installed| +|`Ready`|AR is supported and ready| +|`SessionInitialized`|An AR session is initializing (i.e., starting up). This usually means AR is working but has not gathered enough information about the environment| +|`SessionTracking`|An AR session is running and is tracking (i.e., the device is able to determine its position and orientation in the world).| + +### ARSessionOrigin + +![alt text](images/ar_session_origin.png "AR Session Origin") + +The purpose of the `ARSessionOrigin` is to transform trackable features (such as planar surfaces and feature points) into their final position, orientation, and scale in the Unity scene. Because AR devices provide their data in "session space", an unscaled space relative to the beginning of the AR session, the `ARSessionOrigin` performs the appropriate transformation into Unity space. + +This concept is similar to the difference between "model" or "local" space and world space when working with other assets in Unity. For instance, if you import a house asset from a DCC tool, then the door will have a position relative to the modeler's origin. This is commonly called "model space" or "local space". When it is instantiated in Unity, it will also have a world space, relative to Unity's origin. + +Likewise, trackables produced by an AR device, such as planes, are provided in "session space", relative to the device's coordinate system. When instantiated in Unity as `GameObject`s, they also have a world space. In order to instantiate them in the correct place, AR Foundation needs to know where the session origin should be in the Unity scene. + +The `ARSessionOrigin` also allows you to scale virtual content and apply an offset to the camera. If you are scaling or offseting the `ARSessionOrigin`, then its `Camera` should be a child of the `ARSessionOrigin`. Since the `Camera` is driven by the session, the `Camera` and detected trackables will move together in this setup. + +#### Scale + +To apply scale to the `ARSessionOrigin`, simply set its `transform`'s scale. This has the effect of scaling all the data coming from the device, including the `AR Camera`'s position and any detected trackables. Larger values will make AR content appear smaller, so, for example, a scale of 10 would make your content appear 10 times smaller, while 0.1 would make your content appear 10 times larger. + +### TrackedPoseDriver + +Parented to the `ARSessionOrigin`'s' `GameObject` should be (at least) one camera, which will be used to render any trackables you wish to visualize. The camera should also have a `TrackedPoseDriver` component on it, which will drive the camera's local position and rotation according to the device's tracking information. This setup allows the camera's local space to match the AR "session space". + +![alt text](images/tracked_pose_driver.png "TrackedPoseDriver") + +The `Camera` must be a child of the `ARSessionOrigin`. + +### ARCameraManager + +The `ARCameraManager` enables camera features, such as textures representing the video feed and controls light estimation modes. + +![alt text](images/ar_camera_manager.png "ARCameraManager") + +| Option | Meaning | +|-|-| +| Focus Mode | May be "Auto" or "Fixed". "Auto" enables the hardware camera's automatic focus mode, while "fixed" disables it (the focus is "fixed" and does not change automatically). | +| Light Estimation | May be "Disabled" or "Ambient intensity". If not disabled, this instructs the platform to produce light estimation information, estimating the average light intensity and color in the physical environment. This can have an impact on performance, so disable it if you are not using it. | + +### ARCameraBackground + +If you want to render the device's color camera texture to the background, you need to add an `ARCameraBackground` component to a camera. This will subscribe to AR camera events and blit the camera texture to the screen. This is not required, but common for AR apps. + +![alt text](images/ar_camera_background.png "ARCameraBackground") + +The `Custom Material` property is optional, and typically you do not need to set it. The platform-specific packages provided by Unity (e.g., `ARCore` and `ARKit`) provide their own shaders for background rendering. + +If `Use Custom Material` is `true`, then the `ARCameraBackground` will use the `Material` you specify for background rendering. + +If you have exactly one `ARSessionOrigin`, then you can simply add the `ARCameraBackground` to that camera. If you have multiple `ARSessionOrigin`s (to selectively render different content at different scales, for instance), you should use separate cameras for each `ARSessionOrigin` and a separate, single camera for the `ARCameraBackground`. + +#### Copying the Camera Texture to a Render Texture + +The camera textures are likely [External Textures](https://docs.unity3d.com/ScriptReference/Texture2D.CreateExternalTexture.html) and may not last beyond a frame boundary. It can be useful to copy the camera image to a [Render Texture](https://docs.unity3d.com/Manual/class-RenderTexture.html) for persistence or further processing. This code will blit the camera image to a render texture of your choice: + +```csharp +Graphics.Blit(null, m_MyRenderTexture, m_ARBackgroundCamera.material); +``` + +### Trackable Managers + +The `ARSessionOrigin`'s' `GameObject` can also have a number of additional components on it, which manage the addition, updating, and removal of `GameObject`s to represent planes, point cloud, and reference points. These are the `ARPlaneManager`, `ARPointCloudManager`, and `ARReferencePointManager`, respectively, which each manager a single type of trackable: + +![alt text](images/ar_session_origin_with_managers.png "AR Session Origin with Managers") + +Each manager creates `GameObject`s for each detected trackable. The generated `GameObject`s are parented to a special `GameObject` under the `ARSessionOrigin`, accessible via `ARSessionOrigin.trackablesParent`. + +Each manager also accepts an optional prefab, which will be instantiated to represent the trackable. If no prefab is specified, a `GameObject` is created with an appropriate trackable component: + +| Trackable Manager | Trackable | +|---------------------------|---------------------| +| `ARPlaneManager` | `ARPlane` | +| `ARPointCloudManager` | `ARPointCloud` | +| `ARReferencePointManager` | `ARReferencePoint` | + +Each trackable component stores information about the trackable, but does not visualize it. Its `Transform` is updated by its manager whenever the AR device reports an update. + +Trackables can be enumerated via their manager with the `trackables` member, e.g., + +```csharp +var planeManager = GetComponent(); +foreach (ARPlane plane in planeManager.trackables) +{ + // Do something with the ARPlane +} +``` + +#### Events + +Each trackable manager has a single event which reports all added, updated, and removed trackables for that frame: + +| Trackable Manager | Event | +|-|-| +|`ARPlaneManager`| `planesChanged`| +|`ARPointCloudManager`|`pointCloudsChanged`| +|`ARReferencePointManager`|`referencePointsChanged`| + +Additionally, the `ARPlane` has a `boundaryChanged` event, which is invoked when the boundary points change by more than `ARPlane.vertexChangedThreshold`. + +### Visualizing Trackables + +The trackable components do not do anything on their own; they just contain data associated with each trackable. There are many ways to visualize the trackables, so AR Foundation includes some visualizers that can be used for debugging or as a starting point to create a visualizer suitable for your application. + +#### ARPlaneMeshVisualizer + +To visualize planes, you'll need to create a prefab or `GameObject` which includes a component that subscribes to `ARPlane`'s `boundaryChanged` event. `ARFoundation` provides an `ARPlaneMeshVisualizer`. This component will generate a `Mesh` from the boundary vertices and assign it to a `MeshCollider`, `MeshFilter`, and `LineRenderer`, if present. + +There is a menu item `GameObject > XR > AR Default Plane` which will create a new `GameObject` which you can use to create your prefab. + +![alt text](images/ar_default_plane.png "AR Default Plane") + +Once created, you should assign it to the `ARPlaneManager`'s `Plane Prefab` field. You can use it directly or create a prefab by dragging the `GameObject` into your Assets folder. It is recommended to save the `AR Default Plane` as a prefab first, delete the `AR Default Plane` GameObject, and then use that in the prefab field as leaving the plane in your scene will leave a zero scale plane artifact in the scene. + +![alt text](images/ar_default_plane_as_prefab.png "AR Default Plane Prefab") + +There is a similar menu item for point cloud visualization. + +These components are included for ease of use, but you may wish to create your own visualizers (or other logic) as you see fit. + +## Raycasting + +Also known as hit testing, raycasting allows you to determine where a ray (defined by an origin and direction) intersects with a trackable. The current raycast interface only tests against planes and points in the point cloud. The raycasting interface is similar to the one in the Unity Physics module, but since AR trackables may not necessarily have a presence in the physics world, AR Foundation provides a separate interface. + +To perform a raycast, add an `ARRaycastManager` to the same `GameObject` as the `ARSessionOrigin`. There are two raycasting methods on the `ARSessionOrigin`: + +```csharp +public bool Raycast(Vector2 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All); +public bool Raycast(Ray ray, List hitResults, TrackableType trackableTypeMask = TrackableType.All, float pointCloudRaycastAngleInDegrees = 5f); +``` + +The first method takes a two dimensional position on the screen. You can, for example, pass a touch position directly: + +```csharp +rig.Raycast(Input.GetTouch(0).position, ...); +``` + +The second method takes an arbitrary `Ray` (a position and direction). + +The following table summarizes the other parameters: + +| Parameter | Description | +|-|-| +| `hitResults` | The results for both methods are stored in this `List`, which must not be `null` (this lets you reuse the same `List` object to avoid garbage-collected allocations). | +| `trackableTypeMask` | The type(s) of trackable(s) to hit test against. This is a flag, so multiple types can be bitwise OR'd together, e.g., `TrackableType.PlaneWithinPolygon` | `FeaturePoint` | + +# Technical details +## Requirements + +This version of AR Foundation is compatible with the following versions of the Unity Editor: + +* 2019.2 and later + +## Known limitations + +AR Foundation includes the following known limitations: + +* No known issues + +## Document revision history + +|Date|Reason| +|---|---| +|March 4, 2019|Update documentation to reflect 2.0.0 changes.| +|November 15, 2018|Face Tracking added.| +|July 25, 2018|Update `ARCameraBackground` image and description following refactor.
Add howto section for blitting the camera image to a render texture.| +|July 16, 2018|Additional explanation for `ARSessionOrigin`| +|June 14, 2018|Update `ARSessionOrigin` photos| +|June 12, 2018|Update `ARPlaneMeshVisualizer` and `ARPointCloudMeshVisualizer` with additional debug recommendations and standards.| +|June 7, 2018|Remove known issue.| +|June 6, 2018|Update ARSession image.| +|April 25, 2018|Updated docs and screen shots after package rename.| +|April 19, 2018|Updated screen shots and information after code changes. Added section on `ARBackgroundRenderer` component. | +|April 10, 2018|Document created.| diff --git a/package/Documentation~/images/ar_session.png b/package/Documentation~/images/ar_session.png index b152b3243..bd92c3e44 100755 Binary files a/package/Documentation~/images/ar_session.png and b/package/Documentation~/images/ar_session.png differ diff --git a/package/Documentation~/images/ar_session_origin_with_managers.png b/package/Documentation~/images/ar_session_origin_with_managers.png index bac753776..b05377387 100755 Binary files a/package/Documentation~/images/ar_session_origin_with_managers.png and b/package/Documentation~/images/ar_session_origin_with_managers.png differ diff --git a/package/Documentation~/migration-guide.md b/package/Documentation~/migration-guide.md index efdc6c26c..28bf4211f 100755 --- a/package/Documentation~/migration-guide.md +++ b/package/Documentation~/migration-guide.md @@ -1,100 +1,100 @@ -# Migration Guide - -This will guide you through the changes coming from AR Foundation 1.0 - -## TL;DR - -* Add an `ARInputManager` anywhere in your scene. -* Add an `ARCameraManager` to your AR camera (this replaces the `ARCameraOptions`). -* Raycast via the `ARRaycastManager` instead of the `ARSessionOrigin` -* Some `TryGet`/`TryAdd`/`TryRemove` APIs were renamed to just `Get`/`Add`/`Remove` -* `GetAllXXX` is now a `trackables` property -* Added, update, and removed events have been combined into a single event that gives you lists of all the added, updated, and removed trackables. - -## Events - -In 1.0, each trackable manager provided added, updated, and removed events for each trackable. In 2.0, each trackable manager has a single event invoked no more than once per frame containing all the changes (added, updated, and removed) since the last frame. - -**Example:** - -| 1.0 | 2.0 | -|-|-| -| `ARPlaneManager.planeAdded`, `ARPlaneManager.planeUpdated`, `ARPlaneManager.planeRemoved` | `ARPlaneManager.planesChanged` | - -## Session Relative Data - -Many of the trackables in AR Foundation 1.0 had "session relative data", e.g., `BoundedPlane` and `XRReferencePoint`. These are no longer directly accessible; all their memebers are now properties of an AR Foundation trackable. - -**Example:** - -| Trackable | 1.0 accessor | 2.0 accessor | -|-|-|-| -|`ARPlane`|`boundedPlane.Id`|`trackableId`| - -## Removed Try - -Several APIs used a `TryGet` or `TryAdd` style of API. Such methods that dealt with reference types have dropped the `Try` prefix. - -**Examples:** - -| 1.0 | 2.0 | -|-|-| -| `ARPlane.TryGetPlane(trackableId)` | `ARPlane.GetPlane(trackableId)` | -| `ARReferencePoint.TryAddReferencePoint` | `ARReferencePoint.AddReferencePoint` | -| `ARReferencePoint.TryAttachReferencePoint` | `ARReferencePoint.AttachReferencePoint` | -| `bool ARReferencePoint.TryRemoveReferencePoint` | `bool ARReferencePoint.RemoveReferencePoint` | - -## Enumerating Trackables - -Trackable managers previously had a way to obtain a `List` of all trackables, e.g., `ARPlaneManager.GetAllPlanes` and `ARReferencePointManager.GetAllReferencePoints`. There is now a common property called `trackables`, which can be used in a `foreach`, e.g.: - -```csharp -var planeManager = GetComponent(); -foreach (var plane in planeManager.trackables) { - // Do something with the plane -} -``` - -This property returns a `TrackablesCollection` which does not generate any garbage or cause boxing. - -## ARSubsystemManager Removed - -The `ARSubsystemManager` has been removed in 2.0. It was previously a singleton which provided access to each of the "subsystems" (the low-level interface to the AR platform). However, some subsystems were also simultaneously managed by a `MonoBehavior`, e.g., `ARPlaneManager`. - -The led to confusion about which object to interact with or subscribe to. Now, each "subsystem" has a manager component which not only provides access to that subsystem, but also manages its lifetime. - -If you previously used the `ARSubsystemManager`, look for similar functionality on one of the managers: - -| 1.0 Subsystem | 2.0 Manager | -|-|-| -| `XRPlaneSubsystem` | `ARPlaneManager` | -| `XRReferencePointSubsystem` | `ARReferencePointManager` | -| `XRDepthSubsystem` | `ARPointCloudManager` | -| `XRSessionSubsystem` | `ARSession` | -| `XRInputSubsystem` | `ARInputManager` (new) | -| `XRCameraSubsystem` | `ARCameraManager` (new) | -| `XRRaycastSubsystem` | `ARRaycastManager` (new) | - -## ARInputManager - -Previously, pose tracking was implicitly always on. Now, you must have an `ARInputManager` component in your scene to enable it. It does not matter what `GameObject` this is on. - -The `ARInputManager` enables input tracking; the `TrackedPoseDriver` consumes pose data (as before). - -## ARCameraManager and ARCameraOptions - -The `ARCameraManager` enables the `XRCameraSubsystem`; without it, you will not be able to use background rendering or obtain light estimation information. This component should be placed on a Unity Camera, usually on the same one that is parented to the `ARSessionOrigin` and performs background rendering. - -The `ARCameraBackground` now requires an `ARCameraManager` component. - -The options that were previously on the `ARCameraOptions` component, like focus mode and light estimation mode, are now on the `ARCameraManager`. The `ARCameraOptions` no longer exists. - -## ARPointCloudManager - -In 1.0, the `ARPointCloudManager` managed a single point cloud. Now, it can manage a collection of them, similar to the way other trackable managers work. Some AR platforms, like ARCore and ARKit, still only have a single point cloud. However, other platforms (supported in the future) will generate multiple point clouds. - -As a result, the `ARPointCloudManager.pointCloud` property no longer exists. You can enumerate the point clouds like any other trackable manager, by iterating over its `trackables` property. - -## ARRaycastManager - -The raycasting API is the same as before, only now it is on a new component `ARRaycastManager`. Previously it was on the `ARSessionOrigin`. If you need to perform a raycast, make sure you have a `ARRaycastManager` on the same `GameObject` as the `ARSessionOrigin` and use the `Raycast` methods on that component. +# Migration Guide + +This will guide you through the changes coming from AR Foundation 1.0 + +## TL;DR + +* Add an `ARInputManager` anywhere in your scene. +* Add an `ARCameraManager` to your AR camera (this replaces the `ARCameraOptions`). +* Raycast via the `ARRaycastManager` instead of the `ARSessionOrigin` +* Some `TryGet`/`TryAdd`/`TryRemove` APIs were renamed to just `Get`/`Add`/`Remove` +* `GetAllXXX` is now a `trackables` property +* Added, update, and removed events have been combined into a single event that gives you lists of all the added, updated, and removed trackables. + +## Events + +In 1.0, each trackable manager provided added, updated, and removed events for each trackable. In 2.0, each trackable manager has a single event invoked no more than once per frame containing all the changes (added, updated, and removed) since the last frame. + +**Example:** + +| 1.0 | 2.0 | +|-|-| +| `ARPlaneManager.planeAdded`, `ARPlaneManager.planeUpdated`, `ARPlaneManager.planeRemoved` | `ARPlaneManager.planesChanged` | + +## Session Relative Data + +Many of the trackables in AR Foundation 1.0 had "session relative data", e.g., `BoundedPlane` and `XRReferencePoint`. These are no longer directly accessible; all their memebers are now properties of an AR Foundation trackable. + +**Example:** + +| Trackable | 1.0 accessor | 2.0 accessor | +|-|-|-| +|`ARPlane`|`boundedPlane.Id`|`trackableId`| + +## Removed Try + +Several APIs used a `TryGet` or `TryAdd` style of API. Such methods that dealt with reference types have dropped the `Try` prefix. + +**Examples:** + +| 1.0 | 2.0 | +|-|-| +| `ARPlane.TryGetPlane(trackableId)` | `ARPlane.GetPlane(trackableId)` | +| `ARReferencePoint.TryAddReferencePoint` | `ARReferencePoint.AddReferencePoint` | +| `ARReferencePoint.TryAttachReferencePoint` | `ARReferencePoint.AttachReferencePoint` | +| `bool ARReferencePoint.TryRemoveReferencePoint` | `bool ARReferencePoint.RemoveReferencePoint` | + +## Enumerating Trackables + +Trackable managers previously had a way to obtain a `List` of all trackables, e.g., `ARPlaneManager.GetAllPlanes` and `ARReferencePointManager.GetAllReferencePoints`. There is now a common property called `trackables`, which can be used in a `foreach`, e.g.: + +```csharp +var planeManager = GetComponent(); +foreach (var plane in planeManager.trackables) { + // Do something with the plane +} +``` + +This property returns a `TrackablesCollection` which does not generate any garbage or cause boxing. + +## ARSubsystemManager Removed + +The `ARSubsystemManager` has been removed in 2.0. It was previously a singleton which provided access to each of the "subsystems" (the low-level interface to the AR platform). However, some subsystems were also simultaneously managed by a `MonoBehavior`, e.g., `ARPlaneManager`. + +The led to confusion about which object to interact with or subscribe to. Now, each "subsystem" has a manager component which not only provides access to that subsystem, but also manages its lifetime. + +If you previously used the `ARSubsystemManager`, look for similar functionality on one of the managers: + +| 1.0 Subsystem | 2.0 Manager | +|-|-| +| `XRPlaneSubsystem` | `ARPlaneManager` | +| `XRReferencePointSubsystem` | `ARReferencePointManager` | +| `XRDepthSubsystem` | `ARPointCloudManager` | +| `XRSessionSubsystem` | `ARSession` | +| `XRInputSubsystem` | `ARInputManager` (new) | +| `XRCameraSubsystem` | `ARCameraManager` (new) | +| `XRRaycastSubsystem` | `ARRaycastManager` (new) | + +## ARInputManager + +Previously, pose tracking was implicitly always on. Now, you must have an `ARInputManager` component in your scene to enable it. It does not matter what `GameObject` this is on. + +The `ARInputManager` enables input tracking; the `TrackedPoseDriver` consumes pose data (as before). + +## ARCameraManager and ARCameraOptions + +The `ARCameraManager` enables the `XRCameraSubsystem`; without it, you will not be able to use background rendering or obtain light estimation information. This component should be placed on a Unity Camera, usually on the same one that is parented to the `ARSessionOrigin` and performs background rendering. + +The `ARCameraBackground` now requires an `ARCameraManager` component. + +The options that were previously on the `ARCameraOptions` component, like focus mode and light estimation mode, are now on the `ARCameraManager`. The `ARCameraOptions` no longer exists. + +## ARPointCloudManager + +In 1.0, the `ARPointCloudManager` managed a single point cloud. Now, it can manage a collection of them, similar to the way other trackable managers work. Some AR platforms, like ARCore and ARKit, still only have a single point cloud. However, other platforms (supported in the future) will generate multiple point clouds. + +As a result, the `ARPointCloudManager.pointCloud` property no longer exists. You can enumerate the point clouds like any other trackable manager, by iterating over its `trackables` property. + +## ARRaycastManager + +The raycasting API is the same as before, only now it is on a new component `ARRaycastManager`. Previously it was on the `ARSessionOrigin`. If you need to perform a raycast, make sure you have a `ARRaycastManager` on the same `GameObject` as the `ARSessionOrigin` and use the `Raycast` methods on that component. diff --git a/package/Editor.meta b/package/Editor.meta index f89bde014..94bedbcdc 100755 --- a/package/Editor.meta +++ b/package/Editor.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: d640407051394e845b5a2644547e9f7d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: d640407051394e845b5a2644547e9f7d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/ARCameraBackgroundEditor.cs b/package/Editor/ARCameraBackgroundEditor.cs index 7dd1300b6..b5a6f1c88 100755 --- a/package/Editor/ARCameraBackgroundEditor.cs +++ b/package/Editor/ARCameraBackgroundEditor.cs @@ -1,71 +1,71 @@ -using UnityEngine; -using UnityEngine.XR.ARFoundation; - -namespace UnityEditor.XR.ARFoundation -{ - [CustomEditor(typeof(ARCameraBackground))] - internal class ARCameraBackgroundEditor : Editor - { - SerializedProperty m_UseCustomMaterial; - - SerializedProperty m_CustomMaterial; - - SerializedProperty m_UseCustomRendererAsset; - - SerializedProperty m_CustomRendererAsset; - - static class Tooltips - { - public static readonly GUIContent useCustomMaterial = new GUIContent( - "Use Custom Material", - "When false, a material is generated automatically from the shader included in the platform-specific package. When true, the Custom Material is used instead, overriding the automatically generated one. This is not necessary for most AR experiences."); - - public static readonly GUIContent customMaterial = new GUIContent( - "Custom Material", - "The material to use for background rendering."); - - public static readonly GUIContent useCustomRendererAsset = new GUIContent( - "Use Custom Renderer Asset", - "When false, default background renderer is used. When true, the Custom Render Asset is used to generate a background renderer, overriding the default one."); - - public static readonly GUIContent customRendererAsset = new GUIContent( - "Custom Renderer Asset", - "The Render Asset to use to create background renderer."); - - - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_UseCustomMaterial, Tooltips.useCustomMaterial); - - if (m_UseCustomMaterial.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_CustomMaterial, Tooltips.customMaterial); - EditorGUI.indentLevel--; - } - - EditorGUILayout.PropertyField(m_UseCustomRendererAsset, Tooltips.useCustomRendererAsset); - - if (m_UseCustomRendererAsset.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_CustomRendererAsset, Tooltips.customRendererAsset); - EditorGUI.indentLevel--; - } - - serializedObject.ApplyModifiedProperties(); - } - - void OnEnable() - { - m_UseCustomMaterial = serializedObject.FindProperty("m_UseCustomMaterial"); - m_CustomMaterial = serializedObject.FindProperty("m_CustomMaterial"); - m_UseCustomRendererAsset = serializedObject.FindProperty("m_UseCustomRendererAsset"); - m_CustomRendererAsset = serializedObject.FindProperty("m_CustomRendererAsset"); - } - } -} +using UnityEngine; +using UnityEngine.XR.ARFoundation; + +namespace UnityEditor.XR.ARFoundation +{ + [CustomEditor(typeof(ARCameraBackground))] + internal class ARCameraBackgroundEditor : Editor + { + SerializedProperty m_UseCustomMaterial; + + SerializedProperty m_CustomMaterial; + + SerializedProperty m_UseCustomRendererAsset; + + SerializedProperty m_CustomRendererAsset; + + static class Tooltips + { + public static readonly GUIContent useCustomMaterial = new GUIContent( + "Use Custom Material", + "When false, a material is generated automatically from the shader included in the platform-specific package. When true, the Custom Material is used instead, overriding the automatically generated one. This is not necessary for most AR experiences."); + + public static readonly GUIContent customMaterial = new GUIContent( + "Custom Material", + "The material to use for background rendering."); + + public static readonly GUIContent useCustomRendererAsset = new GUIContent( + "Use Custom Renderer Asset", + "When false, default background renderer is used. When true, the Custom Render Asset is used to generate a background renderer, overriding the default one."); + + public static readonly GUIContent customRendererAsset = new GUIContent( + "Custom Renderer Asset", + "The Render Asset to use to create background renderer."); + + + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUILayout.PropertyField(m_UseCustomMaterial, Tooltips.useCustomMaterial); + + if (m_UseCustomMaterial.boolValue) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(m_CustomMaterial, Tooltips.customMaterial); + EditorGUI.indentLevel--; + } + + EditorGUILayout.PropertyField(m_UseCustomRendererAsset, Tooltips.useCustomRendererAsset); + + if (m_UseCustomRendererAsset.boolValue) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(m_CustomRendererAsset, Tooltips.customRendererAsset); + EditorGUI.indentLevel--; + } + + serializedObject.ApplyModifiedProperties(); + } + + void OnEnable() + { + m_UseCustomMaterial = serializedObject.FindProperty("m_UseCustomMaterial"); + m_CustomMaterial = serializedObject.FindProperty("m_CustomMaterial"); + m_UseCustomRendererAsset = serializedObject.FindProperty("m_UseCustomRendererAsset"); + m_CustomRendererAsset = serializedObject.FindProperty("m_CustomRendererAsset"); + } + } +} diff --git a/package/Editor/ARCameraBackgroundEditor.cs.meta b/package/Editor/ARCameraBackgroundEditor.cs.meta index 1ba79149c..b6a79eb34 100755 --- a/package/Editor/ARCameraBackgroundEditor.cs.meta +++ b/package/Editor/ARCameraBackgroundEditor.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: ee9af0c78ce605749ba0185801851bb3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: ee9af0c78ce605749ba0185801851bb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/ARSceneValidator.cs b/package/Editor/ARSceneValidator.cs index 29e7c1382..884998dce 100755 --- a/package/Editor/ARSceneValidator.cs +++ b/package/Editor/ARSceneValidator.cs @@ -1,71 +1,71 @@ -using System; -using System.Collections.Generic; -using UnityEngine.SceneManagement; -using UnityEngine; -using UnityEditor.Callbacks; -using UnityEngine.XR.ARFoundation; - -namespace UnityEditor.XR.ARFoundation -{ - internal class ARSceneValidator - { - [PostProcessBuild] - static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) - { - if (s_ScenesWithARTypes.Count > 0 && s_SessionCount == 0) - { - var scenes = ""; - foreach(var sceneName in s_ScenesWithARTypes) - { - scenes += string.Format("\n\t{0}", sceneName); - } - - Debug.LogWarningFormat( - "The following scenes contain AR components but no ARSession. The ARSession component controls the AR lifecycle, so these components will not do anything at runtime. Was this intended?{0}", - scenes); - } - - s_ScenesWithARTypes.Clear(); - s_SessionCount = 0; - } - - [PostProcessScene] - static void OnPostProcessScene() - { - if (sceneContainsARTypes) - s_ScenesWithARTypes.Add(SceneManager.GetActiveScene().name); - - s_SessionCount += UnityEngine.Object.FindObjectsOfType().Length; - } - - static bool sceneContainsARTypes - { - get - { - foreach (var type in k_ARTypes) - { - foreach (var component in UnityEngine.Object.FindObjectsOfType(type)) - { - var monobehaviour = component as MonoBehaviour; - if (monobehaviour != null && monobehaviour.enabled) - return true; - } - } - - return false; - } - } - - static List s_ScenesWithARTypes = new List(); - - static int s_SessionCount; - - static readonly Type[] k_ARTypes = new Type[] - { - typeof(ARCameraBackground), - typeof(ARPlaneManager), - typeof(ARPointCloudManager), - typeof(ARReferencePointManager) - }; - } -} +using System; +using System.Collections.Generic; +using UnityEngine.SceneManagement; +using UnityEngine; +using UnityEditor.Callbacks; +using UnityEngine.XR.ARFoundation; + +namespace UnityEditor.XR.ARFoundation +{ + internal class ARSceneValidator + { + [PostProcessBuild] + static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) + { + if (s_ScenesWithARTypes.Count > 0 && s_SessionCount == 0) + { + var scenes = ""; + foreach(var sceneName in s_ScenesWithARTypes) + { + scenes += string.Format("\n\t{0}", sceneName); + } + + Debug.LogWarningFormat( + "The following scenes contain AR components but no ARSession. The ARSession component controls the AR lifecycle, so these components will not do anything at runtime. Was this intended?{0}", + scenes); + } + + s_ScenesWithARTypes.Clear(); + s_SessionCount = 0; + } + + [PostProcessScene] + static void OnPostProcessScene() + { + if (sceneContainsARTypes) + s_ScenesWithARTypes.Add(SceneManager.GetActiveScene().name); + + s_SessionCount += UnityEngine.Object.FindObjectsOfType().Length; + } + + static bool sceneContainsARTypes + { + get + { + foreach (var type in k_ARTypes) + { + foreach (var component in UnityEngine.Object.FindObjectsOfType(type)) + { + var monobehaviour = component as MonoBehaviour; + if (monobehaviour != null && monobehaviour.enabled) + return true; + } + } + + return false; + } + } + + static List s_ScenesWithARTypes = new List(); + + static int s_SessionCount; + + static readonly Type[] k_ARTypes = new Type[] + { + typeof(ARCameraBackground), + typeof(ARPlaneManager), + typeof(ARPointCloudManager), + typeof(ARReferencePointManager) + }; + } +} diff --git a/package/Editor/ARSceneValidator.cs.meta b/package/Editor/ARSceneValidator.cs.meta index 67b50bbd4..ec0c03362 100755 --- a/package/Editor/ARSceneValidator.cs.meta +++ b/package/Editor/ARSceneValidator.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: f674d8841b5c74e4791c6f1c90888637 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: f674d8841b5c74e4791c6f1c90888637 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/Icons.meta b/package/Editor/Icons.meta index 80dcc7e11..e8e03db66 100755 --- a/package/Editor/Icons.meta +++ b/package/Editor/Icons.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 366b943182f744abca717ffdf2049625 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 366b943182f744abca717ffdf2049625 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/Icons/AR_Icon@4x.png.meta b/package/Editor/Icons/AR_Icon@4x.png.meta index 2626476a9..95ff6f09f 100755 --- a/package/Editor/Icons/AR_Icon@4x.png.meta +++ b/package/Editor/Icons/AR_Icon@4x.png.meta @@ -1,88 +1,88 @@ -fileFormatVersion: 2 -guid: c78afcd92a9a33748b02af87f8c94208 -TextureImporter: - fileIDToRecycleName: {} - externalObjects: {} - serializedVersion: 7 - mipmaps: - mipMapMode: 0 - enableMipMap: 1 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: -1 - aniso: -1 - mipBias: -100 - wrapU: -1 - wrapV: -1 - wrapW: -1 - nPOTScale: 1 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 0 - spriteTessellationDetail: -1 - textureType: 0 - textureShape: 1 - singleChannelComponent: 0 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - platformSettings: - - serializedVersion: 2 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: - vertices: [] - indices: - edges: [] - weights: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: c78afcd92a9a33748b02af87f8c94208 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 7 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/PlaneDetectionModeAttributeDrawer.cs b/package/Editor/PlaneDetectionModeAttributeDrawer.cs index 5765f135a..789130fd0 100755 --- a/package/Editor/PlaneDetectionModeAttributeDrawer.cs +++ b/package/Editor/PlaneDetectionModeAttributeDrawer.cs @@ -1,27 +1,27 @@ -using UnityEngine; -using UnityEngine.XR.ARFoundation; - -namespace UnityEditor.XR.ARFoundation -{ - /// - /// A custom property drawer for the PlaneDetectionMode enum. - /// - [CustomPropertyDrawer(typeof(PlaneDetectionModeMaskAttribute))] - class PlaneDetectionModeMaskAttributeDrawer : PropertyDrawer - { - string[] m_EnumNames; - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - // Remove the "None" option - if (m_EnumNames == null) - { - m_EnumNames = new string[property.enumNames.Length - 1]; - for (int i = 1; i < property.enumNames.Length; ++i) - m_EnumNames[i - 1] = property.enumNames[i]; - } - - property.intValue = EditorGUI.MaskField(position, label, property.intValue, m_EnumNames); - } - } -} +using UnityEngine; +using UnityEngine.XR.ARFoundation; + +namespace UnityEditor.XR.ARFoundation +{ + /// + /// A custom property drawer for the PlaneDetectionMode enum. + /// + [CustomPropertyDrawer(typeof(PlaneDetectionModeMaskAttribute))] + class PlaneDetectionModeMaskAttributeDrawer : PropertyDrawer + { + string[] m_EnumNames; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Remove the "None" option + if (m_EnumNames == null) + { + m_EnumNames = new string[property.enumNames.Length - 1]; + for (int i = 1; i < property.enumNames.Length; ++i) + m_EnumNames[i - 1] = property.enumNames[i]; + } + + property.intValue = EditorGUI.MaskField(position, label, property.intValue, m_EnumNames); + } + } +} diff --git a/package/Editor/PlaneDetectionModeAttributeDrawer.cs.meta b/package/Editor/PlaneDetectionModeAttributeDrawer.cs.meta index f7ccfeb55..8acf857ee 100755 --- a/package/Editor/PlaneDetectionModeAttributeDrawer.cs.meta +++ b/package/Editor/PlaneDetectionModeAttributeDrawer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: bf3bd492997dd7d4c98efa9c5727705d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: bf3bd492997dd7d4c98efa9c5727705d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/SceneUtils.cs b/package/Editor/SceneUtils.cs index 13aae19a7..e9418a7a8 100755 --- a/package/Editor/SceneUtils.cs +++ b/package/Editor/SceneUtils.cs @@ -1,122 +1,109 @@ -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.XR.ARFoundation; -using UnityEngine.SpatialTracking; - -namespace UnityEditor.XR.ARFoundation -{ - internal static class SceneUtils - { - static readonly string k_DebugFaceMaterial = "Packages/com.unity.xr.arfoundation/Materials/DebugFace.mat"; - - static readonly string k_DebugPlaneMaterial = "Packages/com.unity.xr.arfoundation/Materials/DebugPlane.mat"; - - static readonly string k_ParticleMaterial = "Default-Particle.mat"; - - static readonly string k_LineMaterial = "Default-Line.mat"; - - static readonly Color k_ParticleColor = new Color(253f / 255f, 184f / 255f, 19f / 255f); - - static readonly float k_ParticleSize = 0.02f; - - [MenuItem("GameObject/XR/AR Session Origin", false, 10)] - static void CreateARSessionOrigin() - { - var originGo = ObjectFactory.CreateGameObject("AR Session Origin", typeof(ARSessionOrigin)); - var cameraGo = ObjectFactory.CreateGameObject("AR Camera", - typeof(Camera), typeof(TrackedPoseDriver), typeof(ARCameraBackground)); - - Undo.SetTransformParent(cameraGo.transform, originGo.transform, "Parent camera to session origin"); - - var camera = cameraGo.GetComponent(); - camera.clearFlags = CameraClearFlags.Color; - camera.backgroundColor = Color.black; - camera.nearClipPlane = 0.1f; - camera.farClipPlane = 20f; - - var origin = originGo.GetComponent(); - origin.camera = camera; - - var tpd = cameraGo.GetComponent(); - tpd.SetPoseSource(TrackedPoseDriver.DeviceType.GenericXRDevice, TrackedPoseDriver.TrackedPose.ColorCamera); - } - - [MenuItem("GameObject/XR/AR Session", false, 10)] - static void CreateARSession() - { - ObjectFactory.CreateGameObject("AR Session", typeof(ARSession)); - } - - [MenuItem("GameObject/XR/AR Default Point Cloud", false, 10)] - static void CreateARPointCloudVisualizer() - { - var go = ObjectFactory.CreateGameObject("AR Default Point Cloud", - typeof(ARPointCloudParticleVisualizer)); - var particleSystem = go.GetComponent(); - UnityEditorInternal.ComponentUtility.MoveComponentDown(particleSystem); - UnityEditorInternal.ComponentUtility.MoveComponentDown(particleSystem); - var main = particleSystem.main; - main.loop = false; - main.startSize = k_ParticleSize; - main.startColor = k_ParticleColor; - main.scalingMode = ParticleSystemScalingMode.Hierarchy; - main.playOnAwake = false; - - var emission = particleSystem.emission; - emission.enabled = false; - - var shape = particleSystem.shape; - shape.enabled = false; - - var renderer = particleSystem.GetComponent(); - renderer.material = AssetDatabase.GetBuiltinExtraResource(k_ParticleMaterial); - } - - [MenuItem("GameObject/XR/AR Default Plane", false, 10)] - static void CreateARPlaneVisualizer() - { - var go = ObjectFactory.CreateGameObject("AR Default Plane", - typeof(ARPlaneMeshVisualizer), typeof(MeshCollider), typeof(MeshFilter), - typeof(MeshRenderer), typeof(LineRenderer)); - SetupMeshRenderer(go.GetComponent(), k_DebugPlaneMaterial); - SetupLineRenderer(go.GetComponent()); - } - - [MenuItem("GameObject/XR/AR Default Face", false, 10)] - static void CreateARFaceVisualizer() - { - var go = ObjectFactory.CreateGameObject("AR Default Face", - typeof(ARFaceMeshVisualizer), typeof(MeshCollider), typeof(MeshFilter), - typeof(MeshRenderer)); - var meshRenderer = go.GetComponent(); - SetupMeshRenderer(meshRenderer, k_DebugFaceMaterial); - //self shadowing doesn't look good on the default face - meshRenderer.receiveShadows = false; - meshRenderer.shadowCastingMode = ShadowCastingMode.Off; - } - - static void SetupLineRenderer(LineRenderer lineRenderer) - { - var materials = new Material[1]; - materials[0] = AssetDatabase.GetBuiltinExtraResource(k_LineMaterial); - lineRenderer.materials = materials; - lineRenderer.loop = true; - var curve = new AnimationCurve(); - curve.AddKey(0f, 0.005f); - lineRenderer.widthCurve = curve; - lineRenderer.startColor = Color.black; - lineRenderer.endColor = Color.black; - lineRenderer.numCornerVertices = 4; - lineRenderer.numCapVertices = 4; - lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - lineRenderer.receiveShadows = false; - lineRenderer.useWorldSpace = false; - } - - static void SetupMeshRenderer(MeshRenderer meshRenderer, string materialName) - { - var material = AssetDatabase.LoadAssetAtPath(materialName); - meshRenderer.materials = new Material[] { material }; - } - } -} +using UnityEngine; +using UnityEngine.SpatialTracking; +using UnityEngine.XR.ARFoundation; + +namespace UnityEditor.XR.ARFoundation +{ + internal static class SceneUtils + { + static readonly string k_DebugPlaneMaterial = "Packages/com.unity.xr.arfoundation/Materials/DebugPlane.mat"; + + static readonly string k_ParticleMaterial = "Default-Particle.mat"; + + static readonly string k_LineMaterial = "Default-Line.mat"; + + static readonly Color k_ParticleColor = new Color(253f / 255f, 184f / 255f, 19f / 255f); + + static readonly float k_ParticleSize = 0.02f; + + [MenuItem("GameObject/XR/AR Session Origin", false, 10)] + static void CreateARSessionOrigin() + { + var originGo = ObjectFactory.CreateGameObject("AR Session Origin", typeof(ARSessionOrigin)); + var cameraGo = ObjectFactory.CreateGameObject("AR Camera", + typeof(Camera), + typeof(TrackedPoseDriver), + typeof(ARCameraManager), + typeof(ARCameraBackground)); + + Undo.SetTransformParent(cameraGo.transform, originGo.transform, "Parent camera to session origin"); + + var camera = cameraGo.GetComponent(); + camera.clearFlags = CameraClearFlags.Color; + camera.backgroundColor = Color.black; + camera.nearClipPlane = 0.1f; + camera.farClipPlane = 20f; + + var origin = originGo.GetComponent(); + origin.camera = camera; + + var tpd = cameraGo.GetComponent(); + tpd.SetPoseSource(TrackedPoseDriver.DeviceType.GenericXRDevice, TrackedPoseDriver.TrackedPose.ColorCamera); + } + + [MenuItem("GameObject/XR/AR Session", false, 10)] + static void CreateARSession() + { + ObjectFactory.CreateGameObject("AR Session", typeof(ARSession), typeof(ARInputManager)); + } + + [MenuItem("GameObject/XR/AR Default Point Cloud", false, 10)] + static void CreateARPointCloudVisualizer() + { + var go = ObjectFactory.CreateGameObject("AR Default Point Cloud", + typeof(ARPointCloudParticleVisualizer)); + var particleSystem = go.GetComponent(); + UnityEditorInternal.ComponentUtility.MoveComponentDown(particleSystem); + UnityEditorInternal.ComponentUtility.MoveComponentDown(particleSystem); + var main = particleSystem.main; + main.loop = false; + main.startSize = k_ParticleSize; + main.startColor = k_ParticleColor; + main.scalingMode = ParticleSystemScalingMode.Hierarchy; + main.playOnAwake = false; + + var emission = particleSystem.emission; + emission.enabled = false; + + var shape = particleSystem.shape; + shape.enabled = false; + + var renderer = particleSystem.GetComponent(); + renderer.material = AssetDatabase.GetBuiltinExtraResource(k_ParticleMaterial); + } + + [MenuItem("GameObject/XR/AR Default Plane", false, 10)] + static void CreateARPlaneVisualizer() + { + var go = ObjectFactory.CreateGameObject("AR Default Plane", + typeof(ARPlaneMeshVisualizer), typeof(MeshCollider), typeof(MeshFilter), + typeof(MeshRenderer), typeof(LineRenderer)); + SetupMeshRenderer(go.GetComponent(), k_DebugPlaneMaterial); + SetupLineRenderer(go.GetComponent()); + } + + static void SetupLineRenderer(LineRenderer lineRenderer) + { + var materials = new Material[1]; + materials[0] = AssetDatabase.GetBuiltinExtraResource(k_LineMaterial); + lineRenderer.materials = materials; + lineRenderer.loop = true; + var curve = new AnimationCurve(); + curve.AddKey(0f, 0.005f); + lineRenderer.widthCurve = curve; + lineRenderer.startColor = Color.black; + lineRenderer.endColor = Color.black; + lineRenderer.numCornerVertices = 4; + lineRenderer.numCapVertices = 4; + lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + lineRenderer.receiveShadows = false; + lineRenderer.useWorldSpace = false; + } + + static void SetupMeshRenderer(MeshRenderer meshRenderer, string materialName) + { + var material = AssetDatabase.LoadAssetAtPath(materialName); + meshRenderer.materials = new Material[] { material }; + } + } +} diff --git a/package/Editor/SceneUtils.cs.meta b/package/Editor/SceneUtils.cs.meta index b4b616e1b..a1beacd93 100755 --- a/package/Editor/SceneUtils.cs.meta +++ b/package/Editor/SceneUtils.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 6422827c20034724a804803686698524 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 6422827c20034724a804803686698524 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/Unity.XR.ARFoundation.Editor.asmdef b/package/Editor/Unity.XR.ARFoundation.Editor.asmdef index 47556029f..f75313b3d 100755 --- a/package/Editor/Unity.XR.ARFoundation.Editor.asmdef +++ b/package/Editor/Unity.XR.ARFoundation.Editor.asmdef @@ -1,11 +1,19 @@ -{ - "name": "Unity.XR.ARFoundation.Editor", - "references": [ - "UnityEngine.SpatialTracking", - "Unity.XR.ARFoundation" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [] -} +{ + "name": "Unity.XR.ARFoundation.Editor", + "references": [ + "UnityEngine.SpatialTracking", + "Unity.XR.ARFoundation", + "Unity.XR.ARSubsystems" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [] +} \ No newline at end of file diff --git a/package/Editor/Unity.XR.ARFoundation.Editor.asmdef.meta b/package/Editor/Unity.XR.ARFoundation.Editor.asmdef.meta index ea62c2f6e..a40bc0643 100755 --- a/package/Editor/Unity.XR.ARFoundation.Editor.asmdef.meta +++ b/package/Editor/Unity.XR.ARFoundation.Editor.asmdef.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 7f759c464cb5ea8448d441f13b57aec0 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 7f759c464cb5ea8448d441f13b57aec0 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/LICENSE.md b/package/LICENSE.md index ce2014561..5dfe7ca06 100755 --- a/package/LICENSE.md +++ b/package/LICENSE.md @@ -1,5 +1,5 @@ -AR Foundation copyright © 2018 Unity Technologies ApS - -Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). - +AR Foundation copyright © 2018 Unity Technologies ApS + +Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). + Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. \ No newline at end of file diff --git a/package/LICENSE.md.meta b/package/LICENSE.md.meta index ed7afba16..b7940e0c4 100755 --- a/package/LICENSE.md.meta +++ b/package/LICENSE.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: ac10132e358b28947a35981268d3ca57 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: ac10132e358b28947a35981268d3ca57 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Materials.meta b/package/Materials.meta index 6071f36f8..7ee738c91 100755 --- a/package/Materials.meta +++ b/package/Materials.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: e6b8dc4e2997217428ebdd00450ce884 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: e6b8dc4e2997217428ebdd00450ce884 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Materials/DebugFace.mat b/package/Materials/DebugFace.mat index 557e74f77..2f9abad20 100755 --- a/package/Materials/DebugFace.mat +++ b/package/Materials/DebugFace.mat @@ -1,77 +1,77 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: DebugFace - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _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} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.406 - - _GlossyReflections: 0 - - _Metallic: 0.216 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.7975305, g: 0.99215686, b: 0.0745098, a: 0.2509804} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DebugFace + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _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} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.406 + - _GlossyReflections: 0 + - _Metallic: 0.216 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.7975305, g: 0.99215686, b: 0.0745098, a: 0.2509804} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/package/Materials/DebugFace.mat.meta b/package/Materials/DebugFace.mat.meta index 38184e815..cd58ddaf2 100755 --- a/package/Materials/DebugFace.mat.meta +++ b/package/Materials/DebugFace.mat.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 35bd980c8f2234e3d8b640e25a677d65 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 35bd980c8f2234e3d8b640e25a677d65 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Materials/DebugPlane.mat b/package/Materials/DebugPlane.mat index 0bbb5bfee..b12260cdb 100755 --- a/package/Materials/DebugPlane.mat +++ b/package/Materials/DebugPlane.mat @@ -1,77 +1,77 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: DebugPlane - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHAPREMULTIPLY_ON - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 - stringTagMap: - RenderType: Transparent - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _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} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 10 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 3 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 0 - m_Colors: - - _Color: {r: 0.99215686, g: 0.72156864, b: 0.07450981, a: 0.2509804} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: DebugPlane + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHAPREMULTIPLY_ON + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _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} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _Color: {r: 0.99215686, g: 0.72156864, b: 0.07450981, a: 0.2509804} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/package/Materials/DebugPlane.mat.meta b/package/Materials/DebugPlane.mat.meta index bd6126850..7f7a80962 100755 --- a/package/Materials/DebugPlane.mat.meta +++ b/package/Materials/DebugPlane.mat.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: f1a110d32af21aa4d872c707dfcc6043 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: f1a110d32af21aa4d872c707dfcc6043 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/README.md b/package/README.md index 5d8f3d19b..3a8a1cefb 100755 --- a/package/README.md +++ b/package/README.md @@ -1,22 +1,14 @@ -# AR Foundation - -Use the AR Foundation package to add high-level functionality for working with augmented reality. Unity 2018.1 includes built-in multi-platform support for AR. These APIs are in the `UnityEngine.Experimental.XR` namespace, and consist of a number of `Subsystem`s, e.g., `XRPlaneSubsystem`. Several XR Subsystems comprise the low-level API for interacting with AR. The **AR Foundation** package wraps this low-level API into a cohesive whole and enhances it with additional utilities, such as AR session lifecycle management and the creation of `GameObject`s to represent detected features in the environment. - -AR Foundation is a set of utilities for dealing with devices that support following concepts: -- Planar surface detection -- Point clouds, aka feature points -- Reference points: an arbitrary position and orientation that the device tracks -- Light estimation: estimates for average color temperature and brightness in physical space. -- World tracking: tracking the device's position and orientation in physical space. -- Face tracking: tracking the position and orientation of the face of a person. - -## Installing AR Foundation - -To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html). - -This package is `com.unity.xr.arfoundation` - -## Documentation - -* [Script API](Runtime/AR/) -* [Manual](Documentation/com.unity.xr.arfoundation.md) +# AR Foundation + +Use the AR Foundation package to add high-level functionality for working with augmented reality. Unity 2018.1 includes built-in multi-platform support for AR. These APIs are in the `UnityEngine.XR.ARSubsystems` namespace, and consist of a number of `Subsystem`s, e.g., `XRPlaneSubsystem`. Several XR Subsystems comprise the low-level API for interacting with AR. The **AR Foundation** package wraps this low-level API into a cohesive whole and enhances it with additional utilities, such as AR session lifecycle management and the creation of `GameObject`s to represent detected features in the environment. + +## Branch Guidelines +* `master` ==> Target this branch for changes that need to be in the most recent preview package. Then cherry-pick changes from this branch into older, non-staging branches. `master` will eventually branch to `2.1.x` once work on a newer release begins. + +* `2.0.x` - Target this branch for changes that should be in the 2.0.x package versions. + +* `2.0.x-staging` - Only merge to this branch from `2.0.x` in preparation for a release. This package should ideally contain the exact contents of the latest release on [staging Bintray](https://bintray.com/unity/unity-staging/com.unity.xr.arfoundation). So before a new release QA would validate against `2.0.x` and then a merge would take place into `2.0.x-staging`. + +* `1.1.x` - Target this branch for changes that should be in the 1.1.x package versions. + +* `1.1.x-staging` - Only merge to this branch from `1.1.x` in preparation for a release. This package should ideally contain the exact contents of the latest release on [staging Bintray](https://bintray.com/unity/unity-staging/com.unity.xr.arfoundation). So before a new release QA would validate against `1.1.x` and then a merge would take place into `1.1.x-staging`. \ No newline at end of file diff --git a/package/README.md.meta b/package/README.md.meta index de670779a..ea64bdbb0 100755 --- a/package/README.md.meta +++ b/package/README.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 07774d0433ccf5544ba52ac5468d1cdc -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 07774d0433ccf5544ba52ac5468d1cdc +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime.meta b/package/Runtime.meta index db64949a9..4b576a456 100755 --- a/package/Runtime.meta +++ b/package/Runtime.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: ab67d34cb7e62e246a0f4c98b463ab1a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: ab67d34cb7e62e246a0f4c98b463ab1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR.meta b/package/Runtime/AR.meta index 39e8b094d..b20012af7 100755 --- a/package/Runtime/AR.meta +++ b/package/Runtime/AR.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 6086591be400b46bea7bc39a491b23a9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 6086591be400b46bea7bc39a491b23a9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARBackgroundRendererAsset.cs b/package/Runtime/AR/ARBackgroundRendererAsset.cs index cd4f332f7..b1067de36 100755 --- a/package/Runtime/AR/ARBackgroundRendererAsset.cs +++ b/package/Runtime/AR/ARBackgroundRendererAsset.cs @@ -1,12 +1,27 @@ namespace UnityEngine.XR.ARFoundation { + /// + /// An asset used with the . Useful for working with the + /// Lightweight Render Pipeline (LWRP). + /// public abstract class ARBackgroundRendererAsset : ScriptableObject { + /// + /// Create a . + /// + /// A new . public abstract ARFoundationBackgroundRenderer CreateARBackgroundRenderer(); + /// + /// Creates helper components associated with . + /// + /// The GameObject on which to create the components. public abstract void CreateHelperComponents(GameObject gameObject); + /// + /// Creates the Material necessary for the custom background rendering. + /// + /// A Material used for background rendering. public abstract Material CreateCustomMaterial(); - } } diff --git a/package/Runtime/AR/ARBackgroundRendererAsset.cs.meta b/package/Runtime/AR/ARBackgroundRendererAsset.cs.meta index 7b0834eef..2debffa7b 100755 --- a/package/Runtime/AR/ARBackgroundRendererAsset.cs.meta +++ b/package/Runtime/AR/ARBackgroundRendererAsset.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: af1c78d93435247e788dcedae6dac9f4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: af1c78d93435247e788dcedae6dac9f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARCameraBackground.cs b/package/Runtime/AR/ARCameraBackground.cs index cd9f14ae4..e876d7fe5 100755 --- a/package/Runtime/AR/ARCameraBackground.cs +++ b/package/Runtime/AR/ARCameraBackground.cs @@ -1,283 +1,292 @@ -using System; -using UnityEngine.Rendering; -using UnityEngine.Serialization; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Add this component to a Camera to copy the color camera's texture onto the background. - /// - /// - /// This is the component-ized version of UnityEngine.XR.ARBackgroundRenderer. - /// - [DisallowMultipleComponent, RequireComponent(typeof(Camera))] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARCameraBackground.html")] - public sealed class ARCameraBackground : MonoBehaviour - { - [SerializeField, FormerlySerializedAs("m_OverrideMaterial")] - bool m_UseCustomMaterial; - - /// - /// When false, a material is generated automatically from the shader included in the platform-specific package. - /// When true, is used instead, overriding the automatically generated one. - /// This is not necessary for most AR experiences. - /// - public bool useCustomMaterial - { - get { return m_UseCustomMaterial; } - set - { - m_UseCustomMaterial = value; - UpdateMaterial(); - } - } - - [SerializeField, FormerlySerializedAs("m_Material")] - Material m_CustomMaterial; - - /// - /// If is true, this Material will be used - /// instead of the one included with the platform-specific AR package. - /// - public Material customMaterial - { - get { return m_CustomMaterial; } - set - { - m_CustomMaterial = value; - UpdateMaterial(); - } - } - - /// - /// The current Material used for background rendering. - /// - public Material material - { - get - { - return backgroundRenderer.backgroundMaterial; - } - private set - { - backgroundRenderer.backgroundMaterial = value; - if (ARSubsystemManager.cameraSubsystem != null) - ARSubsystemManager.cameraSubsystem.Material = value; - } - } - - [SerializeField] - bool m_UseCustomRendererAsset; - - /// - /// Whether to use a . This can assist with - /// usage of the light weight render pipeline. - /// - public bool useCustomRendererAsset - { - get { return m_UseCustomRendererAsset; } - set - { - m_UseCustomRendererAsset = value; - SetupBackgroundRenderer(); - } - } - - [SerializeField] - ARBackgroundRendererAsset m_CustomRendererAsset; - - /// - /// Get the custom to use. This can - /// assist with usage of the light weight render pipeline. - /// - public ARBackgroundRendererAsset customRendererAsset - { - get { return m_CustomRendererAsset; } - set - { - m_CustomRendererAsset = value; - SetupBackgroundRenderer(); - } - } - - ARFoundationBackgroundRenderer backgroundRenderer { get; set; } - - Material CreateMaterialFromSubsystemShader() - { - var cameraSubsystem = ARSubsystemManager.cameraSubsystem; - if (m_CameraSetupThrewException || (cameraSubsystem == null)) - return null; - - // Try to create a material from the plugin's provided shader. - string shaderName = ""; - if (!cameraSubsystem.TryGetShaderName(ref shaderName)) - return null; - - var shader = Shader.Find(shaderName); - if (shader == null) - { - // If an exception is thrown, then something is irrecoverably wrong. - // Set this flag so we don't try to do this every frame. - m_CameraSetupThrewException = true; - - throw new InvalidOperationException(string.Format( - "Could not find shader named \"{0}\" required for video overlay on camera subsystem named \"{1}\".", - shaderName, - cameraSubsystem.SubsystemDescriptor.id)); - } - - return new Material(shader); - } - - void OnCameraFrameReceived(ARCameraFrameEventArgs eventArgs) - { - ARSubsystemManager.cameraSubsystem.Camera = m_Camera; - UpdateMaterial(); - mode = ARRenderMode.MaterialAsBackground; - } - - void SetupBackgroundRenderer() - { - if (useRenderPipeline) - { - if (m_LwrpBackgroundRenderer == null) - { - m_LwrpBackgroundRenderer = m_CustomRendererAsset.CreateARBackgroundRenderer(); - m_CustomRendererAsset.CreateHelperComponents(gameObject); - } - - backgroundRenderer = m_LwrpBackgroundRenderer; - } - else - { - if (m_LegacyBackgroundRenderer == null) - m_LegacyBackgroundRenderer = new ARFoundationBackgroundRenderer(); - - backgroundRenderer = m_LegacyBackgroundRenderer; - } - - backgroundRenderer.mode = mode; - backgroundRenderer.camera = m_Camera; - } - - void Awake() - { - m_Camera = GetComponent(); - SetupBackgroundRenderer(); - } - - void OnEnable() - { - UpdateMaterial(); - if (ARSubsystemManager.cameraSubsystem != null) - ARSubsystemManager.cameraSubsystem.Camera = m_Camera; - ARSubsystemManager.cameraFrameReceived += OnCameraFrameReceived; - ARSubsystemManager.systemStateChanged += OnSystemStateChanged; - } - - void OnDisable() - { - mode = ARRenderMode.StandardBackground; - ARSubsystemManager.cameraFrameReceived -= OnCameraFrameReceived; - ARSubsystemManager.systemStateChanged -= OnSystemStateChanged; - m_CameraSetupThrewException = false; - - // Tell the camera subsystem to stop doing work if we are still the active camera - var cameraSubsystem = ARSubsystemManager.cameraSubsystem; - if ((cameraSubsystem != null) && (cameraSubsystem.Camera == m_Camera)) - { - cameraSubsystem.Camera = null; - cameraSubsystem.Material = null; - } - - // We are no longer setting the projection matrix - // so tell the camera to resume its normal projection - // matrix calculations. - m_Camera.ResetProjectionMatrix(); - } - - void OnSystemStateChanged(ARSystemStateChangedEventArgs eventArgs) - { - // If the session goes away then return to using standard background mode - if (eventArgs.state < ARSystemState.SessionInitializing && backgroundRenderer != null) - mode = ARRenderMode.StandardBackground; - } - - void UpdateMaterial() - { - if (useRenderPipeline) - { - material = lwrpMaterial; - } - else - { - material = m_UseCustomMaterial ? m_CustomMaterial : subsystemMaterial; - } - } - - bool m_CameraSetupThrewException; - - Camera m_Camera; - - Material m_SubsystemMaterial; - - private Material subsystemMaterial - { - get - { - if (m_SubsystemMaterial == null) - m_SubsystemMaterial = CreateMaterialFromSubsystemShader(); - - return m_SubsystemMaterial; - } - } - - Material m_LwrpMaterial; - - Material lwrpMaterial - { - get - { - if (m_LwrpMaterial != null) - return m_LwrpMaterial; - - if (m_UseCustomRendererAsset && m_CustomRendererAsset != null) - { - m_LwrpMaterial = m_CustomRendererAsset.CreateCustomMaterial(); - } - - return m_LwrpMaterial; - } - } - - ARFoundationBackgroundRenderer m_LegacyBackgroundRenderer; - - ARFoundationBackgroundRenderer m_LwrpBackgroundRenderer; - - ARRenderMode m_Mode; - - ARRenderMode mode - { - get { return m_Mode; } - set - { - m_Mode = value; - if (m_LwrpBackgroundRenderer != null) - m_LwrpBackgroundRenderer.mode = m_Mode; - if (m_LegacyBackgroundRenderer != null) - m_LegacyBackgroundRenderer.mode = m_Mode; - } - } - - bool useRenderPipeline - { - get - { - return - m_UseCustomRendererAsset && - (m_CustomRendererAsset != null) && - (GraphicsSettings.renderPipelineAsset != null); - } - } - } -} +using System; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Add this component to a Camera to copy the color camera's texture onto the background. + /// + /// + /// This is the component-ized version of UnityEngine.XR.ARBackgroundRenderer. + /// + [DisallowMultipleComponent] + [RequireComponent(typeof(Camera))] + [RequireComponent(typeof(ARCameraManager))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARCameraBackground.html")] + public sealed class ARCameraBackground : MonoBehaviour + { + [SerializeField, FormerlySerializedAs("m_OverrideMaterial")] + bool m_UseCustomMaterial; + + /// + /// When false, a material is generated automatically from the shader included in the platform-specific package. + /// When true, is used instead, overriding the automatically generated one. + /// This is not necessary for most AR experiences. + /// + public bool useCustomMaterial + { + get { return m_UseCustomMaterial; } + set + { + m_UseCustomMaterial = value; + UpdateMaterial(); + } + } + + [SerializeField, FormerlySerializedAs("m_Material")] + Material m_CustomMaterial; + + /// + /// If is true, this Material will be used + /// instead of the one included with the platform-specific AR package. + /// + public Material customMaterial + { + get { return m_CustomMaterial; } + set + { + m_CustomMaterial = value; + UpdateMaterial(); + } + } + + /// + /// The current Material used for background rendering. + /// + public Material material + { + get + { + return m_BackgroundRenderer.backgroundMaterial; + } + private set + { + m_BackgroundRenderer.backgroundMaterial = value; + } + } + + [SerializeField] + bool m_UseCustomRendererAsset; + + /// + /// Whether to use a . This can assist with + /// usage of the light weight render pipeline. + /// + public bool useCustomRendererAsset + { + get { return m_UseCustomRendererAsset; } + set + { + m_UseCustomRendererAsset = value; + SetupBackgroundRenderer(); + } + } + + [SerializeField] + ARBackgroundRendererAsset m_CustomRendererAsset; + + /// + /// Get the custom to use. This can + /// assist with usage of the light weight render pipeline. + /// + public ARBackgroundRendererAsset customRendererAsset + { + get { return m_CustomRendererAsset; } + set + { + m_CustomRendererAsset = value; + SetupBackgroundRenderer(); + } + } + + ARFoundationBackgroundRenderer m_BackgroundRenderer { get; set; } + + Material CreateMaterialFromSubsystemShader() + { + if (m_CameraSetupThrewException) + return null; + + // Try to create a material from the plugin's provided shader. + if (String.IsNullOrEmpty(m_CameraManager.shaderName)) + return null; + + var shader = Shader.Find(m_CameraManager.shaderName); + if (shader == null) + { + // If an exception is thrown, then something is irrecoverably wrong. + // Set this flag so we don't try to do this every frame. + m_CameraSetupThrewException = true; + + throw new InvalidOperationException(string.Format( + "Could not find shader named \"{0}\" required for video overlay on camera subsystem.", + m_CameraManager.shaderName)); + } + + return new Material(shader); + } + + void OnCameraFrameReceived(ARCameraFrameEventArgs eventArgs) + { + UpdateMaterial(); + + var mat = material; + var count = eventArgs.textures.Count; + for (int i = 0; i < count; ++i) + { + mat.SetTexture( + eventArgs.propertyNameIds[i], + eventArgs.textures[i]); + } + + mode = ARRenderMode.MaterialAsBackground; + + if (eventArgs.displayMatrix.HasValue) + mat.SetMatrix(k_DisplayTransformId, eventArgs.displayMatrix.Value); + + if (eventArgs.projectionMatrix.HasValue) + m_Camera.projectionMatrix = eventArgs.projectionMatrix.Value; + } + + void SetupBackgroundRenderer() + { + if (useRenderPipeline) + { + if (m_LwrpBackgroundRenderer == null) + { + m_LwrpBackgroundRenderer = m_CustomRendererAsset.CreateARBackgroundRenderer(); + m_CustomRendererAsset.CreateHelperComponents(gameObject); + } + + m_BackgroundRenderer = m_LwrpBackgroundRenderer; + } + else + { + if (m_LegacyBackgroundRenderer == null) + m_LegacyBackgroundRenderer = new ARFoundationBackgroundRenderer(); + + m_BackgroundRenderer = m_LegacyBackgroundRenderer; + } + + m_BackgroundRenderer.mode = mode; + m_BackgroundRenderer.camera = m_Camera; + } + + void Awake() + { + m_Camera = GetComponent(); + m_CameraManager = GetComponent(); + SetupBackgroundRenderer(); + } + + void OnEnable() + { + UpdateMaterial(); + m_CameraManager.frameReceived += OnCameraFrameReceived; + ARSession.stateChanged += OnSessionStateChanged; + } + + void OnDisable() + { + mode = ARRenderMode.StandardBackground; + m_CameraManager.frameReceived -= OnCameraFrameReceived; + ARSession.stateChanged -= OnSessionStateChanged; + m_CameraSetupThrewException = false; + + // We are no longer setting the projection matrix + // so tell the camera to resume its normal projection + // matrix calculations. + m_Camera.ResetProjectionMatrix(); + } + + void OnSessionStateChanged(ARSessionStateChangedEventArgs eventArgs) + { + // If the session goes away then return to using standard background mode + if (eventArgs.state < ARSessionState.SessionInitializing && m_BackgroundRenderer != null) + mode = ARRenderMode.StandardBackground; + } + + void UpdateMaterial() + { + if (useRenderPipeline) + { + material = lwrpMaterial; + } + else + { + material = m_UseCustomMaterial ? m_CustomMaterial : subsystemMaterial; + } + } + + bool m_CameraSetupThrewException; + + Camera m_Camera; + + ARCameraManager m_CameraManager; + + Material m_SubsystemMaterial; + + private Material subsystemMaterial + { + get + { + if (m_SubsystemMaterial == null) + m_SubsystemMaterial = CreateMaterialFromSubsystemShader(); + + return m_SubsystemMaterial; + } + } + + Material m_LwrpMaterial; + + Material lwrpMaterial + { + get + { + if (m_LwrpMaterial != null) + return m_LwrpMaterial; + + if (m_UseCustomRendererAsset && m_CustomRendererAsset != null) + { + m_LwrpMaterial = m_CustomRendererAsset.CreateCustomMaterial(); + } + + return m_LwrpMaterial; + } + } + + ARFoundationBackgroundRenderer m_LegacyBackgroundRenderer; + + ARFoundationBackgroundRenderer m_LwrpBackgroundRenderer; + + ARRenderMode m_Mode; + + ARRenderMode mode + { + get { return m_Mode; } + set + { + m_Mode = value; + if (m_LwrpBackgroundRenderer != null) + m_LwrpBackgroundRenderer.mode = m_Mode; + if (m_LegacyBackgroundRenderer != null) + m_LegacyBackgroundRenderer.mode = m_Mode; + } + } + + bool useRenderPipeline + { + get + { + return + m_UseCustomRendererAsset && + (m_CustomRendererAsset != null) && + (GraphicsSettings.renderPipelineAsset != null); + } + } + + const string k_DisplayTransformName = "_UnityDisplayTransform"; + + static readonly int k_DisplayTransformId = Shader.PropertyToID(k_DisplayTransformName); + } +} diff --git a/package/Runtime/AR/ARCameraBackground.cs.meta b/package/Runtime/AR/ARCameraBackground.cs.meta index a1b2ccbec..56517f586 100755 --- a/package/Runtime/AR/ARCameraBackground.cs.meta +++ b/package/Runtime/AR/ARCameraBackground.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 816b289ef451e094f9ae174fb4cf8db0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 816b289ef451e094f9ae174fb4cf8db0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARCameraFrameEventArgs.cs b/package/Runtime/AR/ARCameraFrameEventArgs.cs index 15c6596c2..dcdebfa96 100755 --- a/package/Runtime/AR/ARCameraFrameEventArgs.cs +++ b/package/Runtime/AR/ARCameraFrameEventArgs.cs @@ -1,71 +1,113 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A structure for camera-related information pertaining to a particular frame. - /// This is used to communicate information in the event. - /// - public struct ARCameraFrameEventArgs : IEquatable - { - /// - /// The associated with this frame. - /// - public LightEstimationData lightEstimation { get; private set; } - - /// - /// The time, in seconds, associated with this frame. - /// Use time.HasValue to determine if this data is available. - /// - public float? time { get; private set; } - - /// - /// Constructs an . - /// - /// The for the frame. - /// The time, in seconds, for the frame. - public ARCameraFrameEventArgs(LightEstimationData lightEstimation, float? time) - { - this.lightEstimation = lightEstimation; - this.time = time; - } - - public override int GetHashCode() - { - unchecked - { - return lightEstimation.GetHashCode() * 486187739 + time.GetHashCode(); - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARCameraFrameEventArgs)) - return false; - - return Equals((ARCameraFrameEventArgs)obj); - } - - public override string ToString() - { - return string.Format("(Light Estimation: {0}, Time: {1})", lightEstimation.ToString(), time); - } - - public bool Equals(ARCameraFrameEventArgs other) - { - return - (lightEstimation.Equals(other.lightEstimation)) && - (time == other.time); - } - - public static bool operator ==(ARCameraFrameEventArgs lhs, ARCameraFrameEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARCameraFrameEventArgs lhs, ARCameraFrameEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; +using System.Collections.Generic; +using System.Text; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A structure for camera-related information pertaining to a particular frame. + /// This is used to communicate information in the event. + /// + public struct ARCameraFrameEventArgs : IEquatable + { + /// + /// The associated with this frame. + /// + public ARLightEstimationData lightEstimation { get; set; } + + /// + /// The time, in nanoseconds, associated with this frame. + /// Use timestampNs.HasValue to determine if this data is available. + /// + public long? timestampNs { get; set; } + + /// + /// Gets or sets the projection matrix for the AR Camera. Use + /// projectionMatrix.HasValue to determine if this data is available. + /// + public Matrix4x4? projectionMatrix { get; set; } + + /// + /// Gets or sets the display matrix for use in the shader used + /// by the . + /// Use displayMatrix.HasValue to determine if this data is available. + /// + public Matrix4x4? displayMatrix { get; set; } + + /// + /// The textures associated with this camera frame. These are generally + /// external textures, which exist only on the GPU. To use them on the + /// CPU, e.g., for computer vision processing, you will need to read + /// them back from the GPU. + /// + public List textures { get; set; } + + /// + /// Ids of the property name associated with each texture. This is a + /// parallel List to the list. + /// + public List propertyNameIds { get; set; } + + public override int GetHashCode() + { + unchecked + { + var hash = lightEstimation.GetHashCode(); + hash = hash * 486187739 + timestampNs.GetHashCode(); + hash = hash * 486187739 + projectionMatrix.GetHashCode(); + hash = hash * 486187739 + displayMatrix.GetHashCode(); + hash = hash * 486187739 + (textures == null ? 0 : textures.GetHashCode()); + hash = hash * 486187739 + (propertyNameIds == null ? 0 : propertyNameIds.GetHashCode()); + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARCameraFrameEventArgs)) + return false; + + return Equals((ARCameraFrameEventArgs)obj); + } + + /// + /// Generates a string representation of this struct suitable for debug + /// logging. + /// + /// A string representation of this struct suitable for debug + /// logging. + public override string ToString() + { + var stringBuilder = new StringBuilder(); + stringBuilder.Append("lightEstimation: " + lightEstimation.ToString()); + stringBuilder.Append("\ntimestamp: " + timestampNs); + if (timestampNs.HasValue) + stringBuilder.Append("ns"); + stringBuilder.Append("\nprojectionMatrix: " + projectionMatrix); + stringBuilder.Append("\ndisplayMatrix: " + displayMatrix); + stringBuilder.Append("\ntexture count: " + (textures == null ? 0 : textures.Count)); + stringBuilder.Append("\npropertyNameId count: " + (propertyNameIds == null ? 0 : propertyNameIds.Count)); + + return stringBuilder.ToString(); + } + + public bool Equals(ARCameraFrameEventArgs other) + { + return + (lightEstimation.Equals(other.lightEstimation)) && + (projectionMatrix == other.projectionMatrix) && + (displayMatrix == other.displayMatrix) && + (timestampNs == other.timestampNs); + } + + public static bool operator ==(ARCameraFrameEventArgs lhs, ARCameraFrameEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARCameraFrameEventArgs lhs, ARCameraFrameEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARCameraFrameEventArgs.cs.meta b/package/Runtime/AR/ARCameraFrameEventArgs.cs.meta index f93184726..b403c7bd7 100755 --- a/package/Runtime/AR/ARCameraFrameEventArgs.cs.meta +++ b/package/Runtime/AR/ARCameraFrameEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: cc15e1561f1ab0c4dae42edcbec3c7b3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: cc15e1561f1ab0c4dae42edcbec3c7b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARCameraManager.cs b/package/Runtime/AR/ARCameraManager.cs index 30dd0d359..02fc77a0a 100755 --- a/package/Runtime/AR/ARCameraManager.cs +++ b/package/Runtime/AR/ARCameraManager.cs @@ -1,414 +1,415 @@ -using System; -using System.Collections.Generic; -using Unity.Collections; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Manages the lifetime of the XRCameraSubsystem. Add one of these to a Camera in your scene - /// if you want camera texture and light estimation information to be available. - /// - [DefaultExecutionOrder(ARUpdateOrder.k_CameraManager)] - [DisallowMultipleComponent] - [RequireComponent(typeof(Camera))] - public sealed class ARCameraManager : MonoBehaviour - { - [SerializeField] - [Tooltip("The focus mode to request on the (physical) AR camera.")] - CameraFocusMode m_FocusMode = CameraFocusMode.Auto; - - /// - /// Get or set the CameraFocusMode to use on the camera - /// - public CameraFocusMode focusMode - { - get { return m_FocusMode; } - set - { - m_FocusMode = value; - if (enabled) - subsystem.focusMode = focusMode; - } - } - - [SerializeField] - [Tooltip("When enabled, requests that light estimation information be made available.")] - LightEstimationMode m_LightEstimationMode = LightEstimationMode.Disabled; - - /// - /// Get or set whether light estimation information be made available (if possible). - /// - public LightEstimationMode lightEstimationMode - { - get { return m_LightEstimationMode; } - set - { - m_LightEstimationMode = value; - if (enabled && subsystem != null) - subsystem.lightEstimationMode = value; - } - } - - /// - /// Determines whether camera permission has been granted. - /// - /// true if permission has been granted; otherwise, false. - public bool permissionGranted - { - get - { - if (subsystem != null) - return subsystem.permissionGranted; - - return false; - } - } - - /// - /// An event which fires each time a new camera frame is received. - /// - public event Action frameReceived; - - /// - /// Gets the name of the shader used in background rendering. - /// - public string shaderName - { - get - { - if (subsystem != null) - return subsystem.shaderName; - return null; - } - } - - /// - /// Tries the get camera intrinsics. Camera intrinsics refers to properties - /// of a physical camera which may be useful when performing additional - /// computer vision processing on the camera image. - /// - /// true, if was populated, - /// false otherwise. - /// The camera intrinsics to populate. - public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics) - { - if (subsystem == null) - { - cameraIntrinsics = default(XRCameraIntrinsics); - return false; - } - - return subsystem.TryGetIntrinsics(out cameraIntrinsics); - } - - /// - /// Get the XRCameraSubsystem whose lifetime this component manages. - /// - public XRCameraSubsystem subsystem { get; private set; } - - void Awake() - { - m_Camera = GetComponent(); - } - - void OnEnable() - { - if (subsystem == null) - subsystem = CreateSubsystem(); - - if (subsystem != null) - { - subsystem.focusMode = m_FocusMode; - subsystem.lightEstimationMode = m_LightEstimationMode; - subsystem.Start(); - } - } - - void Update() - { - if (subsystem == null) - return; - - var cameraParams = new XRCameraParams - { - zNear = m_Camera.nearClipPlane, - zFar = m_Camera.farClipPlane, - screenWidth = Screen.width, - screenHeight = Screen.height, - screenOrientation = Screen.orientation - }; - - XRCameraFrame frame; - if (subsystem.TryGetLatestFrame(cameraParams, out frame)) - { - UpdateTexturesInfos(); - - if (frameReceived != null) - InvokeFrameReceivedEvent(frame); - } - } - - void UpdateTexturesInfos() - { - var textureDescriptors = subsystem.GetTextureDescriptors(Allocator.Temp); - try - { - int numUpdated = Math.Min(m_TextureInfos.Count, textureDescriptors.Length); - - // Update the existing textures that are in common between the two arrays. - for (int i = 0; i < numUpdated; ++i) - { - m_TextureInfos[i] = TextureInfo.GetUpdatedTextureInfo(m_TextureInfos[i], textureDescriptors[i]); - } - - // If there are fewer textures in the current frame than we had previously, destroy any remaining unneeded - // textures. - if (numUpdated < m_TextureInfos.Count) - { - for (int i = numUpdated; i < m_TextureInfos.Count; ++i) - { - m_TextureInfos[i].DestroyTexture(); - } - m_TextureInfos.RemoveRange(numUpdated, (m_TextureInfos.Count - numUpdated)); - } - // Else, if there are more textures in the current frame than we have previously, add new textures for any - // additional descriptors. - else if (textureDescriptors.Length > m_TextureInfos.Count) - { - for (int i = numUpdated; i < textureDescriptors.Length; ++i) - { - m_TextureInfos.Add(new TextureInfo(textureDescriptors[i])); - } - } - } - finally - { - if (textureDescriptors.IsCreated) - textureDescriptors.Dispose(); - } - } - - void OnDisable() - { - if (subsystem != null) - subsystem.Stop(); - } - - void OnDestroy() - { - if (subsystem != null) - subsystem.Destroy(); - - subsystem = null; - } - - void InvokeFrameReceivedEvent(XRCameraFrame frame) - { - var lightEstimation = new ARLightEstimationData(); - - if (frame.hasAverageBrightness) - lightEstimation.averageBrightness = frame.averageBrightness; - - if (frame.hasAverageColorTemperature) - lightEstimation.averageColorTemperature = frame.averageColorTemperature; - - if (frame.hasColorCorrection) - lightEstimation.colorCorrection = frame.colorCorrection; - - var eventArgs = new ARCameraFrameEventArgs(); - - eventArgs.lightEstimation = lightEstimation; - - if (frame.hasTimestamp) - eventArgs.timestampNs = frame.timestampNs; - - if (frame.hasProjectionMatrix) - eventArgs.projectionMatrix = frame.projectionMatrix; - - if (frame.hasDisplayMatrix) - eventArgs.displayMatrix = frame.displayMatrix; - - s_Textures.Clear(); - s_PropertyIds.Clear(); - foreach (var textureInfo in m_TextureInfos) - { - s_Textures.Add(textureInfo.texture); - s_PropertyIds.Add(textureInfo.descriptor.propertyNameId); - } - - eventArgs.textures = s_Textures; - eventArgs.propertyNameIds = s_PropertyIds; - - frameReceived(eventArgs); - } - - XRCameraSubsystem CreateSubsystem() - { - SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); - if (s_SubsystemDescriptors.Count > 0) - { - var descriptor = s_SubsystemDescriptors[0]; - if (s_SubsystemDescriptors.Count > 1) - { - Debug.LogWarningFormat("Multiple {0} found. Using {1}", - typeof(XRCameraSubsystem).Name, - descriptor.id); - } - - return descriptor.Create(); - } - else - { - return null; - } - } - - static List s_SubsystemDescriptors = - new List(); - - static List s_Textures = new List(); - - static List s_PropertyIds = new List(); - - readonly List m_TextureInfos = new List(); - - Camera m_Camera; - - /// - /// Container that pairs a that wraps a native texture - /// object and a Texture2D that is created for the native texture object. - /// - struct TextureInfo - { - /// - /// Constant for whether the texture is in a linear color space. - /// - /// - /// Constant for whether the texture is in a linear color space. - /// - const bool k_TextureHasLinearColorSpace = false; - - /// - /// Constructs the texture info with the given descriptor and material. - /// - /// The texture descriptor wrapping a native texture object. - public TextureInfo(XRTextureDescriptor descriptor) - { - m_Descriptor = descriptor; - m_Texture = CreateTexture(m_Descriptor); - } - - /// - /// The texture descriptor describing the metadata for the native texture object. - /// - /// - /// The texture descriptor describing the metadata for the native texture object. - /// - public XRTextureDescriptor descriptor - { - get { return m_Descriptor; } - } - XRTextureDescriptor m_Descriptor; - - /// - /// The Unity Texture2D object for the native texture. - /// - /// - /// The Unity Texture2D object for the native texture. - /// - public Texture2D texture - { - get { return m_Texture; } - } - Texture2D m_Texture; - - /// - /// Sets the current descriptor, and creates/updates the associated texture as appropriate. - /// - /// The texture info to update. - /// The texture descriptor wrapping a native texture object. - public static TextureInfo GetUpdatedTextureInfo(TextureInfo textureInfo, XRTextureDescriptor descriptor) - { - // If the current and given descriptors are equal, exit early from this method. - if (textureInfo.m_Descriptor.Equals(descriptor)) - { - return textureInfo; - } - - // If there is a texture already and if the descriptors have identical texture metadata, we only need - // to update the existing texture with the given native texture object. - if ((textureInfo.m_Texture != null) && textureInfo.m_Descriptor.hasIdenticalTextureMetadata(descriptor)) - { - // Update the current descriptor with the given descriptor. - textureInfo.m_Descriptor = descriptor; - - // Update the current texture with the native texture object. - textureInfo.m_Texture.UpdateExternalTexture(textureInfo.m_Descriptor.nativeTexture); - } - // Else, we need to create a new texture object. - else - { - // Update the current descriptor with the given descriptor. - textureInfo.m_Descriptor = descriptor; - - // Replace the current texture with a newly created texture, and update the material. - textureInfo.DestroyTexture(); - textureInfo.m_Texture = CreateTexture(textureInfo.m_Descriptor); - } - - return textureInfo; - } - - /// - /// Destroys the texture, and sets the property to null - /// - public void DestroyTexture() - { - if (m_Texture != null) - { - UnityEngine.Object.Destroy(m_Texture); - m_Texture = null; - } - } - - /// - /// Create the texture object for the native texture wrapped by the valid descriptor. - /// - /// The texture descriptor wrapping a native texture object. - /// - /// If the descriptor is valid, the Texture2D object created from the texture descriptor. Otherwise, - /// null. - /// - static Texture2D CreateTexture(XRTextureDescriptor descriptor) - { - if (!descriptor.valid) - { - return null; - } - - Texture2D texture = Texture2D.CreateExternalTexture(descriptor.width, descriptor.height, - descriptor.format, (descriptor.mipmapCount != 0), - k_TextureHasLinearColorSpace, - descriptor.nativeTexture); - - // NB: SetWrapMode needs to be the first call here, and the value passed - // needs to be kTexWrapClamp - this is due to limitations of what - // wrap modes are allowed for external textures in OpenGL (which are - // used for ARCore), as Texture::ApplySettings will eventually hit - // an assert about an invalid enum (see calls to glTexParameteri - // towards the top of ApiGLES::TextureSampler) - // reference: "3.7.14 External Textures" section of - // https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt - // (it shouldn't ever matter what the wrap mode is set to normally, since - // this is for a pass-through video texture, so we shouldn't ever need to - // worry about the wrap mode as textures should never "wrap") - texture.wrapMode = TextureWrapMode.Clamp; - texture.filterMode = FilterMode.Bilinear; - texture.hideFlags = HideFlags.HideAndDontSave; - - return texture; - } - } - } -} +using System; +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Manages the lifetime of the XRCameraSubsystem. Add one of these to a Camera in your scene + /// if you want camera texture and light estimation information to be available. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_CameraManager)] + [DisallowMultipleComponent] + [RequireComponent(typeof(Camera))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARCameraManager.html")] + public sealed class ARCameraManager : MonoBehaviour + { + [SerializeField] + [Tooltip("The focus mode to request on the (physical) AR camera.")] + CameraFocusMode m_FocusMode = CameraFocusMode.Auto; + + /// + /// Get or set the CameraFocusMode to use on the camera + /// + public CameraFocusMode focusMode + { + get { return m_FocusMode; } + set + { + m_FocusMode = value; + if (enabled) + subsystem.focusMode = focusMode; + } + } + + [SerializeField] + [Tooltip("When enabled, requests that light estimation information be made available.")] + LightEstimationMode m_LightEstimationMode = LightEstimationMode.Disabled; + + /// + /// Get or set whether light estimation information be made available (if possible). + /// + public LightEstimationMode lightEstimationMode + { + get { return m_LightEstimationMode; } + set + { + m_LightEstimationMode = value; + if (enabled && subsystem != null) + subsystem.lightEstimationMode = value; + } + } + + /// + /// Determines whether camera permission has been granted. + /// + /// true if permission has been granted; otherwise, false. + public bool permissionGranted + { + get + { + if (subsystem != null) + return subsystem.permissionGranted; + + return false; + } + } + + /// + /// An event which fires each time a new camera frame is received. + /// + public event Action frameReceived; + + /// + /// Gets the name of the shader used in background rendering. + /// + public string shaderName + { + get + { + if (subsystem != null) + return subsystem.shaderName; + return null; + } + } + + /// + /// Tries the get camera intrinsics. Camera intrinsics refers to properties + /// of a physical camera which may be useful when performing additional + /// computer vision processing on the camera image. + /// + /// true, if was populated, + /// false otherwise. + /// The camera intrinsics to populate. + public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics) + { + if (subsystem == null) + { + cameraIntrinsics = default(XRCameraIntrinsics); + return false; + } + + return subsystem.TryGetIntrinsics(out cameraIntrinsics); + } + + /// + /// Get the XRCameraSubsystem whose lifetime this component manages. + /// + public XRCameraSubsystem subsystem { get; private set; } + + void Awake() + { + m_Camera = GetComponent(); + } + + void OnEnable() + { + if (subsystem == null) + subsystem = CreateSubsystem(); + + if (subsystem != null) + { + subsystem.focusMode = m_FocusMode; + subsystem.lightEstimationMode = m_LightEstimationMode; + subsystem.Start(); + } + } + + void Update() + { + if (subsystem == null) + return; + + var cameraParams = new XRCameraParams + { + zNear = m_Camera.nearClipPlane, + zFar = m_Camera.farClipPlane, + screenWidth = Screen.width, + screenHeight = Screen.height, + screenOrientation = Screen.orientation + }; + + XRCameraFrame frame; + if (subsystem.TryGetLatestFrame(cameraParams, out frame)) + { + UpdateTexturesInfos(); + + if (frameReceived != null) + InvokeFrameReceivedEvent(frame); + } + } + + void UpdateTexturesInfos() + { + var textureDescriptors = subsystem.GetTextureDescriptors(Allocator.Temp); + try + { + int numUpdated = Math.Min(m_TextureInfos.Count, textureDescriptors.Length); + + // Update the existing textures that are in common between the two arrays. + for (int i = 0; i < numUpdated; ++i) + { + m_TextureInfos[i] = TextureInfo.GetUpdatedTextureInfo(m_TextureInfos[i], textureDescriptors[i]); + } + + // If there are fewer textures in the current frame than we had previously, destroy any remaining unneeded + // textures. + if (numUpdated < m_TextureInfos.Count) + { + for (int i = numUpdated; i < m_TextureInfos.Count; ++i) + { + m_TextureInfos[i].DestroyTexture(); + } + m_TextureInfos.RemoveRange(numUpdated, (m_TextureInfos.Count - numUpdated)); + } + // Else, if there are more textures in the current frame than we have previously, add new textures for any + // additional descriptors. + else if (textureDescriptors.Length > m_TextureInfos.Count) + { + for (int i = numUpdated; i < textureDescriptors.Length; ++i) + { + m_TextureInfos.Add(new TextureInfo(textureDescriptors[i])); + } + } + } + finally + { + if (textureDescriptors.IsCreated) + textureDescriptors.Dispose(); + } + } + + void OnDisable() + { + if (subsystem != null) + subsystem.Stop(); + } + + void OnDestroy() + { + if (subsystem != null) + subsystem.Destroy(); + + subsystem = null; + } + + void InvokeFrameReceivedEvent(XRCameraFrame frame) + { + var lightEstimation = new ARLightEstimationData(); + + if (frame.hasAverageBrightness) + lightEstimation.averageBrightness = frame.averageBrightness; + + if (frame.hasAverageColorTemperature) + lightEstimation.averageColorTemperature = frame.averageColorTemperature; + + if (frame.hasColorCorrection) + lightEstimation.colorCorrection = frame.colorCorrection; + + var eventArgs = new ARCameraFrameEventArgs(); + + eventArgs.lightEstimation = lightEstimation; + + if (frame.hasTimestamp) + eventArgs.timestampNs = frame.timestampNs; + + if (frame.hasProjectionMatrix) + eventArgs.projectionMatrix = frame.projectionMatrix; + + if (frame.hasDisplayMatrix) + eventArgs.displayMatrix = frame.displayMatrix; + + s_Textures.Clear(); + s_PropertyIds.Clear(); + foreach (var textureInfo in m_TextureInfos) + { + s_Textures.Add(textureInfo.texture); + s_PropertyIds.Add(textureInfo.descriptor.propertyNameId); + } + + eventArgs.textures = s_Textures; + eventArgs.propertyNameIds = s_PropertyIds; + + frameReceived(eventArgs); + } + + XRCameraSubsystem CreateSubsystem() + { + SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); + if (s_SubsystemDescriptors.Count > 0) + { + var descriptor = s_SubsystemDescriptors[0]; + if (s_SubsystemDescriptors.Count > 1) + { + Debug.LogWarningFormat("Multiple {0} found. Using {1}", + typeof(XRCameraSubsystem).Name, + descriptor.id); + } + + return descriptor.Create(); + } + else + { + return null; + } + } + + static List s_SubsystemDescriptors = + new List(); + + static List s_Textures = new List(); + + static List s_PropertyIds = new List(); + + readonly List m_TextureInfos = new List(); + + Camera m_Camera; + + /// + /// Container that pairs a that wraps a native texture + /// object and a Texture2D that is created for the native texture object. + /// + struct TextureInfo + { + /// + /// Constant for whether the texture is in a linear color space. + /// + /// + /// Constant for whether the texture is in a linear color space. + /// + const bool k_TextureHasLinearColorSpace = false; + + /// + /// Constructs the texture info with the given descriptor and material. + /// + /// The texture descriptor wrapping a native texture object. + public TextureInfo(XRTextureDescriptor descriptor) + { + m_Descriptor = descriptor; + m_Texture = CreateTexture(m_Descriptor); + } + + /// + /// The texture descriptor describing the metadata for the native texture object. + /// + /// + /// The texture descriptor describing the metadata for the native texture object. + /// + public XRTextureDescriptor descriptor + { + get { return m_Descriptor; } + } + XRTextureDescriptor m_Descriptor; + + /// + /// The Unity Texture2D object for the native texture. + /// + /// + /// The Unity Texture2D object for the native texture. + /// + public Texture2D texture + { + get { return m_Texture; } + } + Texture2D m_Texture; + + /// + /// Sets the current descriptor, and creates/updates the associated texture as appropriate. + /// + /// The texture info to update. + /// The texture descriptor wrapping a native texture object. + public static TextureInfo GetUpdatedTextureInfo(TextureInfo textureInfo, XRTextureDescriptor descriptor) + { + // If the current and given descriptors are equal, exit early from this method. + if (textureInfo.m_Descriptor.Equals(descriptor)) + { + return textureInfo; + } + + // If there is a texture already and if the descriptors have identical texture metadata, we only need + // to update the existing texture with the given native texture object. + if ((textureInfo.m_Texture != null) && textureInfo.m_Descriptor.hasIdenticalTextureMetadata(descriptor)) + { + // Update the current descriptor with the given descriptor. + textureInfo.m_Descriptor = descriptor; + + // Update the current texture with the native texture object. + textureInfo.m_Texture.UpdateExternalTexture(textureInfo.m_Descriptor.nativeTexture); + } + // Else, we need to create a new texture object. + else + { + // Update the current descriptor with the given descriptor. + textureInfo.m_Descriptor = descriptor; + + // Replace the current texture with a newly created texture, and update the material. + textureInfo.DestroyTexture(); + textureInfo.m_Texture = CreateTexture(textureInfo.m_Descriptor); + } + + return textureInfo; + } + + /// + /// Destroys the texture, and sets the property to null + /// + public void DestroyTexture() + { + if (m_Texture != null) + { + UnityEngine.Object.Destroy(m_Texture); + m_Texture = null; + } + } + + /// + /// Create the texture object for the native texture wrapped by the valid descriptor. + /// + /// The texture descriptor wrapping a native texture object. + /// + /// If the descriptor is valid, the Texture2D object created from the texture descriptor. Otherwise, + /// null. + /// + static Texture2D CreateTexture(XRTextureDescriptor descriptor) + { + if (!descriptor.valid) + { + return null; + } + + Texture2D texture = Texture2D.CreateExternalTexture(descriptor.width, descriptor.height, + descriptor.format, (descriptor.mipmapCount != 0), + k_TextureHasLinearColorSpace, + descriptor.nativeTexture); + + // NB: SetWrapMode needs to be the first call here, and the value passed + // needs to be kTexWrapClamp - this is due to limitations of what + // wrap modes are allowed for external textures in OpenGL (which are + // used for ARCore), as Texture::ApplySettings will eventually hit + // an assert about an invalid enum (see calls to glTexParameteri + // towards the top of ApiGLES::TextureSampler) + // reference: "3.7.14 External Textures" section of + // https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt + // (it shouldn't ever matter what the wrap mode is set to normally, since + // this is for a pass-through video texture, so we shouldn't ever need to + // worry about the wrap mode as textures should never "wrap") + texture.wrapMode = TextureWrapMode.Clamp; + texture.filterMode = FilterMode.Bilinear; + texture.hideFlags = HideFlags.HideAndDontSave; + + return texture; + } + } + } +} diff --git a/package/Runtime/AR/ARCameraManager.cs.meta b/package/Runtime/AR/ARCameraManager.cs.meta index 0923a8d5e..84c35a4f2 100755 --- a/package/Runtime/AR/ARCameraManager.cs.meta +++ b/package/Runtime/AR/ARCameraManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 4966719baa26e4b0e8231a24d9bd491a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 4966719baa26e4b0e8231a24d9bd491a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARFoundationBackgroundRenderer.cs b/package/Runtime/AR/ARFoundationBackgroundRenderer.cs index 44a1f1ef1..ffaf850e2 100755 --- a/package/Runtime/AR/ARFoundationBackgroundRenderer.cs +++ b/package/Runtime/AR/ARFoundationBackgroundRenderer.cs @@ -1,247 +1,247 @@ -using System; -using UnityEngine.Rendering; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// AR rendering modes used with . - /// - public enum ARRenderMode - { - /// - /// The standard background is rendered according to Camera settings (Skybox, Solid Color, etc.). - /// - StandardBackground, - - /// - /// The material associated with should be rendered as the background. - /// - MaterialAsBackground - }; - - /// - /// Uses command buffers to blit an image to a camera's background. - /// - public partial class ARFoundationBackgroundRenderer - { - /// - /// The Camera to render the background to. - /// - protected Camera m_Camera; - - /// - /// The Material to blit to the camera's background. - /// - protected Material m_BackgroundMaterial; - - /// - /// A Texture to use with the material. If no texture is set, - /// the 's _MainTex texture is used. - /// - protected Texture m_BackgroundTexture; - - ARRenderMode m_RenderMode = ARRenderMode.StandardBackground; - - CommandBuffer m_CommandBuffer; - - CameraClearFlags m_CameraClearFlags = CameraClearFlags.Skybox; - - /// - /// Invoked when one of the properties of this class change. - /// - public event Action backgroundRendererChanged = null; - - /// - /// Get or set the Material used during background rendering. - /// - public Material backgroundMaterial - { - get - { - return m_BackgroundMaterial; - } - set - { - if (m_BackgroundMaterial == value) - return; - - RemoveCommandBuffersIfNeeded(); - m_BackgroundMaterial = value; - - if (backgroundRendererChanged != null) - backgroundRendererChanged(); - - ReapplyCommandBuffersIfNeeded(); - } - } - - /// - /// The texture to use during background rendering. If no texture is set, - /// the 's _MainTex texture is used. - /// - public Texture backgroundTexture - { - get - { - return m_BackgroundTexture; - } - set - { - if (m_BackgroundTexture = value) - return; - - RemoveCommandBuffersIfNeeded(); - m_BackgroundTexture = value; - - if (backgroundRendererChanged != null) - backgroundRendererChanged(); - - ReapplyCommandBuffersIfNeeded(); - } - } - - /// - /// The Camera to render the background to. - /// - public Camera camera - { - get - { - // Return main camera when no Camera has been set - return (m_Camera != null) ? m_Camera : Camera.main; - } - set - { - if (m_Camera == value) - return; - - RemoveCommandBuffersIfNeeded(); - m_Camera = value; - - if (backgroundRendererChanged != null) - backgroundRendererChanged(); - - ReapplyCommandBuffersIfNeeded(); - } - } - - /// - /// Get or set the . - /// - public ARRenderMode mode - { - get - { - return m_RenderMode; - } - set - { - if (value == m_RenderMode) - return; - - m_RenderMode = value; - - switch (m_RenderMode) - { - case ARRenderMode.StandardBackground: - DisableARBackgroundRendering(); - break; - case ARRenderMode.MaterialAsBackground: - EnableARBackgroundRendering(); - break; - default: - throw new Exception("Unhandled render mode."); - } - - if (backgroundRendererChanged != null) - backgroundRendererChanged(); - } - } - - /// - /// Invoked to indicate background rendering should begin. Use this to setup - /// the 's properties and the command buffers used for background rendering. - /// - /// true if background rendering was enabled. - protected virtual bool EnableARBackgroundRendering() - { - if (m_BackgroundMaterial == null) - return false; - - Camera camera; - - if (m_Camera != null) - camera = m_Camera; - else - camera = Camera.main; - - if (camera == null) - return false; - - // Clear flags - m_CameraClearFlags = camera.clearFlags; - camera.clearFlags = CameraClearFlags.Depth; - - // Command buffer setup - m_CommandBuffer = new CommandBuffer(); - - var backgroundTexture = m_BackgroundTexture; - if (backgroundTexture == null) - { - const string kMainTexName = "_MainTex"; - - // GetTexture will return null if the texture isn't found, but it also - // writes an error to the console. We check for existence to silence - // this error. - if (m_BackgroundMaterial.HasProperty(kMainTexName)) - backgroundTexture = m_BackgroundMaterial.GetTexture(kMainTexName); - } - - m_CommandBuffer.Blit(backgroundTexture, BuiltinRenderTextureType.CameraTarget, m_BackgroundMaterial); - camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); - camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); - - return true; - } - - /// - /// Invoked to indicate background rendering should stop. - /// Removes command buffers and returns the Camera to its previous state. - /// - protected virtual void DisableARBackgroundRendering() - { - if (null == m_CommandBuffer) - return; - - var cam = m_Camera ?? Camera.main; - if (cam == null) - return; - - cam.clearFlags = m_CameraClearFlags; - - // Command buffer - cam.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); - cam.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); - } - - bool ReapplyCommandBuffersIfNeeded() - { - if (m_RenderMode != ARRenderMode.MaterialAsBackground) - return false; - - EnableARBackgroundRendering(); - - return true; - } - - bool RemoveCommandBuffersIfNeeded() - { - if (m_RenderMode != ARRenderMode.MaterialAsBackground) - return false; - - DisableARBackgroundRendering(); - - return true; - } - } -} +using System; +using UnityEngine.Rendering; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// AR rendering modes used with . + /// + public enum ARRenderMode + { + /// + /// The standard background is rendered according to Camera settings (Skybox, Solid Color, etc.). + /// + StandardBackground, + + /// + /// The material associated with should be rendered as the background. + /// + MaterialAsBackground + } + + /// + /// Uses command buffers to blit an image to a camera's background. + /// + public partial class ARFoundationBackgroundRenderer + { + /// + /// The Camera to render the background to. + /// + protected Camera m_Camera; + + /// + /// The Material to blit to the camera's background. + /// + protected Material m_BackgroundMaterial; + + /// + /// A Texture to use with the material. If no texture is set, + /// the 's _MainTex texture is used. + /// + protected Texture m_BackgroundTexture; + + /// + /// Invoked when one of the properties of this class changes. + /// + public event Action backgroundRendererChanged; + + /// + /// Get or set the Material used during background rendering. + /// + public Material backgroundMaterial + { + get + { + return m_BackgroundMaterial; + } + set + { + if (m_BackgroundMaterial == value) + return; + + RemoveCommandBuffersIfNeeded(); + m_BackgroundMaterial = value; + + if (backgroundRendererChanged != null) + backgroundRendererChanged(new ARFoundationBackgroundRendererChangedEventArgs()); + + ReapplyCommandBuffersIfNeeded(); + } + } + + /// + /// The texture to use during background rendering. If no texture is set, + /// the 's _MainTex texture is used. + /// + public Texture backgroundTexture + { + get + { + return m_BackgroundTexture; + } + set + { + if (m_BackgroundTexture = value) + return; + + RemoveCommandBuffersIfNeeded(); + m_BackgroundTexture = value; + + if (backgroundRendererChanged != null) + backgroundRendererChanged(new ARFoundationBackgroundRendererChangedEventArgs()); + + ReapplyCommandBuffersIfNeeded(); + } + } + + /// + /// The Camera to render the background to. + /// + public Camera camera + { + get + { + // Return main camera when no Camera has been set + return (m_Camera != null) ? m_Camera : Camera.main; + } + set + { + if (m_Camera == value) + return; + + RemoveCommandBuffersIfNeeded(); + m_Camera = value; + + if (backgroundRendererChanged != null) + backgroundRendererChanged(new ARFoundationBackgroundRendererChangedEventArgs()); + + ReapplyCommandBuffersIfNeeded(); + } + } + + /// + /// Get or set the . + /// + public ARRenderMode mode + { + get + { + return m_RenderMode; + } + set + { + if (value == m_RenderMode) + return; + + m_RenderMode = value; + + switch (m_RenderMode) + { + case ARRenderMode.StandardBackground: + DisableARBackgroundRendering(); + break; + case ARRenderMode.MaterialAsBackground: + EnableARBackgroundRendering(); + break; + default: + throw new Exception("Unhandled render mode."); + } + + if (backgroundRendererChanged != null) + backgroundRendererChanged(new ARFoundationBackgroundRendererChangedEventArgs()); + } + } + + /// + /// Invoked to indicate background rendering should begin. Use this to setup + /// the 's properties and the command buffers used for background rendering. + /// + /// true if background rendering was enabled. + protected virtual bool EnableARBackgroundRendering() + { + if (m_BackgroundMaterial == null) + return false; + + Camera camera; + + if (m_Camera != null) + camera = m_Camera; + else + camera = Camera.main; + + if (camera == null) + return false; + + // Clear flags + m_CameraClearFlags = camera.clearFlags; + camera.clearFlags = CameraClearFlags.Depth; + + // Command buffer setup + m_CommandBuffer = new CommandBuffer(); + + var backgroundTexture = m_BackgroundTexture; + if (backgroundTexture == null) + { + const string kMainTexName = "_MainTex"; + + // GetTexture will return null if the texture isn't found, but it also + // writes an error to the console. We check for existence to silence + // this error. + if (m_BackgroundMaterial.HasProperty(kMainTexName)) + backgroundTexture = m_BackgroundMaterial.GetTexture(kMainTexName); + } + + m_CommandBuffer.Blit(backgroundTexture, BuiltinRenderTextureType.CameraTarget, m_BackgroundMaterial); + camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); + camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); + + return true; + } + + /// + /// Invoked to indicate background rendering should stop. + /// Removes command buffers and returns the Camera to its previous state. + /// + protected virtual void DisableARBackgroundRendering() + { + if (null == m_CommandBuffer) + return; + + var cam = m_Camera ?? Camera.main; + if (cam == null) + return; + + cam.clearFlags = m_CameraClearFlags; + + // Command buffer + cam.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); + cam.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); + } + + bool ReapplyCommandBuffersIfNeeded() + { + if (m_RenderMode != ARRenderMode.MaterialAsBackground) + return false; + + EnableARBackgroundRendering(); + + return true; + } + + bool RemoveCommandBuffersIfNeeded() + { + if (m_RenderMode != ARRenderMode.MaterialAsBackground) + return false; + + DisableARBackgroundRendering(); + + return true; + } + + ARRenderMode m_RenderMode = ARRenderMode.StandardBackground; + + CommandBuffer m_CommandBuffer; + + CameraClearFlags m_CameraClearFlags = CameraClearFlags.Skybox; + } +} diff --git a/package/Runtime/AR/ARFoundationBackgroundRenderer.cs.meta b/package/Runtime/AR/ARFoundationBackgroundRenderer.cs.meta index e9da26e71..6aa32d0a8 100755 --- a/package/Runtime/AR/ARFoundationBackgroundRenderer.cs.meta +++ b/package/Runtime/AR/ARFoundationBackgroundRenderer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 8ccd6a5d4fe354e6ba7133ea70fc2d41 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 8ccd6a5d4fe354e6ba7133ea70fc2d41 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs b/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs index eae506b00..7f03a5264 100755 --- a/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs +++ b/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs @@ -1,49 +1,49 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// The arguments for the - /// event. This is currently empty, but may change in the future without the need to change the - /// subscribers' method signatures. - /// - public struct ARFoundationBackgroundRendererChangedEventArgs : IEquatable - { - /// - /// Generates a hash code suitable for use in a Dictionary or HashSet. - /// - public override int GetHashCode() - { - unchecked - { - return 0; - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARFoundationBackgroundRendererChangedEventArgs)) - return false; - - return Equals((ARFoundationBackgroundRendererChangedEventArgs)obj); - } - - /// - /// Interface for IEquatable - /// - public bool Equals(ARFoundationBackgroundRendererChangedEventArgs other) - { - return true; - } - - public static bool operator ==(ARFoundationBackgroundRendererChangedEventArgs lhs, ARFoundationBackgroundRendererChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARFoundationBackgroundRendererChangedEventArgs lhs, ARFoundationBackgroundRendererChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } +using System; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// The arguments for the + /// event. This is currently empty, but may change in the future without the need to change the + /// subscribers' method signatures. + /// + public struct ARFoundationBackgroundRendererChangedEventArgs : IEquatable + { + /// + /// Generates a hash code suitable for use in a Dictionary or HashSet. + /// + public override int GetHashCode() + { + unchecked + { + return 0; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARFoundationBackgroundRendererChangedEventArgs)) + return false; + + return Equals((ARFoundationBackgroundRendererChangedEventArgs)obj); + } + + /// + /// Interface for IEquatable + /// + public bool Equals(ARFoundationBackgroundRendererChangedEventArgs other) + { + return true; + } + + public static bool operator ==(ARFoundationBackgroundRendererChangedEventArgs lhs, ARFoundationBackgroundRendererChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARFoundationBackgroundRendererChangedEventArgs lhs, ARFoundationBackgroundRendererChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } } \ No newline at end of file diff --git a/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs.meta b/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs.meta index 81d5fc583..be0c5f6c0 100755 --- a/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARFoundationBackgroundRendererChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: e349520de69a34094afaade01d2e2259 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: e349520de69a34094afaade01d2e2259 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARInputManager.cs b/package/Runtime/AR/ARInputManager.cs index 3fee1344e..39e4d189b 100755 --- a/package/Runtime/AR/ARInputManager.cs +++ b/package/Runtime/AR/ARInputManager.cs @@ -1,65 +1,66 @@ -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Manages the lifetime of the XRInputSubsystem. Add one of these to any GameObject in your scene - /// if you want device pose information to be available. Read the input by using the TrackedPoseDriver - /// - [DefaultExecutionOrder(ARUpdateOrder.k_InputManager)] - [DisallowMultipleComponent] - public sealed class ARInputManager : MonoBehaviour - { - /// - /// Get the XRInputSubsystem whose lifetime this component manages. - /// - public XRInputSubsystem subsystem { get; private set; } - - void OnEnable() - { - if (subsystem == null) - subsystem = CreateSubsystem(); - - if (subsystem != null) - subsystem.Start(); - } - - void OnDisable() - { - if (subsystem != null) - subsystem.Stop(); - } - - void OnDestroy() - { - if (subsystem != null) - subsystem.Destroy(); - - subsystem = null; - } - - XRInputSubsystem CreateSubsystem() - { - SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); - if (s_SubsystemDescriptors.Count > 0) - { - var descriptor = s_SubsystemDescriptors[0]; - if (s_SubsystemDescriptors.Count > 1) - { - Debug.LogWarningFormat("Multiple {0} found. Using {1}", - typeof(XRInputSubsystem).Name, - descriptor.id); - } - - return descriptor.Create(); - } - else - { - return null; - } - } - - static List s_SubsystemDescriptors = - new List(); - } -} +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Manages the lifetime of the XRInputSubsystem. Add one of these to any GameObject in your scene + /// if you want device pose information to be available. Read the input by using the TrackedPoseDriver + /// + [DefaultExecutionOrder(ARUpdateOrder.k_InputManager)] + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARInputManager.html")] + public sealed class ARInputManager : MonoBehaviour + { + /// + /// Get the XRInputSubsystem whose lifetime this component manages. + /// + public XRInputSubsystem subsystem { get; private set; } + + void OnEnable() + { + if (subsystem == null) + subsystem = CreateSubsystem(); + + if (subsystem != null) + subsystem.Start(); + } + + void OnDisable() + { + if (subsystem != null) + subsystem.Stop(); + } + + void OnDestroy() + { + if (subsystem != null) + subsystem.Destroy(); + + subsystem = null; + } + + XRInputSubsystem CreateSubsystem() + { + SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); + if (s_SubsystemDescriptors.Count > 0) + { + var descriptor = s_SubsystemDescriptors[0]; + if (s_SubsystemDescriptors.Count > 1) + { + Debug.LogWarningFormat("Multiple {0} found. Using {1}", + typeof(XRInputSubsystem).Name, + descriptor.id); + } + + return descriptor.Create(); + } + else + { + return null; + } + } + + static List s_SubsystemDescriptors = + new List(); + } +} diff --git a/package/Runtime/AR/ARInputManager.cs.meta b/package/Runtime/AR/ARInputManager.cs.meta index fdf092e12..828f3c2b1 100755 --- a/package/Runtime/AR/ARInputManager.cs.meta +++ b/package/Runtime/AR/ARInputManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: fa850fbd5b8aded44846f96e35f1a9f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: fa850fbd5b8aded44846f96e35f1a9f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARLightEstimationData.cs b/package/Runtime/AR/ARLightEstimationData.cs index 47e485a73..d17585604 100755 --- a/package/Runtime/AR/ARLightEstimationData.cs +++ b/package/Runtime/AR/ARLightEstimationData.cs @@ -1,84 +1,84 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A structure for light estimation information provided by the AR device. - /// - public struct ARLightEstimationData : IEquatable - { - /// - /// An estimate for the average brightness in the scene. - /// Use averageBrightness.HasValue to determine if this information is available. - /// - /// - /// may be null when light estimation is not enabled in the , - /// if the platform does not support it, or if a platform-specific error has occurred. - /// - public float? averageBrightness { get; set; } - - /// - /// An estimate for the average color temperature of the scene. - /// Use averageColorTemperature.HasValue to determine if this information is available. - /// - /// - /// may be null when light estimation is not enabled in the , - /// if the platform does not support it, or if a platform-specific error has occurred. - /// - public float? averageColorTemperature { get; set; } - - /// - /// The scaling factors used for color correction. - /// The RGB scale factors are used to match the color of the light - /// in the scene. The alpha channel value is platform-specific. - /// - /// - /// may be null when light estimation is not enabled in the , - /// if the platform does not support it, or if a platform-specific error has occurred. - /// - public Color? colorCorrection { get; set; } - - public override int GetHashCode() - { - unchecked - { - return - (averageBrightness.GetHashCode() * 486187739 + - averageColorTemperature.GetHashCode()) * 486187739 + - colorCorrection.GetHashCode(); - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARLightEstimationData)) - return false; - - return Equals((ARLightEstimationData)obj); - } - - public override string ToString() - { - return string.Format("(Avg. Brightness: {0}, Avg. Color Temperature: {1}, Color Correction: {2})", - averageBrightness, averageColorTemperature, colorCorrection); - } - - public bool Equals(ARLightEstimationData other) - { - return - (averageBrightness.Equals(other.averageBrightness)) && - (averageColorTemperature.Equals(other.averageColorTemperature)) && - (colorCorrection.Equals(other.colorCorrection)); - } - - public static bool operator ==(ARLightEstimationData lhs, ARLightEstimationData rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARLightEstimationData lhs, ARLightEstimationData rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A structure for light estimation information provided by the AR device. + /// + public struct ARLightEstimationData : IEquatable + { + /// + /// An estimate for the average brightness in the scene. + /// Use averageBrightness.HasValue to determine if this information is available. + /// + /// + /// may be null when light estimation is not enabled in the , + /// if the platform does not support it, or if a platform-specific error has occurred. + /// + public float? averageBrightness { get; set; } + + /// + /// An estimate for the average color temperature of the scene. + /// Use averageColorTemperature.HasValue to determine if this information is available. + /// + /// + /// may be null when light estimation is not enabled in the , + /// if the platform does not support it, or if a platform-specific error has occurred. + /// + public float? averageColorTemperature { get; set; } + + /// + /// The scaling factors used for color correction. + /// The RGB scale factors are used to match the color of the light + /// in the scene. The alpha channel value is platform-specific. + /// + /// + /// may be null when light estimation is not enabled in the , + /// if the platform does not support it, or if a platform-specific error has occurred. + /// + public Color? colorCorrection { get; set; } + + public override int GetHashCode() + { + unchecked + { + return + (averageBrightness.GetHashCode() * 486187739 + + averageColorTemperature.GetHashCode()) * 486187739 + + colorCorrection.GetHashCode(); + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARLightEstimationData)) + return false; + + return Equals((ARLightEstimationData)obj); + } + + public override string ToString() + { + return string.Format("(Avg. Brightness: {0}, Avg. Color Temperature: {1}, Color Correction: {2})", + averageBrightness, averageColorTemperature, colorCorrection); + } + + public bool Equals(ARLightEstimationData other) + { + return + (averageBrightness.Equals(other.averageBrightness)) && + (averageColorTemperature.Equals(other.averageColorTemperature)) && + (colorCorrection.Equals(other.colorCorrection)); + } + + public static bool operator ==(ARLightEstimationData lhs, ARLightEstimationData rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARLightEstimationData lhs, ARLightEstimationData rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARLightEstimationData.cs.meta b/package/Runtime/AR/ARLightEstimationData.cs.meta index 6c5f35128..466efe907 100755 --- a/package/Runtime/AR/ARLightEstimationData.cs.meta +++ b/package/Runtime/AR/ARLightEstimationData.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 4f4808ab7959f4746b4a91cd7a13299d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 4f4808ab7959f4746b4a91cd7a13299d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlane.cs b/package/Runtime/AR/ARPlane.cs index e90211628..d78247014 100755 --- a/package/Runtime/AR/ARPlane.cs +++ b/package/Runtime/AR/ARPlane.cs @@ -1,222 +1,220 @@ -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.XR; -using UnityEngine.XR.ARExtensions; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Represents a plane detected by an AR device. - /// - /// - /// Generated by the when an AR device detects - /// a plane in the environment. - /// - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPlane.html")] - public sealed class ARPlane : MonoBehaviour - { - [SerializeField] - [Tooltip("If true, this component's GameObject will be removed immediately when the plane is removed.")] - bool m_DestroyOnRemoval = true; - - /// - /// If true, this component's GameObject will be removed immediately when the plane is removed. - /// - /// - /// Setting this to false will keep the plane's GameObject around. You may want to do this, for example, - /// if you have custom removal logic, such as a fade out. - /// - public bool destroyOnRemoval - { - get { return m_DestroyOnRemoval; } - set { m_DestroyOnRemoval = value; } - } - - [SerializeField] - [Tooltip("The largest value by which a plane's vertex may change before the polygonChanged event is invoked. Units are in session-space meters.")] - float m_VertexChangedThreshold = 0.01f; - - /// - /// The largest value by which a plane's vertex may change before the mesh is regenerated. Units are in session-space meters. - /// - public float vertexChangedThreshold - { - get { return m_VertexChangedThreshold; } - set { m_VertexChangedThreshold = Mathf.Max(0f, value); } - } - - /// - /// The BoundedPlane data struct which defines this . - /// - public BoundedPlane boundedPlane - { - get { return m_BoundedPlane; } - - internal set - { - m_BoundedPlane = value; - - lastUpdatedFrame = Time.frameCount; - - var pose = boundedPlane.Pose; - transform.localPosition = pose.position; - transform.localRotation = pose.rotation; - - if (updated != null) - updated(this); - - if (boundaryChanged != null) - CheckBoundaryChanged(); - } - } - - /// - /// Gets the normal to this plane in world space. - /// - public Vector3 normal - { - get { return transform.up; } - } - - /// - /// Gets the current TrackingState of this . - /// - public TrackingState trackingState - { - get - { - if (ARSubsystemManager.planeSubsystem == null) - return TrackingState.Unknown; - else - return ARSubsystemManager.planeSubsystem.GetTrackingState(boundedPlane.Id); - } - } - - /// - /// The last frame on which this plane was updated. - /// - public int lastUpdatedFrame { get; private set; } - - /// - /// Invoked whenever the plane updates - /// - public event Action updated; - - /// - /// Invoked just before the plane is about to be removed. - /// - public event Action removed; - - /// - /// Invoked when any vertex in the plane's polygon changes by more than . - /// - /// - /// The data is provided in plane-relative space. That is, relative to the - /// 's localPosition and localRotation. - /// - /// Units are in session-space meters. - /// - public event Action boundaryChanged; - - /// - /// Attempts to retrieve the boundary points of the plane. - /// - /// If successful, the contents are replaced with the 's boundary points. - /// Which coordinate system to use. Space.Self refers to session space, - /// while Space.World refers to Unity world space. The default is Space.World. - /// True if the boundary was successfully retrieved. - public bool TryGetBoundary(List boundaryOut, Space space = Space.World) - { - if (!boundedPlane.TryGetBoundary(boundaryOut)) - return false; - - if (space == Space.World) - transform.parent.TransformPointList(boundaryOut); - - return true; - } - - /// - /// Checks if each set of positions are equal to within some tolerance. - /// - /// The first set of positions - /// The second set of positions - /// Positions in the first set must be within this value to the positions in the second set to be considered equal. - /// True if all positions are approximately equal, false if any of them are not, or if the number of positions in the sets differs. - public static bool PositionsAreApproximatelyEqual(List positions1, List positions2, float tolerance) - { - if (positions1 == null) - throw new ArgumentNullException("positions1"); - - if (positions2 == null) - throw new ArgumentNullException("positions2"); - - if (positions1.Count != positions2.Count) - return false; - - var toleranceSquared = tolerance * tolerance; - for (int i = 0; i < positions1.Count; ++i) - { - var diffSquared = (positions1[i] - positions2[i]).sqrMagnitude; - if (diffSquared > toleranceSquared) - return false; - } - - return true; - } - - void OnValidate() - { - vertexChangedThreshold = Mathf.Max(0f, vertexChangedThreshold); - } - - void CheckBoundaryChanged() - { - var newVertices = s_BoundaryPoints; - if (!boundedPlane.TryGetBoundary(newVertices)) - return; - - // Only perform the boundary check if our changed threshold is non zero - if (vertexChangedThreshold > 0f) - { - if (m_Boundary == null) - m_Boundary = new List(); - - // Early out if the verts haven't changed significantly. - if (PositionsAreApproximatelyEqual(newVertices, m_Boundary, vertexChangedThreshold)) - return; - - // Save the new vertices so we can compare during the next update - m_Boundary.Clear(); - m_Boundary.AddRange(newVertices); - } - - var pose = boundedPlane.Pose; - - // The plane boundary points are in session space, but this GameObject - // is already set to the plane's pose. We therefore want the boundary points - // relative to the plane's pose, or plane-local space. - pose.InverseTransformPositions(newVertices); - var centerInPlaneSpace = pose.InverseTransformPosition(boundedPlane.Center); - var normalInPlaneSpace = pose.InverseTransformDirection(boundedPlane.Normal); - - boundaryChanged(new ARPlaneBoundaryChangedEventArgs(this, centerInPlaneSpace, normalInPlaneSpace, newVertices)); - } - - internal void OnRemove() - { - if (removed != null) - removed(this); - - if (destroyOnRemoval) - Destroy(gameObject); - } - - List m_Boundary; - - BoundedPlane m_BoundedPlane; - - static List s_BoundaryPoints = new List(); - } -} +using System; +using System.Collections.Generic; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Represents a plane (i.e., a flat surface) detected by an AR device. + /// + /// + /// Generated by the when an AR device detects + /// a plane in the environment. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_Plane)] + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARPlane.html")] + public sealed class ARPlane : ARTrackable + { + [SerializeField] + [Tooltip("The largest value by which a plane's vertex may change before the boundaryChanged event is invoked. Units are in meters.")] + float m_VertexChangedThreshold = 0.01f; + + /// + /// The largest value by which a plane's vertex may change before the mesh is regenerated. Units are in meters. + /// + public float vertexChangedThreshold + { + get { return m_VertexChangedThreshold; } + set { m_VertexChangedThreshold = Mathf.Max(0f, value); } + } + + /// + /// Invoked when any vertex in the plane's boundary changes by more than . + /// + public event Action boundaryChanged; + + /// + /// Gets the normal to this plane in world space. + /// + public Vector3 normal + { + get { return transform.up; } + } + + /// + /// The which has subsumed this plane, or null + /// if this plane has not been subsumed. + /// + public ARPlane subsumedBy { get; internal set; } + + /// + /// The alignment of this plane. + /// + public PlaneAlignment alignment { get { return sessionRelativeData.alignment; } } + + /// + /// The 2D center point, in plane space + /// + public Vector2 centerInPlaneSpace { get { return sessionRelativeData.center; } } + + /// + /// The 3D center point, in Unity world space. + /// + public Vector3 center { get { return transform.TransformPoint(centerInPlaneSpace); } } + + /// + /// The physical extents (half dimensions) of the plane in meters. + /// + public Vector2 extents { get { return sessionRelativeData.extents; } } + + /// + /// The physical size (dimensions) of the plane in meters. + /// + public Vector2 size { get { return sessionRelativeData.size; } } + + /// + /// Get the infinite plane associated with this . + /// + public Plane infinitePlane { get { return new Plane(normal, transform.position); } } + + /// + /// Get a native pointer associated with this plane. + /// + /// + /// The data pointed to by this member is implementation defined. + /// The lifetime of the pointed to object is also + /// implementation defined, but should be valid at least until the next + /// update. + /// + public IntPtr nativePtr { get { return sessionRelativeData.nativePtr; } } + + /// + /// The plane's boundary points, in plane space, that is, relative to this 's + /// local position and rotation. + /// + public unsafe NativeArray boundary + { + get + { + if (!m_Boundary.IsCreated) + return default(NativeArray); + + return NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray( + m_Boundary.GetUnsafePtr(), + m_Boundary.Length, + Allocator.None); + } + } + + internal void UpdateBoundary(XRPlaneSubsystem subsystem) + { + // subsystem cannot be null here + if (subsystem.SubsystemDescriptor.supportsBoundaryVertices) + { + subsystem.GetBoundary(trackableId, Allocator.Persistent, ref m_Boundary); + } + else + { + if (!m_Boundary.IsCreated) + { + m_Boundary = new NativeArray(4, Allocator.Persistent); + } + else if (m_Boundary.Length != 4) + { + m_Boundary.Dispose(); + m_Boundary = new NativeArray(4, Allocator.Persistent); + } + + var extents = sessionRelativeData.extents; + m_Boundary[0] = new Vector2(-extents.x, -extents.y); + m_Boundary[1] = new Vector2(-extents.x, extents.y); + m_Boundary[2] = new Vector2( extents.x, extents.y); + m_Boundary[3] = new Vector2( extents.x, -extents.y); + } + + if (boundaryChanged != null) + CheckForBoundaryChanges(); + } + + void OnValidate() + { + vertexChangedThreshold = Mathf.Max(0f, vertexChangedThreshold); + } + + void OnDestroy() + { + if (m_OldBoundary.IsCreated) + m_OldBoundary.Dispose(); + if (m_Boundary.IsCreated) + m_Boundary.Dispose(); + } + + void CheckForBoundaryChanges() + { + if (m_Boundary.Length != m_OldBoundary.Length) + { + CopyBoundaryAndSetChangedFlag(); + } + else if (vertexChangedThreshold == 0f) + { + // Don't need to check each vertex because it will always + // be "different" if threshold is zero. + CopyBoundaryAndSetChangedFlag(); + } + else + { + // Counts are the same; check each vertex + var thresholdSquared = vertexChangedThreshold * vertexChangedThreshold; + for (int i = 0; i < m_Boundary.Length; ++i) + { + var diffSquared = (m_Boundary[i] - m_OldBoundary[i]).sqrMagnitude; + if (diffSquared > thresholdSquared) + { + CopyBoundaryAndSetChangedFlag(); + break; + } + } + } + } + + void CopyBoundaryAndSetChangedFlag() + { + // Copy new boundary + if (m_OldBoundary.IsCreated) + { + // If the lengths are different, then we need + // to reallocate, but otherwise, we can reuse + if (m_OldBoundary.Length != m_Boundary.Length) + { + m_OldBoundary.Dispose(); + m_OldBoundary = new NativeArray(m_Boundary.Length, Allocator.Persistent); + } + } + else + { + m_OldBoundary = new NativeArray(m_Boundary.Length, Allocator.Persistent); + } + + m_OldBoundary.CopyFrom(m_Boundary); + m_HasBoundaryChanged = true; + } + + void Update() + { + if (m_HasBoundaryChanged && (boundaryChanged != null)) + { + m_HasBoundaryChanged = false; + boundaryChanged(new ARPlaneBoundaryChangedEventArgs(this)); + } + } + + NativeArray m_Boundary; + + NativeArray m_OldBoundary; + + bool m_HasBoundaryChanged; + } +} diff --git a/package/Runtime/AR/ARPlane.cs.meta b/package/Runtime/AR/ARPlane.cs.meta index b57999a7c..4a2d8a24b 100755 --- a/package/Runtime/AR/ARPlane.cs.meta +++ b/package/Runtime/AR/ARPlane.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 5f66da7470dce8f4d821d71dd2b1d4ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 5f66da7470dce8f4d821d71dd2b1d4ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs b/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs index 8986d48e5..8c296979f 100755 --- a/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs +++ b/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs @@ -1,65 +1,65 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Data associated with an event. - /// - public struct ARPlaneBoundaryChangedEventArgs : IEquatable - { - /// - /// The which triggered the event. - /// - public ARPlane plane { get; private set; } - - /// - /// Constructor for plane changed events. - /// This is normally only used by the component for events. - /// - /// The that triggered the event. - public ARPlaneBoundaryChangedEventArgs(ARPlane plane) - { - if (plane == null) - throw new ArgumentNullException("plane"); - - this.plane = plane; - } - - public override int GetHashCode() - { - unchecked - { - var hash = plane == null ? 0 : plane.GetHashCode(); - return hash; - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARPlaneBoundaryChangedEventArgs)) - return false; - - return Equals((ARPlaneBoundaryChangedEventArgs)obj); - } - - public override string ToString() - { - return plane.trackableId.ToString(); - } - - public bool Equals(ARPlaneBoundaryChangedEventArgs other) - { - return (plane == other.plane); - } - - public static bool operator ==(ARPlaneBoundaryChangedEventArgs lhs, ARPlaneBoundaryChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARPlaneBoundaryChangedEventArgs lhs, ARPlaneBoundaryChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Data associated with an event. + /// + public struct ARPlaneBoundaryChangedEventArgs : IEquatable + { + /// + /// The which triggered the event. + /// + public ARPlane plane { get; private set; } + + /// + /// Constructor for plane changed events. + /// This is normally only used by the component for events. + /// + /// The that triggered the event. + public ARPlaneBoundaryChangedEventArgs(ARPlane plane) + { + if (plane == null) + throw new ArgumentNullException("plane"); + + this.plane = plane; + } + + public override int GetHashCode() + { + unchecked + { + var hash = plane == null ? 0 : plane.GetHashCode(); + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARPlaneBoundaryChangedEventArgs)) + return false; + + return Equals((ARPlaneBoundaryChangedEventArgs)obj); + } + + public override string ToString() + { + return plane.trackableId.ToString(); + } + + public bool Equals(ARPlaneBoundaryChangedEventArgs other) + { + return (plane == other.plane); + } + + public static bool operator ==(ARPlaneBoundaryChangedEventArgs lhs, ARPlaneBoundaryChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARPlaneBoundaryChangedEventArgs lhs, ARPlaneBoundaryChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs.meta b/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs.meta index f31135f0a..1de14de01 100755 --- a/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARPlaneBoundaryChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 20aba02fbd6687c45829f2d152c68609 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 20aba02fbd6687c45829f2d152c68609 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlaneManager.cs b/package/Runtime/AR/ARPlaneManager.cs index cb6da89c5..9ef13b394 100755 --- a/package/Runtime/AR/ARPlaneManager.cs +++ b/package/Runtime/AR/ARPlaneManager.cs @@ -1,279 +1,285 @@ -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.XR; -using UnityEngine.XR.ARExtensions; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Creates, updates, and removes GameObjects with components under the 's . - /// - /// - /// When enabled, this component subscribes to , - /// , and . - /// If this component is disabled, and there are no other subscribers to those events, - /// plane detection will be disabled on the device. - /// - [RequireComponent(typeof(ARSessionOrigin))] - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPlaneManager.html")] - public sealed class ARPlaneManager : MonoBehaviour - { - [SerializeField] - [Tooltip("If not null, instantiates this prefab for each created plane.")] - GameObject m_PlanePrefab; - - /// - /// Getter/setter for the Plane Prefab. - /// - public GameObject planePrefab - { - get { return m_PlanePrefab; } - set { m_PlanePrefab = value; } - } - - [SerializeField, PlaneDetectionFlagsMask] - [Tooltip("Specifies the types of planes to detect.")] - PlaneDetectionFlags m_DetectionFlags = k_PlaneDetectionFlagEverything; - - /// - /// Get or set the PlaneDetectionFlags to use for plane detection. - /// - public PlaneDetectionFlags detectionFlags - { - get - { - if (m_DetectionFlags == k_PlaneDetectionFlagEverything) - return PlaneDetectionFlags.Horizontal | PlaneDetectionFlags.Vertical; - - return m_DetectionFlags; - } - set - { - m_DetectionFlags = value; - - if (enabled) - ARSubsystemManager.planeDetectionFlags = detectionFlags; - } - } - - /// - /// Raised for each new detected in the environment. - /// - public event Action planeAdded; - - /// - /// Raised for each every time it updates. - /// - public event Action planeUpdated; - - /// - /// Raised whenever an is removed. - /// - public event Action planeRemoved; - - /// - /// Get the number of planes managed by this manager. - /// - public int planeCount - { - get { return m_Planes.Count; } - } - - /// - /// Get all currently tracked s. - /// - /// Replaces the contents with the current list of planes. - public void GetAllPlanes(List planes) - { - if (planes == null) - throw new ArgumentNullException("planes"); - - planes.Clear(); - foreach (var kvp in m_Planes) - { - planes.Add(kvp.Value); - } - } - - /// - /// Attempts to retrieve an . - /// - /// The TrackableId associated with the . - /// The if found. null otherwise. - public ARPlane TryGetPlane(TrackableId planeId) - { - ARPlane plane; - m_Planes.TryGetValue(planeId, out plane); - - return plane; - } - - void Awake() - { - m_SessionOrigin = GetComponent(); - } - - void OnEnable() - { - SyncPlanes(); - ARSubsystemManager.planeDetectionFlags = detectionFlags; - ARSubsystemManager.planeAdded += OnPlaneAdded; - ARSubsystemManager.planeUpdated += OnPlaneUpdated; - ARSubsystemManager.planeRemoved += OnPlaneRemoved; - ARSubsystemManager.sessionDestroyed += OnSessionDestroyed; - } - - void OnDisable() - { - ARSubsystemManager.planeAdded -= OnPlaneAdded; - ARSubsystemManager.planeUpdated -= OnPlaneUpdated; - ARSubsystemManager.planeRemoved -= OnPlaneRemoved; - ARSubsystemManager.sessionDestroyed -= OnSessionDestroyed; - } - - void OnSessionDestroyed() - { - if (planeRemoved != null) - { - foreach (var kvp in m_Planes) - { - var plane = kvp.Value; - planeRemoved(new ARPlaneRemovedEventArgs(plane)); - plane.OnRemove(); - } - } - else - { - foreach (var kvp in m_Planes) - kvp.Value.OnRemove(); - } - - m_Planes.Clear(); - } - - void SyncPlanes() - { - var planeSubsystem = ARSubsystemManager.planeSubsystem; - if (planeSubsystem == null) - return; - - s_BoundedPlanes.Clear(); - planeSubsystem.GetAllPlanes(s_BoundedPlanes); - - // Check for added/updated planes - s_TrackableIds.Clear(); - foreach (var boundedPlane in s_BoundedPlanes) - { - var planeId = boundedPlane.Id; - - ARPlane plane; - if (m_Planes.TryGetValue(planeId, out plane)) - { - plane.boundedPlane = boundedPlane; - if (planeUpdated != null) - planeUpdated(new ARPlaneUpdatedEventArgs(plane)); - } - else - { - plane = AddPlane(boundedPlane); - plane.boundedPlane = boundedPlane; - if (planeAdded != null) - planeAdded(new ARPlaneAddedEventArgs(plane)); - } - - s_TrackableIds.Add(planeId); - } - - // Check for removed planes - s_PlanesToRemove.Clear(); - foreach (var kvp in m_Planes) - { - var planeId = kvp.Key; - if (!s_TrackableIds.Contains(planeId)) - s_PlanesToRemove.Add(planeId); - } - - foreach (var id in s_PlanesToRemove) - RemovePlane(m_Planes[id]); - } - - GameObject CreateGameObject() - { - if (planePrefab != null) - return Instantiate(planePrefab, m_SessionOrigin.trackablesParent); - - var go = new GameObject(); - go.transform.SetParent(m_SessionOrigin.trackablesParent, false); - go.layer = gameObject.layer; - return go; - } - - ARPlane AddPlane(BoundedPlane boundedPlane) - { - var go = CreateGameObject(); - var plane = go.GetComponent(); - if (plane == null) - plane = go.AddComponent(); - - m_Planes.Add(boundedPlane.Id, plane); - - return plane; - } - - void OnPlaneAdded(PlaneAddedEventArgs eventArgs) - { - var boundedPlane = eventArgs.Plane; - var plane = AddPlane(boundedPlane); - plane.boundedPlane = boundedPlane; - - if (planeAdded != null) - planeAdded(new ARPlaneAddedEventArgs(plane)); - } - - void OnPlaneUpdated(PlaneUpdatedEventArgs eventArgs) - { - var boundedPlane = eventArgs.Plane; - var plane = TryGetPlane(boundedPlane.Id); - if (plane == null) - plane = AddPlane(boundedPlane); - - plane.boundedPlane = boundedPlane; - - if (planeUpdated != null) - planeUpdated(new ARPlaneUpdatedEventArgs(plane)); - } - - void OnPlaneRemoved(PlaneRemovedEventArgs eventArgs) - { - var boundedPlane = eventArgs.Plane; - var plane = TryGetPlane(boundedPlane.Id); - - if (plane == null) - return; - - RemovePlane(plane); - } - - void RemovePlane(ARPlane plane) - { - if (planeRemoved != null) - planeRemoved(new ARPlaneRemovedEventArgs(plane)); - - plane.OnRemove(); - m_Planes.Remove(plane.boundedPlane.Id); - } - - Dictionary m_Planes = new Dictionary(); - - ARSessionOrigin m_SessionOrigin; - - static List s_BoundedPlanes = new List(); - - static HashSet s_TrackableIds = new HashSet(); - - static List s_PlanesToRemove = new List(); - - const PlaneDetectionFlags k_PlaneDetectionFlagEverything = (PlaneDetectionFlags)(-1); - } -} +using System; +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine.Serialization; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A manager for s. Creates, updates, and removes + /// GameObjects in response to detected surfaces in the physical + /// environment. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_PlaneManager)] + [DisallowMultipleComponent] + [RequireComponent(typeof(ARSessionOrigin))] + public sealed class ARPlaneManager : ARTrackableManager< + XRPlaneSubsystem, + XRPlaneSubsystemDescriptor, + BoundedPlane, + ARPlane>, IRaycaster + { + [SerializeField] + [Tooltip("If not null, instantiates this prefab for each created plane.")] + GameObject m_PlanePrefab; + + /// + /// Getter/setter for the Plane Prefab. + /// + public GameObject planePrefab + { + get { return m_PlanePrefab; } + set { m_PlanePrefab = value; } + } + + [SerializeField, PlaneDetectionModeMask] + [Tooltip("The types of planes to detect.")] + [FormerlySerializedAs("PlaneDetectionFlags")] + PlaneDetectionMode m_DetectionMode = k_PlaneDetectionModeEverything; + + /// + /// Get or set the PlaneDetectionMode to use for plane detection. + /// + public PlaneDetectionMode detectionMode + { + get + { + if (m_DetectionMode == k_PlaneDetectionModeEverything) + return PlaneDetectionMode.Horizontal | PlaneDetectionMode.Vertical; + + return m_DetectionMode; + } + set + { + m_DetectionMode = value; + + if (subsystem != null) + subsystem.planeDetectionMode = detectionMode; + } + } + + /// + /// Invoked when planes have changed (been added, updated, or removed). + /// + public event Action planesChanged; + + /// + /// Attempt to retrieve an existing by . + /// + /// The of the plane to retrieve. + /// The with , or null if it does not exist. + public ARPlane GetPlane(TrackableId trackableId) + { + ARPlane plane; + if (m_Trackables.TryGetValue(trackableId, out plane)) + return plane; + + return null; + } + + /// + /// Performs a raycast against all currently tracked planes. + /// + /// The ray, in Unity world space, to cast. + /// A mask of raycast types to perform. + /// The Allocator to use when creating the returned NativeArray. + /// + /// A new NativeArray of raycast results allocated with . + /// The caller owns the memory and is responsible for calling Dispose on the NativeArray. + /// + /// + /// + public NativeArray Raycast( + Ray ray, + TrackableType trackableTypeMask, + Allocator allocator) + { + // No plane types requested; early out. + if ((trackableTypeMask & TrackableType.Planes) == TrackableType.None) + return new NativeArray(0, allocator); + + var trackableCollection = trackables; + + // Allocate a buffer that is at least large enough to contain a hit against every plane + var hitBuffer = new NativeArray(trackableCollection.count, Allocator.Temp); + try + { + int count = 0; + foreach (var plane in trackableCollection) + { + TrackableType trackableTypes = TrackableType.None; + + var normal = plane.transform.localRotation * Vector3.up; + var infinitePlane = new Plane(normal, plane.transform.localPosition); + float distance; + if (!infinitePlane.Raycast(ray, out distance)) + continue; + + // Pose in session space + var pose = new Pose( + ray.origin + ray.direction * distance, + plane.transform.localRotation); + + if ((trackableTypeMask & TrackableType.PlaneWithinInfinity) != TrackableType.None) + trackableTypes |= TrackableType.PlaneWithinInfinity; + + // To test the rest, we need the intersection point in plane space + var hitPositionPlaneSpace3d = Quaternion.Inverse(plane.transform.localRotation) * (pose.position - plane.transform.localPosition); + var hitPositionPlaneSpace = new Vector2(hitPositionPlaneSpace3d.x, hitPositionPlaneSpace3d.z); + + var estimatedOrWithinBounds = TrackableType.PlaneWithinBounds | TrackableType.PlaneEstimated; + if ((trackableTypeMask & estimatedOrWithinBounds) != TrackableType.None) + { + var differenceFromCenter = hitPositionPlaneSpace - plane.centerInPlaneSpace; + if ((Mathf.Abs(differenceFromCenter.x) <= plane.extents.x) && + (Mathf.Abs(differenceFromCenter.y) <= plane.extents.y)) + { + trackableTypes |= (estimatedOrWithinBounds & trackableTypeMask); + } + } + + if ((trackableTypeMask & TrackableType.PlaneWithinPolygon) != TrackableType.None) + { + if (WindingNumber(hitPositionPlaneSpace, plane.boundary) != 0) + trackableTypes |= TrackableType.PlaneWithinPolygon; + } + + if (trackableTypes != TrackableType.None) + { + hitBuffer[count++] = new XRRaycastHit( + plane.trackableId, + pose, + distance, + trackableTypes); + } + } + + // Finally, copy to return value + var hitResults = new NativeArray(count, allocator); + NativeArray.Copy(hitBuffer, hitResults, count); + return hitResults; + } + finally + { + hitBuffer.Dispose(); + } + } + + static float GetCrossDirection(Vector2 a, Vector2 b) + { + return a.x * b.y - a.y * b.x; + } + + // See http://geomalgorithms.com/a03-_inclusion.html + static int WindingNumber( + Vector2 positionInPlaneSpace, + NativeArray boundaryInPlaneSpace) + { + int windingNumber = 0; + Vector2 point = positionInPlaneSpace; + for (int i = 0; i < boundaryInPlaneSpace.Length; ++i) + { + int j = (i + 1) % boundaryInPlaneSpace.Length; + Vector2 vi = boundaryInPlaneSpace[i]; + Vector2 vj = boundaryInPlaneSpace[j]; + + if (vi.y <= point.y) + { + if (vj.y > point.y) // an upward crossing + { + if (GetCrossDirection(vj - vi, point - vi) < 0f) // P left of edge + ++windingNumber; + } + // have a valid up intersect + } + else + { // y > P.y (no test needed) + if (vj.y <= point.y) // a downward crossing + { + if (GetCrossDirection(vj - vi, point - vi) > 0f) // P right of edge + --windingNumber; + } + // have a valid down intersect + } + } + + return windingNumber; + } + + protected override GameObject GetPrefab() + { + return m_PlanePrefab; + } + + protected override void OnBeforeStart() + { + subsystem.planeDetectionMode = detectionMode; + } + + protected override void OnAfterSetSessionRelativeData( + ARPlane plane, + BoundedPlane sessionRelativeData) + { + ARPlane subsumedByPlane; + if (m_Trackables.TryGetValue(sessionRelativeData.subsumedById, out subsumedByPlane)) + { + plane.subsumedBy = subsumedByPlane; + } + else + { + plane.subsumedBy = null; + } + + plane.UpdateBoundary(subsystem); + } + + protected override void OnTrackablesChanged( + List added, + List updated, + List removed) + { + if (planesChanged != null) + { + planesChanged( + new ARPlanesChangedEventArgs( + added, + updated, + removed)); + } + } + + /// + /// The name to be used for the GameObject whenever a new plane is detected. + /// + protected override string gameObjectName + { + get { return "ARPlane"; } + } + + protected override void OnEnable() + { + base.OnEnable(); + + if (subsystem != null) + { + var raycastManager = GetComponent(); + if (raycastManager != null) + raycastManager.RegisterRaycaster(this); + } + } + + protected override void OnDisable() + { + base.OnDisable(); + + var raycastManager = GetComponent(); + if (raycastManager != null) + raycastManager.UnregisterRaycaster(this); + } + + static List s_PlaneSpaceBoundary = new List(); + + const PlaneDetectionMode k_PlaneDetectionModeEverything = (PlaneDetectionMode)(-1); + } +} diff --git a/package/Runtime/AR/ARPlaneManager.cs.meta b/package/Runtime/AR/ARPlaneManager.cs.meta index 7c66ac6e5..145fadd9b 100755 --- a/package/Runtime/AR/ARPlaneManager.cs.meta +++ b/package/Runtime/AR/ARPlaneManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: e1760703bbd54c04488a8d10600262ab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: e1760703bbd54c04488a8d10600262ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlaneMeshGenerators.cs b/package/Runtime/AR/ARPlaneMeshGenerators.cs index c7c7e3600..d07071a65 100755 --- a/package/Runtime/AR/ARPlaneMeshGenerators.cs +++ b/package/Runtime/AR/ARPlaneMeshGenerators.cs @@ -1,165 +1,159 @@ -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEngine.XR.ARFoundation -{ - - /// - /// Generator functions for mesh geometery. - /// - /// - /// These static class provides ways to generate different parts of plane geometry, such as vertices, indices, normals and UVs. - /// You can use these functions to build an ARPlane Mesh object. - /// - public static class ARPlaneMeshGenerators - { - - /// - /// Generates a Mesh from the given parameters. The is assumed to be convex. - /// - /// - /// is not checked for its convexness. Concave polygons will produce incorrect results. - /// - /// The Mesh to write results to. - /// The Pose of the plane, in session space. - /// The plane's center, in plane-space. - /// The plane's normal, in plane-space. - /// The vertices of the plane's boundary, in plane-space. - /// If any triangle in the generated mesh is less than this, then the entire mesh is ignored. - /// This handles an edge case which prevents degenerate or very small triangles. Units are meters-squared. - /// True if the was generated, False otherwise. The may - /// fail to generate if it is not a valid polygon (too few vertices) or if it contains degenerate triangles (area smaller than ). - public static bool GenerateMesh(Mesh mesh, Pose pose, Vector3 center, Vector3 normal, List convexPolygon, float areaTolerance = 1e-6f) - { - if (mesh == null) - throw new ArgumentNullException("mesh"); - - if (convexPolygon == null) - throw new ArgumentNullException("convexPolygon"); - - if (convexPolygon.Count < 3) - return false; - - // Vertices - // - s_Vertices.Clear(); - s_Vertices.Capacity = convexPolygon.Count + 1; - s_Vertices.AddRange(convexPolygon); - s_Vertices.Add(center); - - // If the polygon is too small or degenerate, no mesh is created. - if (!GenerateIndices(s_Indices, s_Vertices, areaTolerance)) - return false; - - // We can't fail after this point, so it is safe to mutate the mesh - mesh.Clear(); - mesh.SetVertices(s_Vertices); - - // Indices - // - const int subMesh = 0; - const bool calculateBounds = true; - mesh.SetTriangles(s_Indices, subMesh, calculateBounds); - - // UVs - // - GenerateUvs(s_Uvs, pose, normal, s_Vertices); - mesh.SetUVs(0, s_Uvs); - - // Normals - // - // Reuse the same list for normals - var normals = s_Vertices; - for (int i = 0; i < normals.Count; ++i) - normals[i] = normal; - - mesh.SetNormals(normals); - - return true; - } - - /// - /// Generates a List of UVs from the given parameters. - /// - /// The List to write results to. - /// The Pose of the plane, in session space. - /// The plane's normal, in plane-space. - /// The vertices of the plane's boundary, in plane-space. - public static void GenerateUvs(List Uvs, Pose pose, Vector3 normal, List vertices) - { - // Get the twist rotation about the plane's normal, then apply - // its inverse to the rotation to produce the "untwisted" rotation. - // This is similar to Swing-Twist Decomposition. - var planeRotation = pose.rotation; - var rotationAxis = new Vector3(planeRotation.x, planeRotation.y, planeRotation.z); - var projection = Vector3.Project(rotationAxis, planeRotation * normal); - var normalizedTwist = (new Vector4(projection.x, projection.y, projection.z, planeRotation.w)).normalized; - var inverseTwist = new Quaternion(normalizedTwist.x, normalizedTwist.y, normalizedTwist.z, -normalizedTwist.w); - var untwistedRotation = inverseTwist * pose.rotation; - - // Compute the basis vectors for the plane in session space. - var sessionSpaceRight = untwistedRotation * Vector3.right; - var sessionSpaceForward = untwistedRotation * Vector3.forward; - - Uvs.Clear(); - foreach (var vertex in vertices) - { - var vertexInSessionSpace = pose.rotation * vertex + pose.position; - - // Project onto each axis - var uv = new Vector2( - Vector3.Dot(vertexInSessionSpace, sessionSpaceRight), - Vector3.Dot(vertexInSessionSpace, sessionSpaceForward)); - - Uvs.Add(uv); - } - } - - /// - /// Generates a List of indices from the given parameters. The is assumed to be convex. - /// - /// - /// is not checked for its convexness. Concave polygons will produce incorrect results. - /// - /// The List to write results to. - /// The vertices of the plane's boundary, in plane-space. - /// If any triangle in the generated mesh is less than this, then the entire mesh is ignored. - /// True if the indices were generated, False if a triangle whose area is less than is found. - public static bool GenerateIndices(List indices, List convexPolygon, float areaTolerance = 1e-6f) - { - // Create a triangle fan - indices.Clear(); - - var numBoundaryVertices = convexPolygon.Count - 1; - var centerIndex = numBoundaryVertices; - var areaToleranceSquared = areaTolerance * areaTolerance; - - for (int i = 0; i < numBoundaryVertices; ++i) - { - int j = (i + 1) % numBoundaryVertices; - - // Stop if the area of the triangle is too small - var a = convexPolygon[i] - convexPolygon[centerIndex]; - var b = convexPolygon[j] - convexPolygon[centerIndex]; - var areaSquared = Vector3.Cross(a, b).sqrMagnitude * 0.25f; - if (areaSquared < areaToleranceSquared) - { - return false; - } - - indices.Add(centerIndex); - indices.Add(i); - indices.Add(j); - } - - return true; - } - - // Caches to avoid reallocing Lists during calculations - static List s_Indices = new List(); - static List s_Uvs = new List(); - static List s_Vertices = new List(); - } - +using System; +using System.Collections.Generic; +using Unity.Collections; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Generator functions for mesh geometery. + /// + /// + /// These static class provides ways to generate different parts of plane geometry, such as vertices, indices, normals and UVs. + /// You can use these functions to build an ARPlane Mesh object. + /// + public static class ARPlaneMeshGenerators + { + /// + /// Generates a Mesh from the given parameters. The is assumed to be convex. + /// + /// + /// is not checked for its convexness. Concave polygons will produce incorrect results. + /// + /// The Mesh to write results to. + /// The vertices of the plane's boundary, in plane-space. + /// If any triangle in the generated mesh is less than this, then the entire mesh is ignored. + /// This handles an edge case which prevents degenerate or very small triangles. Units are meters-squared. + /// True if the was generated, False otherwise. The may + /// fail to generate if it is not a valid polygon (too few vertices) or if it contains degenerate triangles (area smaller than ). + public static bool GenerateMesh(Mesh mesh, Pose pose, NativeArray convexPolygon, float areaTolerance = 1e-6f) + { + if (mesh == null) + throw new ArgumentNullException("mesh"); + + if (convexPolygon.Length < 3) + return false; + + // Vertices + s_Vertices.Clear(); + var center = Vector3.zero; + foreach (var point2 in convexPolygon) + { + var point3 = new Vector3(point2.x, 0, point2.y); + center += point3; + s_Vertices.Add(point3); + } + center /= convexPolygon.Length; + s_Vertices.Add(center); + + // If the polygon is too small or degenerate, no mesh is created. + if (!GenerateIndices(s_Indices, s_Vertices, areaTolerance)) + return false; + + // We can't fail after this point, so it is safe to mutate the mesh + mesh.Clear(); + mesh.SetVertices(s_Vertices); + + // Indices + const int subMesh = 0; + const bool calculateBounds = true; + mesh.SetTriangles(s_Indices, subMesh, calculateBounds); + + // UVs + GenerateUvs(s_Uvs, pose, s_Vertices); + mesh.SetUVs(0, s_Uvs); + + // Normals + // Reuse the same list for normals + var normals = s_Vertices; + for (int i = 0; i < normals.Count; ++i) + normals[i] = Vector3.up; + + mesh.SetNormals(normals); + + return true; + } + + /// + /// Generates a List of UVs from the given parameters. + /// + /// The List to write results to. + /// The vertices of the plane's boundary, in plane-space. + public static void GenerateUvs(List Uvs, Pose pose, List vertices) + { + // Get the twist rotation about the plane's normal, then apply + // its inverse to the rotation to produce the "untwisted" rotation. + // This is similar to Swing-Twist Decomposition. + var planeRotation = pose.rotation; + var rotationAxis = new Vector3(planeRotation.x, planeRotation.y, planeRotation.z); + var projection = Vector3.Project(rotationAxis, planeRotation * Vector3.up); + var normalizedTwist = (new Vector4(projection.x, projection.y, projection.z, planeRotation.w)).normalized; + var inverseTwist = new Quaternion(normalizedTwist.x, normalizedTwist.y, normalizedTwist.z, -normalizedTwist.w); + var untwistedRotation = inverseTwist * pose.rotation; + + // Compute the basis vectors for the plane in session space. + var sessionSpaceRight = untwistedRotation * Vector3.right; + var sessionSpaceForward = untwistedRotation * Vector3.forward; + + Uvs.Clear(); + foreach (var vertex in vertices) + { + var vertexInSessionSpace = pose.rotation * vertex + pose.position; + + // Project onto each axis + var uv = new Vector2( + Vector3.Dot(vertexInSessionSpace, sessionSpaceRight), + Vector3.Dot(vertexInSessionSpace, sessionSpaceForward)); + + Uvs.Add(uv); + } + } + + /// + /// Generates a List of indices from the given parameters, forming a triangle fan. + /// The is assumed to be convex. + /// + /// + /// is not checked for its convexness. Concave polygons will produce incorrect results. + /// + /// The List to write results to. + /// The vertices of the plane's boundary, in plane-space. + /// If any triangle in the generated mesh is less than this, then the entire mesh is ignored. + /// True if the indices were generated, False if a triangle whose area is less than is found. + public static bool GenerateIndices(List indices, List convexPolygon, float areaTolerance = 1e-6f) + { + indices.Clear(); + + var numBoundaryVertices = convexPolygon.Count - 1; + var centerIndex = numBoundaryVertices; + var areaToleranceSquared = areaTolerance * areaTolerance; + + for (int i = 0; i < numBoundaryVertices; ++i) + { + int j = (i + 1) % numBoundaryVertices; + + // Stop if the area of the triangle is too small + var a = convexPolygon[i] - convexPolygon[centerIndex]; + var b = convexPolygon[j] - convexPolygon[centerIndex]; + + // Area is the magnitude of the normal / 2, so the + // area squared is the magnitude squared / 4 + var areaSquared = Vector3.Cross(a, b).sqrMagnitude * 0.25f; + if (areaSquared < areaToleranceSquared) + return false; + + indices.Add(centerIndex); + indices.Add(i); + indices.Add(j); + } + + return true; + } + + // Caches to avoid reallocing Lists during calculations + static List s_Indices = new List(); + + static List s_Uvs = new List(); + + static List s_Vertices = new List(); + } } \ No newline at end of file diff --git a/package/Runtime/AR/ARPlaneMeshGenerators.cs.meta b/package/Runtime/AR/ARPlaneMeshGenerators.cs.meta index ab7d1164a..b2bb3d4ff 100755 --- a/package/Runtime/AR/ARPlaneMeshGenerators.cs.meta +++ b/package/Runtime/AR/ARPlaneMeshGenerators.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: e1d3b0f541190fc4995f7c69c961157f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: e1d3b0f541190fc4995f7c69c961157f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlaneMeshVisualizer.cs b/package/Runtime/AR/ARPlaneMeshVisualizer.cs index 3af57cc91..1c43efa4f 100755 --- a/package/Runtime/AR/ARPlaneMeshVisualizer.cs +++ b/package/Runtime/AR/ARPlaneMeshVisualizer.cs @@ -1,157 +1,136 @@ -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Generates a mesh for an . - /// - /// - /// If this GameObject has a MeshFilter and/or MeshCollider, - /// this component will generate a mesh from the underlying BoundedPlane. - /// - /// It will also update a LineRenderer with the boundary points, if present. - /// - [RequireComponent(typeof(ARPlane))] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPlaneMeshVisualizer.html")] - public sealed class ARPlaneMeshVisualizer : MonoBehaviour - { - /// - /// Get the Mesh that this visualizer creates and manages. - /// - public Mesh mesh { get; private set; } - - /// - /// Invoked after has been regenerated, but before - /// any components have been updated to use the new Mesh. - /// - public event Action meshUpdated; - - void OnBoundaryChanged(ARPlaneBoundaryChangedEventArgs eventArgs) - { - // Ignore subsumed planes - if (m_Plane.boundedPlane.SubsumedById != TrackableId.InvalidId) - { - DisableComponents(); - return; - } - - var center = eventArgs.center; - var normal = eventArgs.normal; - var polygon = eventArgs.convexBoundary; - - if (!ARPlaneMeshGenerators.GenerateMesh(mesh, m_Plane.boundedPlane.Pose, center, normal, polygon)) - return; - - if (meshUpdated != null) - meshUpdated(this); - - var lineRenderer = GetComponent(); - if (lineRenderer != null) - { - lineRenderer.positionCount = polygon.Count; - for (int i = 0; i < polygon.Count; ++i) - { - lineRenderer.SetPosition(i, polygon[i]); - } - } - - var meshFilter = GetComponent(); - if (meshFilter != null) - meshFilter.sharedMesh = mesh; - - var meshCollider = GetComponent(); - if (meshCollider != null) - meshCollider.sharedMesh = mesh; - } - - void DisableComponents() - { - enabled = false; - - var meshCollider = GetComponent(); - if (meshCollider != null) - meshCollider.enabled = false; - - UpdateVisibility(); - } - - void SetVisible(bool visible) - { - var meshRenderer = GetComponent(); - if (meshRenderer != null) - meshRenderer.enabled = visible; - - var lineRenderer = GetComponent(); - if (lineRenderer != null) - lineRenderer.enabled = visible; - } - - void UpdateVisibility() - { - var visible = enabled && - (m_Plane.trackingState != TrackingState.Unavailable) && - (ARSubsystemManager.systemState > ARSystemState.Ready); - - SetVisible(visible); - } - - void OnUpdated(ARPlane plane) - { - UpdateVisibility(); - } - - void OnSystemStateChanged(ARSystemStateChangedEventArgs eventArgs) - { - UpdateVisibility(); - } - - void Awake() - { - mesh = new Mesh(); - m_Plane = GetComponent(); - } - - void OnEnable() - { - m_Plane.boundaryChanged += OnBoundaryChanged; - m_Plane.updated += OnUpdated; - ARSubsystemManager.systemStateChanged += OnSystemStateChanged; - UpdateVisibility(); - } - - void OnDisable() - { - m_Plane.boundaryChanged -= OnBoundaryChanged; - m_Plane.updated -= OnUpdated; - ARSubsystemManager.systemStateChanged -= OnSystemStateChanged; - UpdateVisibility(); - } - - void Update() - { - if (transform.hasChanged) - { - var lineRenderer = GetComponent(); - if (lineRenderer != null) - { - if (!m_InitialLineWidthMultiplier.HasValue) - m_InitialLineWidthMultiplier = lineRenderer.widthMultiplier; - - lineRenderer.widthMultiplier = m_InitialLineWidthMultiplier.Value * transform.lossyScale.x; - } - else - { - m_InitialLineWidthMultiplier = null; - } - - transform.hasChanged = false; - } - } - - float? m_InitialLineWidthMultiplier; - - ARPlane m_Plane; - } -} +using System; +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Generates a mesh for an . + /// + /// + /// If this GameObject has a MeshFilter and/or MeshCollider, + /// this component will generate a mesh from the underlying BoundedPlane. + /// + /// It will also update a LineRenderer with the boundary points, if present. + /// + [RequireComponent(typeof(ARPlane))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARPlaneMeshVisualizer.html")] + public sealed class ARPlaneMeshVisualizer : MonoBehaviour + { + /// + /// Get the Mesh that this visualizer creates and manages. + /// + public Mesh mesh { get; private set; } + + void OnBoundaryChanged(ARPlaneBoundaryChangedEventArgs eventArgs) + { + var boundary = m_Plane.boundary; + if (!ARPlaneMeshGenerators.GenerateMesh(mesh, new Pose(transform.localPosition, transform.localRotation), boundary)) + return; + + var lineRenderer = GetComponent(); + if (lineRenderer != null) + { + lineRenderer.positionCount = boundary.Length; + for (int i = 0; i < boundary.Length; ++i) + { + var point2 = boundary[i]; + lineRenderer.SetPosition(i, new Vector3(point2.x, 0, point2.y)); + } + } + + var meshFilter = GetComponent(); + if (meshFilter != null) + meshFilter.sharedMesh = mesh; + + var meshCollider = GetComponent(); + if (meshCollider != null) + meshCollider.sharedMesh = mesh; + } + + void DisableComponents() + { + enabled = false; + + var meshCollider = GetComponent(); + if (meshCollider != null) + meshCollider.enabled = false; + + UpdateVisibility(); + } + + void SetVisible(bool visible) + { + var meshRenderer = GetComponent(); + if (meshRenderer != null) + meshRenderer.enabled = visible; + + var lineRenderer = GetComponent(); + if (lineRenderer != null) + lineRenderer.enabled = visible; + } + + void UpdateVisibility() + { + var visible = enabled && + (m_Plane.trackingState != TrackingState.None) && + (ARSession.state > ARSessionState.Ready) && + (m_Plane.subsumedBy == null); + + SetVisible(visible); + } + + void Awake() + { + mesh = new Mesh(); + m_Plane = GetComponent(); + } + + void OnEnable() + { + m_Plane.boundaryChanged += OnBoundaryChanged; + UpdateVisibility(); + OnBoundaryChanged(default(ARPlaneBoundaryChangedEventArgs)); + } + + void OnDisable() + { + m_Plane.boundaryChanged -= OnBoundaryChanged; + UpdateVisibility(); + } + + void Update() + { + if (transform.hasChanged) + { + var lineRenderer = GetComponent(); + if (lineRenderer != null) + { + if (!m_InitialLineWidthMultiplier.HasValue) + m_InitialLineWidthMultiplier = lineRenderer.widthMultiplier; + + lineRenderer.widthMultiplier = m_InitialLineWidthMultiplier.Value * transform.lossyScale.x; + } + else + { + m_InitialLineWidthMultiplier = null; + } + + transform.hasChanged = false; + } + + if (m_Plane.subsumedBy != null) + { + DisableComponents(); + } + else + { + UpdateVisibility(); + } + } + + float? m_InitialLineWidthMultiplier; + + ARPlane m_Plane; + } +} diff --git a/package/Runtime/AR/ARPlaneMeshVisualizer.cs.meta b/package/Runtime/AR/ARPlaneMeshVisualizer.cs.meta index 1b55c8ad2..7bc0bbba4 100755 --- a/package/Runtime/AR/ARPlaneMeshVisualizer.cs.meta +++ b/package/Runtime/AR/ARPlaneMeshVisualizer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 3d180956a54db4646a1c6342921672ad -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 3d180956a54db4646a1c6342921672ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPlanesChangedEventArgs.cs b/package/Runtime/AR/ARPlanesChangedEventArgs.cs index e7634fce2..7169ab16f 100755 --- a/package/Runtime/AR/ARPlanesChangedEventArgs.cs +++ b/package/Runtime/AR/ARPlanesChangedEventArgs.cs @@ -1,89 +1,89 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Event arguments for the event. - /// - public struct ARPlanesChangedEventArgs : IEquatable - { - /// - /// The list of s added since the last event. - /// - public List added { get; private set; } - - /// - /// The list of s udpated since the last event. - /// - public List updated { get; private set; } - - /// - /// The list of s removed since the last event. - /// - public List removed { get; private set; } - - /// - /// Constructs an . - /// - /// The list of s added since the last event. - /// The list of s updated since the last event. - /// The list of s removed since the last event. - public ARPlanesChangedEventArgs( - List added, - List updated, - List removed) - { - this.added = added; - this.updated = updated; - this.removed = removed; - } - - public override int GetHashCode() - { - unchecked - { - int hash = 0; - hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); - hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); - hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); - return hash; - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARPlanesChangedEventArgs)) - return false; - - return Equals((ARPlanesChangedEventArgs)obj); - } - - public override string ToString() - { - return string.Format("Added: {0}, Updated: {1}, Removed: {2}", - added == null ? 0 : added.Count, - updated == null ? 0 : updated.Count, - removed == null ? 0 : removed.Count); - - } - - public bool Equals(ARPlanesChangedEventArgs other) - { - return - (added == other.added) && - (updated == other.updated) && - (removed == other.removed); - } - - public static bool operator ==(ARPlanesChangedEventArgs lhs, ARPlanesChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARPlanesChangedEventArgs lhs, ARPlanesChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Event arguments for the event. + /// + public struct ARPlanesChangedEventArgs : IEquatable + { + /// + /// The list of s added since the last event. + /// + public List added { get; private set; } + + /// + /// The list of s udpated since the last event. + /// + public List updated { get; private set; } + + /// + /// The list of s removed since the last event. + /// + public List removed { get; private set; } + + /// + /// Constructs an . + /// + /// The list of s added since the last event. + /// The list of s updated since the last event. + /// The list of s removed since the last event. + public ARPlanesChangedEventArgs( + List added, + List updated, + List removed) + { + this.added = added; + this.updated = updated; + this.removed = removed; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 0; + hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); + hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); + hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARPlanesChangedEventArgs)) + return false; + + return Equals((ARPlanesChangedEventArgs)obj); + } + + public override string ToString() + { + return string.Format("Added: {0}, Updated: {1}, Removed: {2}", + added == null ? 0 : added.Count, + updated == null ? 0 : updated.Count, + removed == null ? 0 : removed.Count); + + } + + public bool Equals(ARPlanesChangedEventArgs other) + { + return + (added == other.added) && + (updated == other.updated) && + (removed == other.removed); + } + + public static bool operator ==(ARPlanesChangedEventArgs lhs, ARPlanesChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARPlanesChangedEventArgs lhs, ARPlanesChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARPlanesChangedEventArgs.cs.meta b/package/Runtime/AR/ARPlanesChangedEventArgs.cs.meta index a8791d873..d89e43a9f 100755 --- a/package/Runtime/AR/ARPlanesChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARPlanesChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 4c1d505cf04abe44f932e086699662a6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 4c1d505cf04abe44f932e086699662a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloud.cs b/package/Runtime/AR/ARPointCloud.cs index a03aebca3..7409b4f15 100755 --- a/package/Runtime/AR/ARPointCloud.cs +++ b/package/Runtime/AR/ARPointCloud.cs @@ -1,71 +1,103 @@ -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Represents a detected point cloud, aka feature points. - /// - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPointCloud.html")] - public class ARPointCloud : MonoBehaviour - { - /// - /// Invoked when the point cloud is updated. - /// - public event Action updated; - - /// - /// The last frame during which the point cloud was updated. - /// - /// - /// This is consistent with the value you get from Time.frameCount - /// - public int lastUpdatedFrame - { - get - { - return depthSubsystem.LastUpdatedFrame; - } - } - - /// - /// Replaces the contents of with the feature points in Unity world space. - /// - /// A List of Vector3s. The contents are replaced with the current point cloud. - /// Which coordinate system to use. Space.Self refers to session space, - /// while Space.World refers to Unity world space. The default is Space.World. - public void GetPoints(List points, Space space = Space.World) - { - depthSubsystem.GetPoints(points); - - if (space == Space.World) - transform.parent.TransformPointList(points); - } - - /// - /// Gets the confidence values for each point in the point cloud. - /// - /// A List of floats representing the confidence values for each point - /// in the point cloud. The contents are replaced with the current confidence values. - public void GetConfidence(List confidence) - { - depthSubsystem.GetConfidence(confidence); - } - - /// - /// The XR Subsystem providing the point cloud data. - /// - XRDepthSubsystem depthSubsystem - { - get { return ARSubsystemManager.depthSubsystem; } - } - - internal void OnUpdated() - { - if (updated != null) - updated(this); - } - } -} +using System; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Represents a detected point cloud, aka feature points. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_PointCloud)] + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARPointCloud.html")] + public class ARPointCloud : ARTrackable + { + /// + /// Invoked whenever the point cloud is updated. + /// + public event Action updated; + + /// + /// An array of positions for each point in the point cloud. + /// This array is parallel to and + /// . Check for existence with + /// positions.IsCreated. Positions are provided in + /// point cloud space, that is, relative to this 's + /// local position and rotation. + /// + public NativeArray positions + { + get + { + return GetUndisposable(m_Data.positions); + } + } + + /// + /// An array of identifiers for each point in the point cloud. + /// This array is parallel to and + /// . Check for existence with + /// identifiers.IsCreated. + /// + public NativeArray identifiers + { + get + { + return GetUndisposable(m_Data.identifiers); + } + } + + /// + /// An array of confidence values for each point in the point cloud + /// ranging from 0..1. + /// This array is parallel to and + /// . Check for existence with + /// confidenceValues.IsCreated. + /// + public NativeArray confidenceValues + { + get + { + return GetUndisposable(m_Data.confidenceValues); + } + } + + void Update() + { + if (m_PointsUpdated && updated != null) + { + m_PointsUpdated = false; + updated(new ARPointCloudUpdatedEventArgs()); + } + } + + void OnDestroy() + { + m_Data.Dispose(); + } + + // Creates an alias to the same array, but the caller cannot Dispose it. + unsafe NativeArray GetUndisposable(NativeArray disposable) where T : struct + { + if (!disposable.IsCreated) + return default(NativeArray); + + return NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray( + disposable.GetUnsafePtr(), + disposable.Length, + Allocator.None); + } + + internal void UpdateData(XRDepthSubsystem subsystem) + { + m_Data.Dispose(); + m_Data = subsystem.GetPointCloudData(trackableId, Allocator.Persistent); + m_PointsUpdated = m_Data.positions.IsCreated; + } + + XRPointCloudData m_Data; + + bool m_PointsUpdated = false; + } +} diff --git a/package/Runtime/AR/ARPointCloud.cs.meta b/package/Runtime/AR/ARPointCloud.cs.meta index fd4a84186..b5d1defcd 100755 --- a/package/Runtime/AR/ARPointCloud.cs.meta +++ b/package/Runtime/AR/ARPointCloud.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: afcab4e7938ae724a8a59ecac3580761 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: afcab4e7938ae724a8a59ecac3580761 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloudChangedEventArgs.cs b/package/Runtime/AR/ARPointCloudChangedEventArgs.cs index 4739e5013..95a11e5ea 100755 --- a/package/Runtime/AR/ARPointCloudChangedEventArgs.cs +++ b/package/Runtime/AR/ARPointCloudChangedEventArgs.cs @@ -1,81 +1,81 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Event arguments for the event. - /// - public struct ARPointCloudChangedEventArgs : IEquatable - { - /// - /// The list of s added since the last event. - /// - public List added { get; private set; } - - /// - /// The list of s udpated since the last event. - /// - public List updated { get; private set; } - - /// - /// The list of s removed since the last event. - /// - public List removed { get; private set; } - - /// - /// Constructs an . - /// - /// The list of s added since the last event. - /// The list of s updated since the last event. - /// The list of s removed since the last event. - public ARPointCloudChangedEventArgs( - List added, - List updated, - List removed) - { - this.added = added; - this.updated = updated; - this.removed = removed; - } - public override int GetHashCode() - { - unchecked - { - int hash = 0; - hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); - hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); - hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); - return hash; - } - } - public override bool Equals(object obj) - { - if (!(obj is ARPointCloudChangedEventArgs)) - return false; - return Equals((ARPointCloudChangedEventArgs)obj); - } - public override string ToString() - { - return string.Format("Added: {0}, Updated: {1}, Removed: {2}", - added == null ? 0 : added.Count, - updated == null ? 0 : updated.Count, - removed == null ? 0 : removed.Count); - } - public bool Equals(ARPointCloudChangedEventArgs other) - { - return - (added == other.added) && - (updated == other.updated) && - (removed == other.removed); - } - public static bool operator ==(ARPointCloudChangedEventArgs lhs, ARPointCloudChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - public static bool operator !=(ARPointCloudChangedEventArgs lhs, ARPointCloudChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } +using System; +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Event arguments for the event. + /// + public struct ARPointCloudChangedEventArgs : IEquatable + { + /// + /// The list of s added since the last event. + /// + public List added { get; private set; } + + /// + /// The list of s udpated since the last event. + /// + public List updated { get; private set; } + + /// + /// The list of s removed since the last event. + /// + public List removed { get; private set; } + + /// + /// Constructs an . + /// + /// The list of s added since the last event. + /// The list of s updated since the last event. + /// The list of s removed since the last event. + public ARPointCloudChangedEventArgs( + List added, + List updated, + List removed) + { + this.added = added; + this.updated = updated; + this.removed = removed; + } + public override int GetHashCode() + { + unchecked + { + int hash = 0; + hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); + hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); + hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); + return hash; + } + } + public override bool Equals(object obj) + { + if (!(obj is ARPointCloudChangedEventArgs)) + return false; + return Equals((ARPointCloudChangedEventArgs)obj); + } + public override string ToString() + { + return string.Format("Added: {0}, Updated: {1}, Removed: {2}", + added == null ? 0 : added.Count, + updated == null ? 0 : updated.Count, + removed == null ? 0 : removed.Count); + } + public bool Equals(ARPointCloudChangedEventArgs other) + { + return + (added == other.added) && + (updated == other.updated) && + (removed == other.removed); + } + public static bool operator ==(ARPointCloudChangedEventArgs lhs, ARPointCloudChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + public static bool operator !=(ARPointCloudChangedEventArgs lhs, ARPointCloudChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } } \ No newline at end of file diff --git a/package/Runtime/AR/ARPointCloudChangedEventArgs.cs.meta b/package/Runtime/AR/ARPointCloudChangedEventArgs.cs.meta index 837870a8f..671bef664 100755 --- a/package/Runtime/AR/ARPointCloudChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARPointCloudChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 18506283f6e884a4598c794c1247ff3c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 18506283f6e884a4598c794c1247ff3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloudManager.cs b/package/Runtime/AR/ARPointCloudManager.cs index e62424557..4ad4e891c 100755 --- a/package/Runtime/AR/ARPointCloudManager.cs +++ b/package/Runtime/AR/ARPointCloudManager.cs @@ -1,100 +1,270 @@ -using System; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Creates and updates a GameObject under the 's TrackablesParent - /// to represent a point cloud. - /// - /// When enabled, this component subscribes to event. - /// If this component is disabled, and there are no other subscribers to that event, - /// point clouds will be disabled. - /// - [RequireComponent(typeof(ARSessionOrigin))] - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPointCloudManager.html")] - public sealed class ARPointCloudManager : MonoBehaviour - { - [SerializeField] - [Tooltip("If not null, instantiates this prefab for the created point cloud.")] - GameObject m_PointCloudPrefab; - - /// - /// Getter/setter for the Point Cloud Prefab. - /// - public GameObject pointCloudPrefab - { - get { return m_PointCloudPrefab; } - set { m_PointCloudPrefab = value; } - } - - /// - /// Getter for the instantiated . - /// - public ARPointCloud pointCloud { get; private set; } - - /// - /// Raised each time the is updated. - /// - public event Action pointCloudUpdated; - - void Awake() - { - m_SessionOrigin = GetComponent(); - } - - void OnEnable() - { - ARSubsystemManager.pointCloudUpdated += OnPointCloudUpdated; - ARSubsystemManager.sessionDestroyed += OnSessionDestroyed; - } - - void OnDisable() - { - ARSubsystemManager.pointCloudUpdated -= OnPointCloudUpdated; - ARSubsystemManager.sessionDestroyed -= OnSessionDestroyed; - } - - void OnSessionDestroyed() - { - if (pointCloud != null) - { - Destroy(pointCloud.gameObject); - pointCloud = null; - } - } - - void OnPointCloudUpdated(PointCloudUpdatedEventArgs eventArgs) - { - if (pointCloud == null) - { - GameObject newGameObject; - if (pointCloudPrefab != null) - { - newGameObject = Instantiate(pointCloudPrefab, m_SessionOrigin.trackablesParent); - newGameObject.transform.localPosition = Vector3.zero; - newGameObject.transform.localRotation = Quaternion.identity; - newGameObject.transform.localScale = Vector3.one; - } - else - { - newGameObject = new GameObject(); - newGameObject.transform.SetParent(m_SessionOrigin.trackablesParent, false); - newGameObject.layer = gameObject.layer; - } - - pointCloud = newGameObject.GetComponent(); - if (pointCloud == null) - pointCloud = newGameObject.AddComponent(); - } - - pointCloud.OnUpdated(); - - if (pointCloudUpdated != null) - pointCloudUpdated(new ARPointCloudUpdatedEventArgs(pointCloud)); - } - - ARSessionOrigin m_SessionOrigin; - } -} +using System; +using System.Collections.Generic; +using Unity.Collections; +using Unity.Jobs; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A manager for s. Uses the XRDepthSubsystem + /// to recognize and track depth data in the physical environment. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_PointCloudManager)] + [RequireComponent(typeof(ARSessionOrigin))] + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARPointCloudManager.html")] + public class ARPointCloudManager : ARTrackableManager< + XRDepthSubsystem, + XRDepthSubsystemDescriptor, + XRPointCloud, + ARPointCloud>, IRaycaster + { + [SerializeField] + [Tooltip("If not null, instantiates this prefab for each point cloud.")] + GameObject m_PointCloudPrefab; + + /// + /// Getter/setter for the Point Cloud Prefab. + /// + public GameObject pointCloudPrefab + { + get { return m_PointCloudPrefab; } + set { m_PointCloudPrefab = value; } + } + + /// Invoked once per frame with information about the s that have changed, i.e., been added, updated, or removed. + /// This happens just before s are destroyed, so you can set ARTrackedObject.destroyOnRemoval to false + /// from this event to suppress this behavior. + public event Action pointCloudsChanged; + + protected override void OnEnable() + { + base.OnEnable(); + + if (subsystem != null) + { + var raycastManager = GetComponent(); + if (raycastManager != null) + raycastManager.RegisterRaycaster(this); + } + } + + protected override void OnDisable() + { + base.OnDisable(); + + var raycastManager = GetComponent(); + if (raycastManager != null) + raycastManager.UnregisterRaycaster(this); + } + + /// + /// ARTrackableManager interface. + /// + protected override GameObject GetPrefab() + { + return m_PointCloudPrefab; + } + + /// + /// The name to be used for the GameObject whenever a new Object is detected. + /// + protected override string gameObjectName + { + get { return "ARPointCloud"; } + } + + protected override void OnAfterSetSessionRelativeData( + ARPointCloud pointCloud, + XRPointCloud sessionRelativeData) + { + pointCloud.UpdateData(subsystem); + } + + /// + /// Invokes the event. + /// + /// A list of objects added this frame. + /// A list of objects updated this frame. + /// A list of objects removed this frame. + protected override void OnTrackablesChanged( + List added, + List updated, + List removed) + { + if (pointCloudsChanged != null) + pointCloudsChanged( + new ARPointCloudChangedEventArgs( + added, + updated, + removed)); + } + + /// + /// Implementation for the IRaycaster interface. Raycasts against every point cloud. + /// + /// A Ray, in session space. + /// The type of trackables to raycast against. + /// If TrackableType.FeaturePoint is not set, this method returns an empty array. + /// The allocator to use for the returned NativeArray. + /// A new NativeArray, allocated using , containing + /// a list of XRRaycastHits of points hit by the raycast. + public NativeArray Raycast( + Ray rayInSessionSpace, + TrackableType trackableTypeMask, + Allocator allocator) + { + if ((trackableTypeMask & TrackableType.FeaturePoint) == TrackableType.None) + return new NativeArray(0, allocator); + + // TODO: Expose this as a property + float raycastAngleInRadians = Mathf.Deg2Rad * 5f; + + var trackableCollection = trackables; + + var allHits = new NativeArray(0, allocator); + + foreach (var pointCloud in trackableCollection) + { + var sessionSpacePose = new Pose( + pointCloud.transform.localPosition, + pointCloud.transform.localRotation); + + var invRotation = Quaternion.Inverse(sessionSpacePose.rotation); + + // Get the ray in "point cloud space", i.e., relative to the point cloud's local transform + var ray = new Ray( + invRotation * (rayInSessionSpace.origin - sessionSpacePose.position), + invRotation * rayInSessionSpace.direction); + + // Collect the points in the point cloud + var points = pointCloud.positions; + + // Perform the raycast against each point + var infos = new NativeArray(points.Length, Allocator.TempJob); + var raycastJob = new PointCloudRaycastJob + { + points = points, + ray = ray, + infoOut = infos + }; + var raycastHandle = raycastJob.Schedule(infos.Length, 1); + + // Collect the hits + using (var hitBuffer = new NativeArray(infos.Length, Allocator.TempJob)) + { + var collectResultsJob = new PointCloudRaycastCollectResultsJob + { + points = points, + infos = infos, + hits = hitBuffer, + cosineThreshold = Mathf.Cos(raycastAngleInRadians * .5f), + pose = sessionSpacePose, + trackableId = pointCloud.trackableId, + count = new NativeArray(1, Allocator.TempJob) + }; + var collectResultsHandle = collectResultsJob.Schedule(raycastHandle); + + // Wait for it to finish + collectResultsHandle.Complete(); + + // Read out the count + var count = collectResultsJob.count[0]; + + // Done with native arrays + infos.Dispose(); + points.Dispose(); + collectResultsJob.count.Dispose(); + + // Copy out the results + Append(ref allHits, hitBuffer, count, allocator); + } + } + + return allHits; + } + + static void Append( + ref NativeArray currentArray, + NativeArray arrayToAppend, + int lengthToCopy, + Allocator allocator) where T : struct + { + var dstArray = new NativeArray(currentArray.Length + lengthToCopy, allocator); + NativeArray.Copy(currentArray, dstArray); + NativeArray.Copy(arrayToAppend, 0, dstArray, currentArray.Length, lengthToCopy); + currentArray.Dispose(); + currentArray = dstArray; + } + + struct PointCloudRaycastInfo + { + public float distance; + public float cosineAngleWithRay; + } + + struct PointCloudRaycastJob : IJobParallelFor + { + [ReadOnly] + public NativeArray points; + + [WriteOnly] + public NativeArray infoOut; + + public Ray ray; + + public void Execute(int i) + { + var originToPoint = points[i] - ray.origin; + float distance = originToPoint.magnitude; + var info = new PointCloudRaycastInfo + { + distance = distance, + cosineAngleWithRay = Vector3.Dot(originToPoint, ray.direction) / distance + }; + + infoOut[i] = info; + } + } + + struct PointCloudRaycastCollectResultsJob : IJob + { + [ReadOnly] + public NativeArray points; + + [ReadOnly] + public NativeArray infos; + + [WriteOnly] + public NativeArray hits; + + [WriteOnly] + public NativeArray count; + + public float cosineThreshold; + + public Pose pose; + + public TrackableId trackableId; + + public void Execute() + { + var hitIndex = 0; + for (int i = 0; i < points.Length; ++i) + { + if (infos[i].cosineAngleWithRay >= cosineThreshold) + { + hits[hitIndex++] = new XRRaycastHit( + trackableId, + new Pose(pose.rotation * points[i] + pose.position, Quaternion.identity), + infos[i].distance, + TrackableType.FeaturePoint); + } + } + + count[0] = hitIndex; + } + } + } +} diff --git a/package/Runtime/AR/ARPointCloudManager.cs.meta b/package/Runtime/AR/ARPointCloudManager.cs.meta index 0b14820cd..dd1ceb6e9 100755 --- a/package/Runtime/AR/ARPointCloudManager.cs.meta +++ b/package/Runtime/AR/ARPointCloudManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 7ab0e80cee9cc1d44928bfe488dd1e2d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 7ab0e80cee9cc1d44928bfe488dd1e2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloudMeshVisualizer.cs b/package/Runtime/AR/ARPointCloudMeshVisualizer.cs index 6ba0bfeab..aa2c15d88 100755 --- a/package/Runtime/AR/ARPointCloudMeshVisualizer.cs +++ b/package/Runtime/AR/ARPointCloudMeshVisualizer.cs @@ -1,81 +1,82 @@ -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Renders an as a Mesh with MeshTopology.Points. - /// - [RequireComponent(typeof(ARPointCloud))] - public sealed class ARPointCloudMeshVisualizer : MonoBehaviour - { - /// - /// Get the Mesh that this visualizer creates and manages. - /// - public Mesh mesh { get; private set; } - - void OnPointCloudChanged(ARPointCloud pointCloud) - { - var points = s_Vertices; - pointCloud.GetPoints(points, Space.Self); - - mesh.Clear(); - mesh.SetVertices(points); - - var indices = new int[points.Count]; - for (int i = 0; i < points.Count; ++i) - { - indices[i] = i; - } - - mesh.SetIndices(indices, MeshTopology.Points, 0); - - var meshFilter = GetComponent(); - if (meshFilter != null) - meshFilter.sharedMesh = mesh; - } - - void Awake() - { - mesh = new Mesh(); - m_PointCloud = GetComponent(); - } - - void OnEnable() - { - m_PointCloud.updated += OnPointCloudChanged; - ARSubsystemManager.systemStateChanged += OnSystemStateChanged; - UpdateVisibility(); - } - - void OnDisable() - { - m_PointCloud.updated -= OnPointCloudChanged; - ARSubsystemManager.systemStateChanged -= OnSystemStateChanged; - UpdateVisibility(); - } - - void OnSystemStateChanged(ARSystemStateChangedEventArgs eventArgs) - { - UpdateVisibility(); - } - - void UpdateVisibility() - { - var visible = enabled && - (ARSubsystemManager.systemState == ARSystemState.SessionTracking); - - SetVisible(visible); - } - - void SetVisible(bool visible) - { - var meshRenderer = GetComponent(); - if (meshRenderer != null) - meshRenderer.enabled = visible; - } - - ARPointCloud m_PointCloud; - - static List s_Vertices = new List(); - } -} +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Renders an as a Mesh with MeshTopology.Points. + /// + [RequireComponent(typeof(ARPointCloud))] + public sealed class ARPointCloudMeshVisualizer : MonoBehaviour + { + /// + /// Get the Mesh that this visualizer creates and manages. + /// + public Mesh mesh { get; private set; } + + void OnPointCloudChanged(ARPointCloudUpdatedEventArgs eventArgs) + { + s_Vertices.Clear(); + foreach (var point in m_PointCloud.positions) + s_Vertices.Add(point); + + mesh.Clear(); + mesh.SetVertices(s_Vertices); + + var indices = new int[s_Vertices.Count]; + for (int i = 0; i < s_Vertices.Count; ++i) + { + indices[i] = i; + } + + mesh.SetIndices(indices, MeshTopology.Points, 0); + + var meshFilter = GetComponent(); + if (meshFilter != null) + meshFilter.sharedMesh = mesh; + } + + void Awake() + { + mesh = new Mesh(); + m_PointCloud = GetComponent(); + } + + void OnEnable() + { + m_PointCloud.updated += OnPointCloudChanged; + UpdateVisibility(); + } + + void OnDisable() + { + m_PointCloud.updated -= OnPointCloudChanged; + UpdateVisibility(); + } + + void Update() + { + UpdateVisibility(); + } + + void UpdateVisibility() + { + var visible = + enabled && + (m_PointCloud.trackingState != TrackingState.None); + + SetVisible(visible); + } + + void SetVisible(bool visible) + { + var meshRenderer = GetComponent(); + if (meshRenderer != null) + meshRenderer.enabled = visible; + } + + ARPointCloud m_PointCloud; + + static List s_Vertices = new List(); + } +} diff --git a/package/Runtime/AR/ARPointCloudMeshVisualizer.cs.meta b/package/Runtime/AR/ARPointCloudMeshVisualizer.cs.meta index 43bab281b..0bd41dc09 100755 --- a/package/Runtime/AR/ARPointCloudMeshVisualizer.cs.meta +++ b/package/Runtime/AR/ARPointCloudMeshVisualizer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 0865ed1da42853844860cbdf054fe047 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 0865ed1da42853844860cbdf054fe047 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloudParticleVisualizer.cs b/package/Runtime/AR/ARPointCloudParticleVisualizer.cs index 3c4e56492..dca9049a0 100755 --- a/package/Runtime/AR/ARPointCloudParticleVisualizer.cs +++ b/package/Runtime/AR/ARPointCloudParticleVisualizer.cs @@ -1,98 +1,100 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Renders an as a ParticleSystem. - /// - [RequireComponent(typeof(ARPointCloud))] - [RequireComponent(typeof(ParticleSystem))] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARPointCloudParticleVisualizer.html")] - public sealed class ARPointCloudParticleVisualizer : MonoBehaviour - { - void OnPointCloudChanged(ARPointCloud pointCloud) - { - var points = s_Vertices; - pointCloud.GetPoints(points, Space.Self); - - int numParticles = points.Count; - if (m_Particles == null || m_Particles.Length < numParticles) - m_Particles = new ParticleSystem.Particle[numParticles]; - - var color = m_ParticleSystem.main.startColor.color; - var size = m_ParticleSystem.main.startSize.constant; - - for (int i = 0; i < numParticles; ++i) - { - m_Particles[i].startColor = color; - m_Particles[i].startSize = size; - m_Particles[i].position = points[i]; - m_Particles[i].remainingLifetime = 1f; - } - - // Remove any existing particles by setting remainingLifetime - // to a negative value. - for (int i = numParticles; i < m_NumParticles; ++i) - { - m_Particles[i].remainingLifetime = -1f; - } - - m_ParticleSystem.SetParticles(m_Particles, Math.Max(numParticles, m_NumParticles)); - m_NumParticles = numParticles; - } - - void Awake() - { - m_PointCloud = GetComponent(); - m_ParticleSystem = GetComponent(); - } - - void OnEnable() - { - m_PointCloud.updated += OnPointCloudChanged; - ARSubsystemManager.systemStateChanged += OnSystemStateChanged; - UpdateVisibility(); - } - - void OnDisable() - { - m_PointCloud.updated -= OnPointCloudChanged; - ARSubsystemManager.systemStateChanged -= OnSystemStateChanged; - UpdateVisibility(); - } - - void OnSystemStateChanged(ARSystemStateChangedEventArgs eventArgs) - { - UpdateVisibility(); - } - - void UpdateVisibility() - { - var visible = enabled && - (ARSubsystemManager.systemState == ARSystemState.SessionTracking); - - SetVisible(visible); - } - - void SetVisible(bool visible) - { - if (m_ParticleSystem == null) - return; - - var renderer = m_ParticleSystem.GetComponent(); - if (renderer != null) - renderer.enabled = visible; - } - - ARPointCloud m_PointCloud; - - ParticleSystem m_ParticleSystem; - - ParticleSystem.Particle[] m_Particles; - - int m_NumParticles; - - static List s_Vertices = new List(); - } -} +using System; +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Renders an as a ParticleSystem. + /// + [RequireComponent(typeof(ARPointCloud))] + [RequireComponent(typeof(ParticleSystem))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARPointCloudParticleVisualizer.html")] + public sealed class ARPointCloudParticleVisualizer : MonoBehaviour + { + void OnPointCloudChanged(ARPointCloudUpdatedEventArgs eventArgs) + { + var points = s_Vertices; + points.Clear(); + foreach (var point in m_PointCloud.positions) + s_Vertices.Add(point); + + int numParticles = points.Count; + if (m_Particles == null || m_Particles.Length < numParticles) + m_Particles = new ParticleSystem.Particle[numParticles]; + + var color = m_ParticleSystem.main.startColor.color; + var size = m_ParticleSystem.main.startSize.constant; + + for (int i = 0; i < numParticles; ++i) + { + m_Particles[i].startColor = color; + m_Particles[i].startSize = size; + m_Particles[i].position = points[i]; + m_Particles[i].remainingLifetime = 1f; + } + + // Remove any existing particles by setting remainingLifetime + // to a negative value. + for (int i = numParticles; i < m_NumParticles; ++i) + { + m_Particles[i].remainingLifetime = -1f; + } + + m_ParticleSystem.SetParticles(m_Particles, Math.Max(numParticles, m_NumParticles)); + m_NumParticles = numParticles; + } + + void Awake() + { + m_PointCloud = GetComponent(); + m_ParticleSystem = GetComponent(); + } + + void OnEnable() + { + m_PointCloud.updated += OnPointCloudChanged; + UpdateVisibility(); + } + + void OnDisable() + { + m_PointCloud.updated -= OnPointCloudChanged; + UpdateVisibility(); + } + + void Update() + { + UpdateVisibility(); + } + + void UpdateVisibility() + { + var visible = + enabled && + (m_PointCloud.trackingState != TrackingState.None); + + SetVisible(visible); + } + + void SetVisible(bool visible) + { + if (m_ParticleSystem == null) + return; + + var renderer = m_ParticleSystem.GetComponent(); + if (renderer != null) + renderer.enabled = visible; + } + + ARPointCloud m_PointCloud; + + ParticleSystem m_ParticleSystem; + + ParticleSystem.Particle[] m_Particles; + + int m_NumParticles; + + static List s_Vertices = new List(); + } +} diff --git a/package/Runtime/AR/ARPointCloudParticleVisualizer.cs.meta b/package/Runtime/AR/ARPointCloudParticleVisualizer.cs.meta index e7d67f1fa..fc57075cb 100755 --- a/package/Runtime/AR/ARPointCloudParticleVisualizer.cs.meta +++ b/package/Runtime/AR/ARPointCloudParticleVisualizer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 468ea6c98cd64494abbc2c2f34d6cde2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 468ea6c98cd64494abbc2c2f34d6cde2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs b/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs index 654c31387..f72e6a31c 100755 --- a/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs +++ b/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs @@ -1,49 +1,49 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// The arguments for the - /// event. This is currently empty, but may change in the future without the need to change the - /// subscribers' method signatures. - /// - public struct ARPointCloudUpdatedEventArgs : IEquatable - { - /// - /// Generates a hash code suitable for use in a Dictionary or HashSet. - /// - public override int GetHashCode() - { - unchecked - { - return 0; - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARPointCloudUpdatedEventArgs)) - return false; - - return Equals((ARPointCloudUpdatedEventArgs)obj); - } - - /// - /// Interface for IEquatable - /// - public bool Equals(ARPointCloudUpdatedEventArgs other) - { - return true; - } - - public static bool operator ==(ARPointCloudUpdatedEventArgs lhs, ARPointCloudUpdatedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARPointCloudUpdatedEventArgs lhs, ARPointCloudUpdatedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } +using System; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// The arguments for the + /// event. This is currently empty, but may change in the future without the need to change the + /// subscribers' method signatures. + /// + public struct ARPointCloudUpdatedEventArgs : IEquatable + { + /// + /// Generates a hash code suitable for use in a Dictionary or HashSet. + /// + public override int GetHashCode() + { + unchecked + { + return 0; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARPointCloudUpdatedEventArgs)) + return false; + + return Equals((ARPointCloudUpdatedEventArgs)obj); + } + + /// + /// Interface for IEquatable + /// + public bool Equals(ARPointCloudUpdatedEventArgs other) + { + return true; + } + + public static bool operator ==(ARPointCloudUpdatedEventArgs lhs, ARPointCloudUpdatedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARPointCloudUpdatedEventArgs lhs, ARPointCloudUpdatedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } } \ No newline at end of file diff --git a/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs.meta b/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs.meta index 64a9cfc18..b41d42e6e 100755 --- a/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs.meta +++ b/package/Runtime/AR/ARPointCloudUpdatedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 4ebe63e3282a6406396933b12d75b3b8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 4ebe63e3282a6406396933b12d75b3b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARRaycastHit.cs b/package/Runtime/AR/ARRaycastHit.cs index d5bcf85e2..6a8e2ddfb 100755 --- a/package/Runtime/AR/ARRaycastHit.cs +++ b/package/Runtime/AR/ARRaycastHit.cs @@ -1,110 +1,118 @@ -using System; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Represents the result of a raycast intersection with a trackable. - /// - public struct ARRaycastHit : IEquatable - { - /// - /// Constructor invoked by the methods. - /// - /// The raw data containing hit information. - /// The distance, in Unity world space, of the hit. - /// The Transform that transforms from session space to world space. - public ARRaycastHit(XRRaycastHit hit, float distance, Transform transform) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - m_Hit = hit; - this.distance = distance; - m_Transform = transform; - } - - /// - /// The distance, in Unity world space, from the ray origin to the intersection point. - /// - public float distance { get; private set; } - - /// - /// The type of trackable hit by the raycast. - /// - public TrackableType hitType - { - get { return m_Hit.HitType; } - } - - /// - /// The Pose, in Unity world space, of the intersection point. - /// - public Pose pose - { - get { return m_Transform.TransformPose(sessionRelativePose); } - } - - /// - /// The session-unique identifier for the trackable that was hit. - /// - public TrackableId trackableId - { - get { return m_Hit.TrackableId; } - } - - /// - /// The Pose, in local (session) space, of the intersection point. - /// - public Pose sessionRelativePose - { - get { return m_Hit.Pose; } - } - - /// - /// The distance, in local (session) space, from the ray origin to the intersection point. - /// - public float sessionRelativeDistance - { - get { return m_Hit.Distance; } - } - - public override int GetHashCode() - { - unchecked - { - return (m_Hit.GetHashCode() * 486187739 + distance.GetHashCode()) * 486187739 + (m_Transform == null ? 0 : m_Transform.GetHashCode()); - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARRaycastHit)) - return false; - - return Equals((ARRaycastHit)obj); - } - - public bool Equals(ARRaycastHit other) - { - return - (m_Hit.Equals(other.m_Hit)) && - (distance.Equals(other.distance)) && - (m_Transform.Equals(other.m_Transform)); - } - - public static bool operator ==(ARRaycastHit lhs, ARRaycastHit rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARRaycastHit lhs, ARRaycastHit rhs) - { - return !lhs.Equals(rhs); - } - - XRRaycastHit m_Hit; - - Transform m_Transform; - } -} +using System; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Represents the result of a raycast intersection with a trackable. + /// + public struct ARRaycastHit : IEquatable, IComparable + { + /// + /// Constructor invoked by the methods. + /// + /// Session-relative raycast hit data. + /// The distance, in Unity world space, of the hit. + /// The Transform that transforms from session space to world space. + public ARRaycastHit(XRRaycastHit hit, float distance, Transform transform) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + m_Hit = hit; + this.distance = distance; + m_Transform = transform; + } + + /// + /// The distance, in Unity world space, from the ray origin to the intersection point. + /// + public float distance { get; private set; } + + /// + /// The type of trackable hit by the raycast. + /// + public TrackableType hitType + { + get { return m_Hit.hitType; } + } + + /// + /// The Pose, in Unity world space, of the intersection point. + /// + public Pose pose + { + get { return m_Transform.TransformPose(sessionRelativePose); } + } + + /// + /// The session-unique identifier for the trackable that was hit. + /// + public TrackableId trackableId + { + get { return m_Hit.trackableId; } + } + + /// + /// The Pose, in local (session) space, of the intersection point. + /// + public Pose sessionRelativePose + { + get { return m_Hit.pose; } + } + + /// + /// The distance, in local (session) space, from the ray origin to the intersection point. + /// + public float sessionRelativeDistance + { + get { return m_Hit.distance; } + } + + public override int GetHashCode() + { + unchecked + { + var hash = m_Hit.GetHashCode(); + hash = hash * 486187739 + distance.GetHashCode(); + hash = hash * 486187739 + (m_Transform == null ? 0 : m_Transform.GetHashCode()); + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARRaycastHit)) + return false; + + return Equals((ARRaycastHit)obj); + } + + public bool Equals(ARRaycastHit other) + { + return + (m_Hit.Equals(other.m_Hit)) && + (distance.Equals(other.distance)) && + (m_Transform.Equals(other.m_Transform)); + } + + public static bool operator ==(ARRaycastHit lhs, ARRaycastHit rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARRaycastHit lhs, ARRaycastHit rhs) + { + return !lhs.Equals(rhs); + } + + public int CompareTo(ARRaycastHit other) + { + return m_Hit.distance.CompareTo(other.m_Hit.distance); + } + + XRRaycastHit m_Hit; + + Transform m_Transform; + } +} diff --git a/package/Runtime/AR/ARRaycastHit.cs.meta b/package/Runtime/AR/ARRaycastHit.cs.meta index b96dd4a25..6e4dc495f 100755 --- a/package/Runtime/AR/ARRaycastHit.cs.meta +++ b/package/Runtime/AR/ARRaycastHit.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: d933471f829ecae49a9e46d639ad5f54 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: d933471f829ecae49a9e46d639ad5f54 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARRaycastManager.cs b/package/Runtime/AR/ARRaycastManager.cs index 490d3468f..d1856c3e9 100755 --- a/package/Runtime/AR/ARRaycastManager.cs +++ b/package/Runtime/AR/ARRaycastManager.cs @@ -1,236 +1,236 @@ -using System; -using System.Collections.Generic; -using Unity.Collections; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Manages an XRRaycastSubsystem, exposing raycast functionality in ARFoundation. Use this component - /// to raycast against trackables (i.e., detected features in the physical environment) when they do not have - /// a presence in the Physics world. - /// - [DisallowMultipleComponent] - [RequireComponent(typeof(ARSessionOrigin))] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.1/api/UnityEngine.XR.ARFoundation.ARRaycastManager.html")] - public sealed class ARRaycastManager : SubsystemLifecycleManager - { - /// - /// Cast a ray from a point in screen space against trackables, i.e., detected features such as planes. - /// - /// The point, in device screen pixels, from which to cast. - /// Contents are replaced with the raycast results, if successful. - /// (Optional) The types of trackables to cast against. - /// True if the raycast hit a trackable in the - public bool Raycast( - Vector2 screenPoint, - List hitResults, - TrackableType trackableTypes = TrackableType.All) - { - if (subsystem == null) - return false; - - if (hitResults == null) - throw new ArgumentNullException("hitResults"); - - var nativeHits = m_RaycastViewportDelegate(screenPoint, trackableTypes, Allocator.Temp); - var originTransform = m_SessionOrigin.camera != null ? m_SessionOrigin.camera.transform : m_SessionOrigin.trackablesParent; - return TransformAndDisposeNativeHitResults(nativeHits, hitResults, originTransform.position); - } - - /// - /// Cast a Ray against trackables, i.e., detected features such as planes. - /// - /// The Ray, in Unity world space, to cast. - /// Contents are replaced with the raycast results, if successful. - /// (Optional) The types of trackables to cast against. - /// True if the raycast hit a trackable in the - public bool Raycast( - Ray ray, - List hitResults, - TrackableType trackableTypes = TrackableType.All) - { - if (subsystem == null) - return false; - - if (hitResults == null) - throw new ArgumentNullException("hitResults"); - - var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(ray); - var nativeHits = m_RaycastRayDelegate(sessionSpaceRay, trackableTypes, Allocator.Temp); - return TransformAndDisposeNativeHitResults(nativeHits, hitResults, ray.origin); - } - - static void TransformAndSortRaycastResults( - Transform transform, - NativeArray nativeHits, - List managedHits, - Vector3 rayOrigin) - { - foreach (var nativeHit in nativeHits) - { - float distanceInWorldSpace = (nativeHit.pose.position - rayOrigin).magnitude; - managedHits.Add(new ARRaycastHit(nativeHit, distanceInWorldSpace, transform)); - } - } - - /// - /// Allows AR managers to register themselves as a raycaster. - /// Raycasters be used as a fallback method if the AR platform does - /// not support raycasting using arbitrary Rays. - /// - /// A raycaster implementing the IRaycast interface. - internal void RegisterRaycaster(IRaycaster raycaster) - { - ConstructIfNecessary(); - if (!m_Raycasters.Contains(raycaster)) - m_Raycasters.Add(raycaster); - } - - /// - /// Unregisters a raycaster previously registered with . - /// - /// A raycaster to use in the fallback case. - internal void UnregisterRaycaster(IRaycaster raycaster) - { - if (m_Raycasters != null) - m_Raycasters.Remove(raycaster); - } - - protected override void OnAfterStart() - { - if (subsystem.SubsystemDescriptor.supportsViewportBasedRaycast) - { - m_RaycastViewportDelegate = RaycastViewport; - } - else - { - m_RaycastViewportDelegate = RaycastViewportAsRay; - } - - if (subsystem.SubsystemDescriptor.supportsWorldBasedRaycast) - { - m_RaycastRayDelegate = RaycastRay; - } - else - { - m_RaycastRayDelegate = RaycastFallback; - } - - var raycasters = GetComponents(typeof(IRaycaster)); - foreach (var raycaster in raycasters) - RegisterRaycaster((IRaycaster)raycaster); - } - - NativeArray RaycastViewportAsRay( - Vector2 screenPoint, - TrackableType trackableTypeMask, - Allocator allocator) - { - if (m_SessionOrigin.camera == null) - return new NativeArray(0, allocator); - - var worldSpaceRay = m_SessionOrigin.camera.ScreenPointToRay(screenPoint); - var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(worldSpaceRay); - return m_RaycastRayDelegate(sessionSpaceRay, trackableTypeMask, allocator); - } - - NativeArray RaycastViewport( - Vector2 screenPoint, - TrackableType trackableTypeMask, - Allocator allocator) - { - screenPoint.x = Mathf.Clamp01(screenPoint.x / Screen.width); - screenPoint.y = Mathf.Clamp01(screenPoint.y / Screen.height); - return subsystem.Raycast(screenPoint, trackableTypeMask, allocator); - } - - NativeArray RaycastRay( - Ray ray, - TrackableType trackableTypeMask, - Allocator allocator) - { - return subsystem.Raycast(ray, trackableTypeMask, allocator); - } - - static int RaycastHitComparer(ARRaycastHit lhs, ARRaycastHit rhs) - { - return lhs.CompareTo(rhs); - } - - NativeArray RaycastFallback( - Ray ray, - TrackableType trackableTypeMask, - Allocator allocator) - { - s_NativeRaycastHits.Clear(); - int count = 0; - foreach (var raycaster in m_Raycasters) - { - var hits = raycaster.Raycast(ray, trackableTypeMask, Allocator.Temp); - if (hits.IsCreated) - { - s_NativeRaycastHits.Add(hits); - count += hits.Length; - } - } - - var allHits = new NativeArray(count, allocator); - int dstIndex = 0; - foreach (var hitArray in s_NativeRaycastHits) - { - NativeArray.Copy(hitArray, 0, allHits, dstIndex, hitArray.Length); - hitArray.Dispose(); - dstIndex += hitArray.Length; - } - - return allHits; - } - - bool TransformAndDisposeNativeHitResults( - NativeArray nativeHits, - List managedHits, - Vector3 rayOrigin) - { - managedHits.Clear(); - if (!nativeHits.IsCreated) - return false; - - try - { - // Results are in "trackables space", so transform results back into world space - TransformAndSortRaycastResults(m_SessionOrigin.trackablesParent, nativeHits, managedHits, rayOrigin); - managedHits.Sort(s_RaycastHitComparer); - return managedHits.Count > 0; - } - finally - { - nativeHits.Dispose(); - } - } - - void ConstructIfNecessary() - { - if (m_Raycasters == null) - m_Raycasters = new List(); - } - - void Awake() - { - m_SessionOrigin = GetComponent(); - ConstructIfNecessary(); - } - - static Comparison s_RaycastHitComparer = RaycastHitComparer; - - static List> s_NativeRaycastHits = new List>(); - - ARSessionOrigin m_SessionOrigin; - - Func> m_RaycastViewportDelegate; - - Func> m_RaycastRayDelegate; - - List m_Raycasters; - } -} +using System; +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Manages an XRRaycastSubsystem, exposing raycast functionality in ARFoundation. Use this component + /// to raycast against trackables (i.e., detected features in the physical environment) when they do not have + /// a presence in the Physics world. + /// + [DisallowMultipleComponent] + [RequireComponent(typeof(ARSessionOrigin))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARRaycastManager.html")] + public sealed class ARRaycastManager : SubsystemLifecycleManager + { + /// + /// Cast a ray from a point in screen space against trackables, i.e., detected features such as planes. + /// + /// The point, in device screen pixels, from which to cast. + /// Contents are replaced with the raycast results, if successful. + /// (Optional) The types of trackables to cast against. + /// True if the raycast hit a trackable in the + public bool Raycast( + Vector2 screenPoint, + List hitResults, + TrackableType trackableTypes = TrackableType.All) + { + if (subsystem == null) + return false; + + if (hitResults == null) + throw new ArgumentNullException("hitResults"); + + var nativeHits = m_RaycastViewportDelegate(screenPoint, trackableTypes, Allocator.Temp); + var originTransform = m_SessionOrigin.camera != null ? m_SessionOrigin.camera.transform : m_SessionOrigin.trackablesParent; + return TransformAndDisposeNativeHitResults(nativeHits, hitResults, originTransform.position); + } + + /// + /// Cast a Ray against trackables, i.e., detected features such as planes. + /// + /// The Ray, in Unity world space, to cast. + /// Contents are replaced with the raycast results, if successful. + /// (Optional) The types of trackables to cast against. + /// True if the raycast hit a trackable in the + public bool Raycast( + Ray ray, + List hitResults, + TrackableType trackableTypes = TrackableType.All) + { + if (subsystem == null) + return false; + + if (hitResults == null) + throw new ArgumentNullException("hitResults"); + + var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(ray); + var nativeHits = m_RaycastRayDelegate(sessionSpaceRay, trackableTypes, Allocator.Temp); + return TransformAndDisposeNativeHitResults(nativeHits, hitResults, ray.origin); + } + + static void TransformAndSortRaycastResults( + Transform transform, + NativeArray nativeHits, + List managedHits, + Vector3 rayOrigin) + { + foreach (var nativeHit in nativeHits) + { + float distanceInWorldSpace = (nativeHit.pose.position - rayOrigin).magnitude; + managedHits.Add(new ARRaycastHit(nativeHit, distanceInWorldSpace, transform)); + } + } + + /// + /// Allows AR managers to register themselves as a raycaster. + /// Raycasters be used as a fallback method if the AR platform does + /// not support raycasting using arbitrary Rays. + /// + /// A raycaster implementing the IRaycast interface. + internal void RegisterRaycaster(IRaycaster raycaster) + { + ConstructIfNecessary(); + if (!m_Raycasters.Contains(raycaster)) + m_Raycasters.Add(raycaster); + } + + /// + /// Unregisters a raycaster previously registered with . + /// + /// A raycaster to use in the fallback case. + internal void UnregisterRaycaster(IRaycaster raycaster) + { + if (m_Raycasters != null) + m_Raycasters.Remove(raycaster); + } + + protected override void OnAfterStart() + { + if (subsystem.SubsystemDescriptor.supportsViewportBasedRaycast) + { + m_RaycastViewportDelegate = RaycastViewport; + } + else + { + m_RaycastViewportDelegate = RaycastViewportAsRay; + } + + if (subsystem.SubsystemDescriptor.supportsWorldBasedRaycast) + { + m_RaycastRayDelegate = RaycastRay; + } + else + { + m_RaycastRayDelegate = RaycastFallback; + } + + var raycasters = GetComponents(typeof(IRaycaster)); + foreach (var raycaster in raycasters) + RegisterRaycaster((IRaycaster)raycaster); + } + + NativeArray RaycastViewportAsRay( + Vector2 screenPoint, + TrackableType trackableTypeMask, + Allocator allocator) + { + if (m_SessionOrigin.camera == null) + return new NativeArray(0, allocator); + + var worldSpaceRay = m_SessionOrigin.camera.ScreenPointToRay(screenPoint); + var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(worldSpaceRay); + return m_RaycastRayDelegate(sessionSpaceRay, trackableTypeMask, allocator); + } + + NativeArray RaycastViewport( + Vector2 screenPoint, + TrackableType trackableTypeMask, + Allocator allocator) + { + screenPoint.x = Mathf.Clamp01(screenPoint.x / Screen.width); + screenPoint.y = Mathf.Clamp01(screenPoint.y / Screen.height); + return subsystem.Raycast(screenPoint, trackableTypeMask, allocator); + } + + NativeArray RaycastRay( + Ray ray, + TrackableType trackableTypeMask, + Allocator allocator) + { + return subsystem.Raycast(ray, trackableTypeMask, allocator); + } + + static int RaycastHitComparer(ARRaycastHit lhs, ARRaycastHit rhs) + { + return lhs.CompareTo(rhs); + } + + NativeArray RaycastFallback( + Ray ray, + TrackableType trackableTypeMask, + Allocator allocator) + { + s_NativeRaycastHits.Clear(); + int count = 0; + foreach (var raycaster in m_Raycasters) + { + var hits = raycaster.Raycast(ray, trackableTypeMask, Allocator.Temp); + if (hits.IsCreated) + { + s_NativeRaycastHits.Add(hits); + count += hits.Length; + } + } + + var allHits = new NativeArray(count, allocator); + int dstIndex = 0; + foreach (var hitArray in s_NativeRaycastHits) + { + NativeArray.Copy(hitArray, 0, allHits, dstIndex, hitArray.Length); + hitArray.Dispose(); + dstIndex += hitArray.Length; + } + + return allHits; + } + + bool TransformAndDisposeNativeHitResults( + NativeArray nativeHits, + List managedHits, + Vector3 rayOrigin) + { + managedHits.Clear(); + if (!nativeHits.IsCreated) + return false; + + try + { + // Results are in "trackables space", so transform results back into world space + TransformAndSortRaycastResults(m_SessionOrigin.trackablesParent, nativeHits, managedHits, rayOrigin); + managedHits.Sort(s_RaycastHitComparer); + return managedHits.Count > 0; + } + finally + { + nativeHits.Dispose(); + } + } + + void ConstructIfNecessary() + { + if (m_Raycasters == null) + m_Raycasters = new List(); + } + + void Awake() + { + m_SessionOrigin = GetComponent(); + ConstructIfNecessary(); + } + + static Comparison s_RaycastHitComparer = RaycastHitComparer; + + static List> s_NativeRaycastHits = new List>(); + + ARSessionOrigin m_SessionOrigin; + + Func> m_RaycastViewportDelegate; + + Func> m_RaycastRayDelegate; + + List m_Raycasters; + } +} diff --git a/package/Runtime/AR/ARRaycastManager.cs.meta b/package/Runtime/AR/ARRaycastManager.cs.meta index c9d6ab986..eebb70416 100755 --- a/package/Runtime/AR/ARRaycastManager.cs.meta +++ b/package/Runtime/AR/ARRaycastManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: fa17d122634046b4a8e23048891fafc5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: fa17d122634046b4a8e23048891fafc5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARReferencePoint.cs b/package/Runtime/AR/ARReferencePoint.cs index c48eb3012..a6f1caeed 100755 --- a/package/Runtime/AR/ARReferencePoint.cs +++ b/package/Runtime/AR/ARReferencePoint.cs @@ -1,46 +1,29 @@ -using System; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Represents a Reference Point (aka anchor) tracked by an AR device. - /// - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARReferencePoint.html")] - public sealed class ARReferencePoint : MonoBehaviour - { - /// - /// Invoked whenever this reference point is updated. - /// - public event Action updated; - - /// - /// The raw data associated with the reference point. - /// - public ReferencePoint sessionRelativeData - { - get { return m_Data; } - internal set { SetData(value); } - } - - /// - /// The last frame on which this reference point was updated. - /// - public int lastUpdatedFrame { get; private set; } - - void SetData(ReferencePoint referencePointData) - { - m_Data = referencePointData; - var pose = referencePointData.Pose; - transform.localPosition = pose.position; - transform.localRotation = pose.rotation; - lastUpdatedFrame = Time.frameCount; - - if (updated != null) - updated(this); - } - - ReferencePoint m_Data; - } -} +using System; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Represents a Reference Point tracked by an XR device. + /// + /// + /// A reference point is a pose in the physical environment that is tracked by an XR device. + /// As the device refines its understanding of the environment, reference points will be + /// updated, helping you to keep virtual content connected to a real-world position and orientation. + /// + [DefaultExecutionOrder(ARUpdateOrder.k_ReferencePoint)] + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARReferencePoint.html")] + public sealed class ARReferencePoint : ARTrackable + { + /// + /// Get the native pointer associated with this . + /// + /// + /// The data pointed to by this pointer is implementation defined. While its + /// lifetime is also implementation defined, it should be valid until at least + /// the next update. + /// + public IntPtr nativePtr { get { return sessionRelativeData.nativePtr; } } + } +} diff --git a/package/Runtime/AR/ARReferencePoint.cs.meta b/package/Runtime/AR/ARReferencePoint.cs.meta index c3d42dd74..fb4b2819c 100755 --- a/package/Runtime/AR/ARReferencePoint.cs.meta +++ b/package/Runtime/AR/ARReferencePoint.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: eb898793194e03f4bb10dba03ec2cb70 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: eb898793194e03f4bb10dba03ec2cb70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARReferencePointManager.cs b/package/Runtime/AR/ARReferencePointManager.cs index 5586d1d5c..4d956cf2b 100755 --- a/package/Runtime/AR/ARReferencePointManager.cs +++ b/package/Runtime/AR/ARReferencePointManager.cs @@ -1,332 +1,171 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using UnityEngine.Experimental.XR; -using UnityEngine.XR.ARExtensions; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Manages reference points (aka anchors). - /// - /// - /// Use this component to programmatically add, remove, or query for - /// reference points. Reference points are Poses in the world - /// which will be periodically updated by an AR devices as its understanding - /// of the world changes. - /// - [RequireComponent(typeof(ARSessionOrigin))] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARReferencePointManager.html")] - public sealed class ARReferencePointManager : MonoBehaviour - { - [SerializeField] - [Tooltip("If not null, instantiates this prefab for each instantiated reference point.")] - GameObject m_ReferencePointPrefab; - - /// - /// Getter/setter for the Reference Point Prefab. - /// - public GameObject referencePointPrefab - { - get { return m_ReferencePointPrefab; } - set { m_ReferencePointPrefab = value; } - } - - /// - /// Raised each time an is updated. - /// - /// - /// This can happen when the 's Pose changes, or - /// when its TrackingState changes. - /// - public event Action referencePointUpdated; - - /// - /// Attempts to add an with the given Pose. - /// - /// - /// If is not null, a new instance will be created. Otherwise, a - /// new GameObject will be created. In either case, this method ensures that the resulting - /// GameObject has a component on it. - /// - /// The pose, in Unity world space, of the . - /// If successful, a new . Otherwise, null. - public ARReferencePoint TryAddReferencePoint(Pose pose) - { - return TryAddReferencePoint(pose.position, pose.rotation); - } - - /// - /// Attempts to add an with the given and . - /// - /// - /// If is not null, a new instance will be created. Otherwise, a - /// new GameObject will be created. In either case, this method ensures that the resulting - /// GameObject has a component on it. - /// - /// The position, in Unity world space, of the . - /// The rotation, in Unity world space, of the . - /// If successful, a new . Otherwise, null. - public ARReferencePoint TryAddReferencePoint(Vector3 position, Quaternion rotation) - { - var referencePointSubsystem = ARSubsystemManager.referencePointSubsystem; - if (referencePointSubsystem == null) - return null; - - // World space pose - var pose = new Pose(position, rotation); - - // Session space pose - var sessionRelativePose = m_SessionOrigin.trackablesParent.InverseTransformPose(pose); - - // Add the reference point to the XRReferencePointSubsystem - TrackableId referencePointId; - if (!referencePointSubsystem.TryAddReferencePoint(sessionRelativePose.position, sessionRelativePose.rotation, out referencePointId)) - return null; - - return CreateArReferencePoint(referencePointId, sessionRelativePose); - } - - /// - /// Attempts to create a new reference point that is attached to an existing . - /// - /// The to which to attach. - /// The initial Pose, in Unity world space, of the reference point. - /// A new if successful, or null if not. - public ARReferencePoint TryAttachReferencePoint(ARPlane plane, Pose pose) - { - var referencePointSubsystem = ARSubsystemManager.referencePointSubsystem; - if (referencePointSubsystem == null) - return null; - - if (plane == null) - throw new ArgumentNullException("plane"); - - var sessionRelativePose = m_SessionOrigin.trackablesParent.InverseTransformPose(pose); - var newId = referencePointSubsystem.AttachReferencePoint(plane.boundedPlane.Id, sessionRelativePose); - if (newId == TrackableId.InvalidId) - return null; - - return CreateArReferencePoint(newId, sessionRelativePose); - } - - /// - /// Attempts to create a new reference point that is attached to an existing . - /// - /// The to which to attach. - /// The initial position, in Unity world space, of the reference point. - /// The initial rotation, in Unity world space, of the reference point. - /// A new if successful, or null if not. - public ARReferencePoint TryAttachReferencePoint(ARPlane plane, Vector3 position, Quaternion rotation) - { - return TryAttachReferencePoint(plane, new Pose(position, rotation)); - } - - /// - /// Attempts to remove an by TrackableId - /// - /// The TrackableId associated with the you wish to remove. - /// True if the reference point was successfully removed. - /// False usually means the reference point doesn't exist or isn't tracked by this manager. - public bool TryRemoveReferencePoint(TrackableId referencePointId) - { - var referencePointSubsystem = ARSubsystemManager.referencePointSubsystem; - if (referencePointSubsystem == null) - return false; - - // Are we tracking it? - var referencePoint = TryGetReferencePoint(referencePointId); - if (referencePoint == null) - return false; - - return TryRemoveReferencePointInternal(referencePointId, referencePoint); - } - - /// - /// Attempts to remove an . - /// - /// The reference point you wish to remove. - /// True if the reference point was successfully removed. - /// False usually means the reference point doesn't exist or isn't tracked by this manager. - public bool TryRemoveReferencePoint(ARReferencePoint referencePoint) - { - if (referencePoint == null) - return false; - - TrackableId referencePointId = referencePoint.sessionRelativeData.Id; - if (!m_ReferencePoints.ContainsKey(referencePointId)) - return false; - - return TryRemoveReferencePointInternal(referencePointId, referencePoint); - } - - bool TryRemoveReferencePointInternal(TrackableId referencePointId, ARReferencePoint referencePoint) - { - var referencePointSubsystem = ARSubsystemManager.referencePointSubsystem; - if (!referencePointSubsystem.TryRemoveReferencePoint(referencePointId)) - return false; - - Destroy(referencePoint.gameObject); - m_ReferencePoints.Remove(referencePointId); - return true; - } - - /// - /// Attempts to retrieve an existing previously added with . - /// - /// The TrackableId associated with the reference point. - /// Populated with the if successful. - /// The with TrackableId . Otherwise, null. - public ARReferencePoint TryGetReferencePoint(TrackableId referencePointId) - { - ARReferencePoint referencePoint; - m_ReferencePoints.TryGetValue(referencePointId, out referencePoint); - return referencePoint; - } - - /// - /// Get all currently tracked s. - /// - /// Replaces the contents with the current list of reference points. - public void GetAllReferencePoints(List referencePointsOut) - { - if (referencePointsOut == null) - throw new ArgumentNullException("referencePointsOut"); - - referencePointsOut.Clear(); - foreach (var kvp in m_ReferencePoints) - { - referencePointsOut.Add(kvp.Value); - } - } - - [StructLayout(LayoutKind.Sequential)] - struct ReferencePointShadow - { - public TrackableId trackableId; - public TrackingState trackingState; - public Pose pose; - } - - ReferencePoint CreateReferencePointData(TrackableId trackableId, TrackingState trackingState, Pose pose) - { - var shadowData = new ReferencePointShadow() - { - trackableId = trackableId, - trackingState = trackingState, - pose = pose - }; - - ReferencePoint returnVal; - unsafe - { - returnVal = *(ReferencePoint*)(&shadowData); - } - - return returnVal; - } - - ARReferencePoint CreateArReferencePoint(ReferencePoint referencePointData) - { - // Create a new GameObject for this point - var parentTransform = m_SessionOrigin.trackablesParent; - GameObject go; - if (referencePointPrefab != null) - { - go = Instantiate(referencePointPrefab, parentTransform); - } - else - { - go = new GameObject(); - go.transform.SetParent(parentTransform, false); - go.layer = gameObject.layer; - } - - go.name = string.Format("ReferencePoint {0}", referencePointData.Id); - - // Make sure it has an ARReferencePoint component. - var referencePoint = go.GetComponent(); - if (referencePoint == null) - referencePoint = go.AddComponent(); - - m_ReferencePoints.Add(referencePointData.Id, referencePoint); - referencePoint.sessionRelativeData = referencePointData; - - return referencePoint; - } - - ARReferencePoint CreateArReferencePoint(TrackableId referencePointId, Pose pose) - { - if (referencePointId == TrackableId.InvalidId) - return null; - - // Get the data back of the XRReferencePointSubsystem - ReferencePoint referencePointData; - var referencePointExists = ARSubsystemManager.referencePointSubsystem.TryGetReferencePoint( - referencePointId, out referencePointData); - - // It's possible the native code has updated its internal state to include the reference - // point we just created, so manufacture some data in that case. - if (!referencePointExists) - referencePointData = CreateReferencePointData(referencePointId, TrackingState.Unknown, pose); - - return CreateArReferencePoint(referencePointData); - } - - void OnReferencePointUpdated(ReferencePointUpdatedEventArgs eventArgs) - { - var referencePointData = eventArgs.ReferencePoint; - ARReferencePoint referencePoint = TryGetReferencePoint(referencePointData.Id); - if (referencePoint == null) - referencePoint = CreateArReferencePoint(eventArgs.ReferencePoint); - - referencePoint.sessionRelativeData = referencePointData; - - // Notify event subscribers - RaiseReferencePointUpdatedEvent(eventArgs, referencePoint); - } - - void RaiseReferencePointUpdatedEvent(ReferencePointUpdatedEventArgs eventArgs, ARReferencePoint referencePoint) - { - if (referencePointUpdated == null) - return; - - referencePointUpdated(new ARReferencePointUpdatedEventArgs( - referencePoint, - eventArgs.PreviousTrackingState, - eventArgs.PreviousPose)); - } - - void OnSessionDestroyed() - { - foreach (var kvp in m_ReferencePoints) - { - var referencePoint = kvp.Value; - Destroy(referencePoint.gameObject); - } - - m_ReferencePoints.Clear(); - } - - void Awake() - { - m_SessionOrigin = GetComponent(); - } - - void OnEnable() - { - ARSubsystemManager.referencePointUpdated += OnReferencePointUpdated; - ARSubsystemManager.sessionDestroyed += OnSessionDestroyed; - } - - void OnDisable() - { - ARSubsystemManager.referencePointUpdated -= OnReferencePointUpdated; - ARSubsystemManager.sessionDestroyed -= OnSessionDestroyed; - } - - ARSessionOrigin m_SessionOrigin; - - Dictionary m_ReferencePoints = new Dictionary(); - } -} +using System; +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Manages reference points. + /// + /// + /// Use this component to programmatically add, remove, or query for + /// reference points. Reference points are Poses in the world + /// which will be periodically updated by an AR device as its understanding + /// of the world changes. + /// Subscribe to changes (added, updated, & removed) via the + /// event. + /// + /// + [DefaultExecutionOrder(ARUpdateOrder.k_ReferencePointManager)] + [DisallowMultipleComponent] + [RequireComponent(typeof(ARSessionOrigin))] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARReferencePointManager.html")] + public sealed class ARReferencePointManager : ARTrackableManager< + XRReferencePointSubsystem, + XRReferencePointSubsystemDescriptor, + XRReferencePoint, + ARReferencePoint> + { + [SerializeField] + [Tooltip("If not null, instantiates this prefab for each instantiated reference point.")] + GameObject m_ReferencePointPrefab; + + /// + /// Getter/setter for the Reference Point Prefab. + /// + public GameObject referencePointPrefab + { + get { return m_ReferencePointPrefab; } + set { m_ReferencePointPrefab = value; } + } + + /// + /// Invoked once per frame to communicate changes to reference points, including + /// new reference points, the update of existing reference points, and the removal + /// of previously existing reference points. + /// + public event Action referencePointsChanged; + + /// + /// Attempts to add an with the given Pose. + /// + /// + /// If + /// is not null, a new instance of that prefab will be instantiated. Otherwise, a + /// new GameObject will be created. In either case, the resulting + /// GameObject will have an component on it. + /// + /// The pose, in Unity world space, of the . + /// A new if successful, otherwise null. + public ARReferencePoint AddReferencePoint(Pose pose) + { + if (!enabled) + throw new InvalidOperationException("Cannot create a reference point from a disabled reference point manager."); + + if (subsystem == null) + throw new InvalidOperationException("Reference point manager has no subsystem. Enable the manager first."); + + var sessionRelativePose = sessionOrigin.trackablesParent.InverseTransformPose(pose); + + // Add the reference point to the XRReferencePointSubsystem + XRReferencePoint sessionRelativeData; + if (subsystem.TryAddReferencePoint(sessionRelativePose, out sessionRelativeData)) + return CreateTrackableImmediate(sessionRelativeData); + + return null; + } + + /// + /// Attempts to create a new reference point that is attached to an existing . + /// + /// The to which to attach. + /// The initial Pose, in Unity world space, of the reference point. + /// A new if successful, otherwise null. + public ARReferencePoint AttachReferencePoint(ARPlane plane, Pose pose) + { + if (!enabled) + throw new InvalidOperationException("Cannot create a reference point from a disabled reference point manager."); + + if (subsystem == null) + throw new InvalidOperationException("Reference point manager has no subsystem. Enable the manager first."); + + if (plane == null) + throw new ArgumentNullException("plane"); + + var sessionRelativePose = sessionOrigin.trackablesParent.InverseTransformPose(pose); + XRReferencePoint sessionRelativeData; + if (subsystem.TryAttachReferencePoint(plane.trackableId, sessionRelativePose, out sessionRelativeData)) + return CreateTrackableImmediate(sessionRelativeData); + + return null; + } + + /// + /// Attempts to remove an . + /// + /// The reference point you wish to remove. + /// + /// True if the reference point was successfully removed. + /// False usually means the reference point is not longer tracked by the system. + /// + public bool RemoveReferencePoint(ARReferencePoint referencePoint) + { + if (!enabled) + throw new InvalidOperationException("Cannot create a reference point from a disabled reference point manager."); + + if (subsystem == null) + throw new InvalidOperationException("Reference point manager has no subsystem. Enable the manager first."); + + if (referencePoint == null) + throw new ArgumentNullException("referencePoint"); + + if (subsystem.TryRemoveReferencePoint(referencePoint.trackableId)) + { + DestroyPendingTrackable(referencePoint.trackableId); + return true; + } + + return false; + } + + /// + /// Gets the with given , + /// or null if it does not exist. + /// + /// The of the to retrieve. + /// The with or null if it does not exist. + public ARReferencePoint GetReferencePoint(TrackableId trackableId) + { + ARReferencePoint referencePoint; + if (m_Trackables.TryGetValue(trackableId, out referencePoint)) + return referencePoint; + + return null; + } + + protected override GameObject GetPrefab() + { + return m_ReferencePointPrefab; + } + + protected override string gameObjectName + { + get { return "ReferencePoint"; } + } + + protected override void OnTrackablesChanged( + List addedPoints, + List updatedPoints, + List removedPoints) + { + if (referencePointsChanged != null) + { + referencePointsChanged( + new ARReferencePointsChangedEventArgs( + addedPoints, + updatedPoints, + removedPoints)); + } + } + } +} diff --git a/package/Runtime/AR/ARReferencePointManager.cs.meta b/package/Runtime/AR/ARReferencePointManager.cs.meta index 2b9e4e141..35d883ca4 100755 --- a/package/Runtime/AR/ARReferencePointManager.cs.meta +++ b/package/Runtime/AR/ARReferencePointManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 728ad7fae8e460a4ba41265c7308d757 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 728ad7fae8e460a4ba41265c7308d757 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs b/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs index d03b6283f..5487e843f 100755 --- a/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs +++ b/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs @@ -1,91 +1,91 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Event arguments for the event. - /// - public struct ARReferencePointsChangedEventArgs : IEquatable - { - /// - /// The list of s added since the last event. - /// - public List added { get; private set; } - - /// - /// The list of s udpated since the last event. - /// - public List updated { get; private set; } - - /// - /// The list of s removed since the last event. - /// At the time the event is invoked, the s in - /// this list still exist. They are destroyed immediately afterward. - /// - public List removed { get; private set; } - - /// - /// Constructs an . - /// - /// The list of s added since the last event. - /// The list of s updated since the last event. - /// The list of s removed since the last event. - public ARReferencePointsChangedEventArgs( - List added, - List updated, - List removed) - { - this.added = added; - this.updated = updated; - this.removed = removed; - } - - public override int GetHashCode() - { - unchecked - { - int hash = 0; - hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); - hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); - hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); - return hash; - } - } - - public override bool Equals(object obj) - { - if (!(obj is ARReferencePointsChangedEventArgs)) - return false; - - return Equals((ARReferencePointsChangedEventArgs)obj); - } - - public override string ToString() - { - return string.Format("Added: {0}, Updated: {1}, Removed: {2}", - added == null ? 0 : added.Count, - updated == null ? 0 : updated.Count, - removed == null ? 0 : removed.Count); - - } - - public bool Equals(ARReferencePointsChangedEventArgs other) - { - return - (added == other.added) && - (updated == other.updated) && - (removed == other.removed); - } - - public static bool operator ==(ARReferencePointsChangedEventArgs lhs, ARReferencePointsChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARReferencePointsChangedEventArgs lhs, ARReferencePointsChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Event arguments for the event. + /// + public struct ARReferencePointsChangedEventArgs : IEquatable + { + /// + /// The list of s added since the last event. + /// + public List added { get; private set; } + + /// + /// The list of s udpated since the last event. + /// + public List updated { get; private set; } + + /// + /// The list of s removed since the last event. + /// At the time the event is invoked, the s in + /// this list still exist. They are destroyed immediately afterward. + /// + public List removed { get; private set; } + + /// + /// Constructs an . + /// + /// The list of s added since the last event. + /// The list of s updated since the last event. + /// The list of s removed since the last event. + public ARReferencePointsChangedEventArgs( + List added, + List updated, + List removed) + { + this.added = added; + this.updated = updated; + this.removed = removed; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 0; + hash = hash * 486187739 + (added == null ? 0 : added.GetHashCode()); + hash = hash * 486187739 + (updated == null ? 0 : updated.GetHashCode()); + hash = hash * 486187739 + (removed == null ? 0 : removed.GetHashCode()); + return hash; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ARReferencePointsChangedEventArgs)) + return false; + + return Equals((ARReferencePointsChangedEventArgs)obj); + } + + public override string ToString() + { + return string.Format("Added: {0}, Updated: {1}, Removed: {2}", + added == null ? 0 : added.Count, + updated == null ? 0 : updated.Count, + removed == null ? 0 : removed.Count); + + } + + public bool Equals(ARReferencePointsChangedEventArgs other) + { + return + (added == other.added) && + (updated == other.updated) && + (removed == other.removed); + } + + public static bool operator ==(ARReferencePointsChangedEventArgs lhs, ARReferencePointsChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARReferencePointsChangedEventArgs lhs, ARReferencePointsChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs.meta b/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs.meta index 119d3502d..dad2abb61 100755 --- a/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARReferencePointsChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: a4937dc50330b794bb431b897d742681 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: a4937dc50330b794bb431b897d742681 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARSession.cs b/package/Runtime/AR/ARSession.cs index 9ca5c295c..03e191361 100755 --- a/package/Runtime/AR/ARSession.cs +++ b/package/Runtime/AR/ARSession.cs @@ -1,125 +1,321 @@ -using System.Collections; -using UnityEngine.SceneManagement; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Controls the lifecycle and configuration options for an AR session. There - /// is only one active session. If you have multiple components, - /// they all talk to the same session and will conflict with each other. - /// - /// Enabling or disabling the will start or stop the session, - /// respectively. - /// - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARSession.html")] - public class ARSession : MonoBehaviour - { - [SerializeField] - [Tooltip("If enabled, the session will attempt to update a supported device if its AR software is out of date.")] - bool m_AttemptUpdate = true; - - /// - /// If the device supports AR but does not have the necessary software, some platforms - /// allow prompting the user to install or update the software. If - /// is true, a software update will be attempted. If the appropriate software is not installed - /// or out of date, and is false, then AR will not be available. - /// - public bool attemptUpdate - { - get { return m_AttemptUpdate; } - set { m_AttemptUpdate = value; } - } - - /// - /// Resets the AR Session. This destroys the current session, including all trackables, and - /// then establishes a new session. - /// - public void Reset() - { - if (ARSubsystemManager.systemState < ARSystemState.Ready) - return; - - ARSubsystemManager.StopSubsystems(); - ARSubsystemManager.DestroySubsystems(); - ARSubsystemManager.CreateSubsystems(); - ARSubsystemManager.StartSubsystems(); - } - - /// - /// Emits a warning in the console if more than one active - /// component is active. There is only a single, global AR Session; this - /// component controls that session. If two or more s are - /// simultaneously active, then they both issue commands to the same session. - /// Although this can cause unintended behavior, it is not expressly forbidden. - /// - /// This method is expensive and should not be called frequently. - /// - void WarnIfMultipleARSessions() - { - var sessions = FindObjectsOfType(); - if (sessions.Length > 1) - { - // Compile a list of session names - string sessionNames = ""; - foreach (var session in sessions) - { - sessionNames += string.Format("\t{0}\n", session.name); - } - - Debug.LogWarningFormat( - "Multiple active AR Sessions found. " + - "These will conflict with each other, so " + - "you should only have one active ARSession at a time. " + - "Found these active sessions:\n{0}", sessionNames); - } - } - - void OnEnable() - { -#if DEBUG - WarnIfMultipleARSessions(); -#endif - ARSubsystemManager.CreateSubsystems(); - StartCoroutine(Initialize()); - } - - IEnumerator Initialize() - { - // Make sure we've checked for availability - if (ARSubsystemManager.systemState <= ARSystemState.CheckingAvailability) - yield return ARSubsystemManager.CheckAvailability(); - - // Make sure we didn't get disabled while checking for availability - if (!enabled) - yield break; - - // Complete install if necessary - if (((ARSubsystemManager.systemState == ARSystemState.NeedsInstall) && attemptUpdate) || - (ARSubsystemManager.systemState == ARSystemState.Installing)) - { - yield return ARSubsystemManager.Install(); - } - - // If we're still enabled and everything is ready, then start. - if (ARSubsystemManager.systemState == ARSystemState.Ready && enabled) - { - ARSubsystemManager.StartSubsystems(); - } - else - { - enabled = false; - } - } - - void OnDisable() - { - ARSubsystemManager.StopSubsystems(); - } - - void OnDestroy() - { - ARSubsystemManager.DestroySubsystems(); - } - } -} +using System; +using System.Collections; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// + /// Controls the lifecycle and configuration options for an AR session. There + /// is only one active session. If you have multiple components, + /// they all talk to the same session and will conflict with each other. + /// + /// Enabling or disabling the will start or stop the session, + /// respectively. + /// + /// + [DisallowMultipleComponent] + [DefaultExecutionOrder(ARUpdateOrder.k_Session)] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARSession.html")] + public sealed class ARSession : SubsystemLifecycleManager + { + [SerializeField] + [Tooltip("If enabled, the session will attempt to update a supported device if its AR software is out of date.")] + bool m_AttemptUpdate = true; + + /// + /// If the device supports XR but does not have the necessary software, some platforms + /// allow prompting the user to install or update the software. If + /// is true, a software update will be attempted. If the appropriate software is not installed + /// or out of date, and is false, then AR will not be available. + /// + public bool attemptUpdate + { + get { return m_AttemptUpdate; } + set { m_AttemptUpdate = value; } + } + + /// + /// This event is invoked whenever the changes. + /// + public static event Action stateChanged; + + /// + /// The state of the entire system. Use this to determine the status of AR availability and installation. + /// + public static ARSessionState state + { + get { return s_State; } + private set + { + if (s_State == value) + return; + + s_State = value; + if (stateChanged != null) + stateChanged(new ARSessionStateChangedEventArgs(state)); + } + } + + /// + /// Resets the AR Session. This destroys the current session, including all trackables, and + /// then establishes a new session. + /// + public void Reset() + { + if (subsystem != null) + subsystem.Reset(); + + if (state > ARSessionState.Ready) + state = ARSessionState.SessionInitializing; + } + + /// + /// Emits a warning in the console if more than one active + /// component is active. There is only a single, global AR Session; this + /// component controls that session. If two or more s are + /// simultaneously active, then they both issue commands to the same session. + /// Although this can cause unintended behavior, it is not expressly forbidden. + /// + /// This method is expensive and should not be called frequently. + /// + void WarnIfMultipleARSessions() + { + var sessions = FindObjectsOfType(); + if (sessions.Length > 1) + { + // Compile a list of session names + string sessionNames = ""; + foreach (var session in sessions) + { + sessionNames += string.Format("\t{0}\n", session.name); + } + + Debug.LogWarningFormat( + "Multiple active AR Sessions found. " + + "These will conflict with each other, so " + + "you should only have one active ARSession at a time. " + + "Found these active sessions:\n{0}", sessionNames); + } + } + + /// + /// Start checking the availability of XR on the current device. + /// + /// + /// The availability check may be asynchronous, so this is implemented as a coroutine. + /// It is safe to call this multiple times; if called a second time while an availability + /// check is being made, it returns a new coroutine which waits on the first. + /// + /// An IEnumerator used for a coroutine. + public static IEnumerator CheckAvailability() + { + // Wait if availability is currently being checked. + while (state == ARSessionState.CheckingAvailability) + { + yield return null; + } + + // Availability has already been determined if we make it here and the state is not None. + if (state != ARSessionState.None) + yield break; + + // Normally, the subsystem is created in OnEnable, but users may + // want to check availability before enabling the session. + s_Instance.CreateSubsystemIfNecessary(); + + if (s_Instance.subsystem == null) + { + // No subsystem means there is no support on this platform. + state = ARSessionState.Unsupported; + } + else if (state == ARSessionState.None) + { + state = ARSessionState.CheckingAvailability; + var availabilityPromise = s_Instance.subsystem.GetAvailabilityAsync(); + yield return availabilityPromise; + s_Availability = availabilityPromise.result; + + if (s_Availability.IsSupported() && s_Availability.IsInstalled()) + { + state = ARSessionState.Ready; + } + else if (s_Availability.IsSupported() && !s_Availability.IsInstalled()) + { + state = s_Instance.subsystem.SubsystemDescriptor.supportsInstall ? ARSessionState.NeedsInstall : ARSessionState.Unsupported; + } + else + { + state = ARSessionState.Unsupported; + } + } + } + + /// + /// Begin installing AR software on the current device (if supported). + /// + /// + /// + /// Installation may be asynchronous, so this is implemented as a coroutine. + /// It is safe to call this multiple times, but you must first call . + /// + /// You must call before tring to Install + /// and the must not be + /// or this method will throw. + /// + /// + /// An IEnumerator used for a coroutine. + public static IEnumerator Install() + { + while ((state == ARSessionState.Installing) || (state == ARSessionState.CheckingAvailability)) + { + yield return null; + } + + switch (state) + { + case ARSessionState.Installing: + case ARSessionState.NeedsInstall: + break; + case ARSessionState.None: + throw new InvalidOperationException("Cannot install until availability has been determined. Have you called CheckAvailability()?"); + case ARSessionState.Ready: + case ARSessionState.SessionInitializing: + case ARSessionState.SessionTracking: + yield break; + case ARSessionState.Unsupported: + throw new InvalidOperationException("Cannot install because XR is not supported on this platform."); + } + + // We can't get this far without having had a valid subsystem at one point. + if (s_Instance.subsystem == null) + throw new InvalidOperationException("The subsystem was destroyed while attempting to install AR software."); + + state = ARSessionState.Installing; + var installPromise = s_Instance.subsystem.InstallAsync(); + yield return installPromise; + var installStatus = installPromise.result; + + switch (installStatus) + { + case SessionInstallationStatus.Success: + state = ARSessionState.Ready; + s_Availability = (s_Availability | SessionAvailability.Installed); + break; + case SessionInstallationStatus.ErrorUserDeclined: + state = ARSessionState.NeedsInstall; + break; + default: + state = ARSessionState.Unsupported; + break; + } + } + + /// + /// Creates and initializes the session subsystem. Begins checking for availability. + /// + protected override void OnEnable() + { +#if DEVELOPMENT_BUILD || UNITY_EDITOR + WarnIfMultipleARSessions(); +#endif + CreateSubsystemIfNecessary(); + + if (subsystem != null) + StartCoroutine(Initialize()); + } + + IEnumerator Initialize() + { + // Make sure we've checked for availability + if (state <= ARSessionState.CheckingAvailability) + yield return CheckAvailability(); + + // Make sure we didn't get disabled while checking for availability + if (!enabled) + yield break; + + // Complete install if necessary + if (((state == ARSessionState.NeedsInstall) && attemptUpdate) || + (state == ARSessionState.Installing)) + { + yield return Install(); + } + + // If we're still enabled and everything is ready, then start. + if (state == ARSessionState.Ready && enabled) + { + subsystem.Start(); + } + else + { + enabled = false; + } + } + + void Awake() + { + s_Instance = this; + } + + void Update() + { + if (subsystem != null && subsystem.running) + { + subsystem.Update(new XRSessionUpdateParams + { + screenOrientation = Screen.orientation, + screenDimensions = new Vector2Int(Screen.width, Screen.height) + }); + + switch (subsystem.trackingState) + { + case TrackingState.None: + case TrackingState.Limited: + state = ARSessionState.SessionInitializing; + break; + case TrackingState.Tracking: + state = ARSessionState.SessionTracking; + break; + } + } + } + + void OnApplicationPause(bool paused) + { + if (subsystem == null) + return; + + if (paused) + subsystem.OnApplicationPause(); + else + subsystem.OnApplicationResume(); + } + + protected override void OnDisable() + { + base.OnDisable(); + + // Only set back to ready if we were previously running + if (state > ARSessionState.Ready) + state = ARSessionState.Ready; + } + + protected override void OnDestroy() + { + base.OnDestroy(); + + // Only set back to ready if we were previously running + if (state > ARSessionState.Ready) + state = ARSessionState.Ready; + + s_Instance = null; + } + + static ARSessionState s_State; + + static SessionAvailability s_Availability; + + static ARSession s_Instance; + } +} diff --git a/package/Runtime/AR/ARSession.cs.meta b/package/Runtime/AR/ARSession.cs.meta index d124dfb9e..130c7712e 100755 --- a/package/Runtime/AR/ARSession.cs.meta +++ b/package/Runtime/AR/ARSession.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 3859a92a05d4f5d418cb6ca605290e74 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 3859a92a05d4f5d418cb6ca605290e74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARSessionOrigin.cs b/package/Runtime/AR/ARSessionOrigin.cs index ea4a3bf25..5fd8adbfa 100755 --- a/package/Runtime/AR/ARSessionOrigin.cs +++ b/package/Runtime/AR/ARSessionOrigin.cs @@ -1,335 +1,250 @@ -using System; -using System.Collections.Generic; -using UnityEngine.SpatialTracking; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// An ARSessionOrigin is the parent for an AR setup. It contains a Camera and - /// any GameObjects created from detected features, such as planes or point clouds. - /// - /// - /// Session space vs Unity space - /// - /// Since an AR device will be used to drive the Camera's position and rotation, - /// you cannot directly place the Camera at an arbitrary position in the Unity scene. - /// Instead, you should position the ARSessionOrigin. This will make the Camera - /// (and any detected features) relative to that as a result. - /// - /// It is important to keep the Camera and detected features in the same space relative to - /// each other (otherwise, detected features like planes won't appear in the correct place relative - /// to the Camera). We call the space relative to the AR device's starting position - /// "session space" or "device space". For example, when the AR session begins, the device may - /// report its position as (0, 0, 0). Detected features, such as planes, will be reported relative - /// to this starting position. The purpose of the ARSessionOrigin is to convert the session space - /// to Unity world space. - /// - /// To facilitate this, the ARSessionOrigin creates a new GameObject called "Trackables" - /// as a sibling of its Camera. This should be the parent GameObject for all - /// detected features. - /// - /// At runtime, a typical scene graph might look like this: - /// - AR Session Origin - /// - Camera - /// - Trackables - /// - Detected plane 1 - /// - Detected plane 2 - /// - Point cloud - /// - etc... - /// - /// You can access the "trackables" GameObject with . - /// - /// Note that the localPosition and localRotation of detected trackables - /// remain in real-world meters relative to the AR device's starting position and rotation. - /// - /// Scale - /// - /// If you want to scale the content rendered by the ARSessionOrigin you should apply - /// the scale to the ARSessionOrigin's transform. This is preferrable to scaling - /// the content directly as that can have undesirable side-effects. Physics and NavMeshes, - /// for example, do not perform well when scaled very small. - /// - [DisallowMultipleComponent] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@1.0/api/UnityEngine.XR.ARFoundation.ARSessionOrigin.html")] - public class ARSessionOrigin : MonoBehaviour - { - [SerializeField] - [Tooltip("The Camera to associate with the AR device.")] - Camera m_Camera; - - /// - /// The Camera to associate with the AR device. It must be a child of this ARSessionOrigin. - /// - /// - /// The Camera should update its position and rotation according to the AR device. - /// This is typically accomplished by adding a TrackedPoseDriver component to the - /// Camera. - /// -#if UNITY_EDITOR - public new Camera camera -#else - public Camera camera -#endif - { - get { return m_Camera; } - set { m_Camera = value; } - } - - /// - /// The parent Transform for all "trackables", e.g., planes and feature points. - /// - public Transform trackablesParent { get; private set; } - - GameObject m_ContentOffsetGameObject; - - Transform contentOffsetTransform - { - get - { - if (m_ContentOffsetGameObject == null) - { - // Insert a GameObject directly below the rig - m_ContentOffsetGameObject = new GameObject("Content Placement Offset"); - m_ContentOffsetGameObject.transform.SetParent(transform, false); - - // Re-parent any children of the ARSessionOrigin - for (var i = 0; i < transform.childCount; ++i) - { - var child = transform.GetChild(i); - if (child != m_ContentOffsetGameObject.transform) - { - child.SetParent(m_ContentOffsetGameObject.transform, true); - --i; // Decrement because childCount is also one less. - } - } - } - - return m_ContentOffsetGameObject.transform; - } - } - - /// - /// Makes appear to be placed at with orientation . - /// - /// The Transform of the content you wish to affect. - /// The position you wish the content to appear at. This could be - /// a position on a detected plane, for example. - /// The rotation the content should appear to be in, relative - /// to the Camera. - /// - /// This method does not actually change the Transform of content; instead, - /// it updates the ARSessionOrigin's Transform such that it appears the content - /// is now at the given position and rotation. This is useful for placing AR - /// content onto surfaces when the content itself cannot be moved at runtime. - /// For example, if your content includes terrain or a nav mesh, then it cannot - /// be moved or rotated dynamically. - /// - public void MakeContentAppearAt(Transform content, Vector3 position, Quaternion rotation) - { - MakeContentAppearAt(content, position); - MakeContentAppearAt(content, rotation); - } - - /// - /// Makes appear to be placed at . - /// - /// The Transform of the content you wish to affect. - /// The position you wish the content to appear at. This could be - /// a position on a detected plane, for example. - /// - /// This method does not actually change the Transform of content; instead, - /// it updates the ARSessionOrigin's Transform such that it appears the content - /// is now at the given position. - /// - public void MakeContentAppearAt(Transform content, Vector3 position) - { - if (content == null) - throw new ArgumentNullException("content"); - - // Adjust the "point of interest" transform to account - // for the actual position we want the content to appear at. - contentOffsetTransform.position += transform.position - position; - - // The ARSessionOrigin's position needs to match the content's pivot. This is so - // the entire ARSessionOrigin rotates around the content (so the impression is that - // the content is rotating, not the rig). - transform.position = content.position; - } - - /// - /// Makes appear to have orientation relative to the Camera. - /// - /// The Transform of the content you wish to affect. - /// The rotation the content should appear to be in, relative - /// to the Camera. - /// - /// This method does not actually change the Transform of content; instead, - /// it updates the ARSessionOrigin's Transform such that it appears the content - /// is in the requested orientation. - /// - public void MakeContentAppearAt(Transform content, Quaternion rotation) - { - if (content == null) - throw new ArgumentNullException("content"); - - // Since we aren't rotating the content, we need to perform the inverse - // operation on the ARSessionOrigin. For example, if we want the - // content to appear to be rotated 90 degrees on the Y axis, we should - // rotate our rig -90 degrees on the Y axis. - transform.rotation = Quaternion.Inverse(rotation) * content.rotation; - } - - /// - /// Cast a ray from a point in screen space against trackables, i.e., detected features such as planes. - /// - /// The point, in device screen pixels, from which to cast. - /// Contents are replaced with the raycast results, if successful. - /// (Optional) The types of trackables to cast against. - /// True if the raycast hit a trackable in the - public bool Raycast(Vector3 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All) - { - if (hitResults == null) - throw new ArgumentNullException("hitResults"); - - var raycastSubsystem = ARSubsystemManager.raycastSubsystem; - if (raycastSubsystem == null) - return false; - - var originTransform = camera != null ? camera.transform : trackablesParent; - - // Results are in "trackables space" - if (raycastSubsystem.Raycast(screenPoint, s_RaycastHits, trackableTypeMask)) - { - // Transform results back into world space - TransformRaycastResults(trackablesParent, hitResults, originTransform.position); - return hitResults.Count > 0; - } - - return false; - } - - /// - /// Cast a Ray against trackables, i.e., detected features such as planes. - /// - /// The Ray, in Unity world space, to cast. - /// Contents are replaced with the raycast results, if successful. - /// (Optional) The types of trackables to cast against. - /// (Optional) Used to define the angle of the cone to use when raycasting against feature points. - /// True if the raycast hit a trackable in the - public bool Raycast(Ray ray, List hitResults, TrackableType trackableTypeMask = TrackableType.All, float pointCloudRaycastAngleInDegrees = 5f) - { - if (trackablesParent == null) - return false; - - if (hitResults == null) - throw new ArgumentNullException("hitResults"); - - var rayLocalSpace = trackablesParent.InverseTransformRay(ray); - - XRRaycastSubsystem.Raycast( - rayLocalSpace, - ARSubsystemManager.depthSubsystem, - ARSubsystemManager.planeSubsystem, - s_RaycastHits, - trackableTypeMask, - pointCloudRaycastAngleInDegrees); - - TransformRaycastResults(trackablesParent, hitResults, ray.origin); - - return hitResults.Count > 0; - } - - static void TransformRaycastResults(Transform transform, List hits, Vector3 rayOrigin) - { - hits.Clear(); - foreach (var hit in s_RaycastHits) - { - float distanceInWorldSpace = (hit.Pose.position - rayOrigin).magnitude; - hits.Add(new ARRaycastHit(hit, distanceInWorldSpace, transform)); - } - } - - void Awake() - { - // This will be the parent GameObject for any trackables (such as planes) for which - // we want a corresponding GameObject. - trackablesParent = (new GameObject("Trackables")).transform; - trackablesParent.SetParent(transform, false); - trackablesParent.localPosition = Vector3.zero; - trackablesParent.localRotation = Quaternion.identity; - trackablesParent.localScale = Vector3.one; - - if (camera != null) - { - var trackedPoseDriver = camera.GetComponent(); - - // Warn if not using a TrackedPoseDriver - if (trackedPoseDriver == null) - { - Debug.LogWarningFormat( - "Camera \"{0}\" does not use a Tracked Pose Driver, so its transform " + - "will not be updated by an XR device.", camera.name); - } - // If we are using a TrackedPoseDriver, and the user hasn't chosen "make relative" - // then warn if the camera has a non-identity transform (since it will be overwritten). - else if (!trackedPoseDriver.UseRelativeTransform) - { - var cameraTransform = camera.transform; - if ((cameraTransform.localPosition != Vector3.zero) || (cameraTransform.localRotation != Quaternion.identity)) - { - Debug.LogWarningFormat( - "Camera \"{0}\" has a non-identity transform (position = {1}, rotation = {2}). " + - "The camera's local position and rotation will be overwritten by the XR device, " + - "so this starting transform will have no effect. Tick the \"Make Relative\" " + - "checkbox on the camera's Tracked Pose Driver to apply this starting transform.", - camera.name, - cameraTransform.localPosition, - cameraTransform.localRotation); - } - } - } - } - - Pose GetCameraOriginPose() - { - var trackedPoseDriver = camera.GetComponent(); - if (trackedPoseDriver != null) - { - var localOriginPose = trackedPoseDriver.originPose; - var parent = camera.transform.parent; - - if (parent == null) - return localOriginPose; - - return parent.TransformPose(localOriginPose); - } - - return Pose.identity; - } - - void Update() - { - if (camera != null) - { - // Make sure the trackables has the same local transform as the camera's origin - var pose = GetCameraOriginPose(); - trackablesParent.position = pose.position; - trackablesParent.rotation = pose.rotation; - - var cameraSubsystem = ARSubsystemManager.cameraSubsystem; - if ((cameraSubsystem != null) && (cameraSubsystem.Camera != null)) - { - // This rig may not be using the AR Session's camera, but it - // is probably rendering AR content. The projection matrices - // should match in order for the AR content to look correct. - // Otherwise, it will appear "floaty". - if (camera != cameraSubsystem.Camera) - camera.projectionMatrix = cameraSubsystem.Camera.projectionMatrix; - } - } - } - - static List s_RaycastHits = new List(); - } -} +using System; +using UnityEngine.SpatialTracking; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// An ARSessionOrigin is the parent for an AR setup. It contains a Camera and + /// any GameObjects created from detected features, such as planes or point clouds. + /// + /// + /// Session space vs Unity space + /// + /// Since an AR device will be used to drive the Camera's position and rotation, + /// you cannot directly place the Camera at an arbitrary position in the Unity scene. + /// Instead, you should position the ARSessionOrigin. This will make the Camera + /// (and any detected features) relative to that as a result. + /// + /// It is important to keep the Camera and detected features in the same space relative to + /// each other (otherwise, detected features like planes won't appear in the correct place relative + /// to the Camera). We call the space relative to the AR device's starting position + /// "session space" or "device space". For example, when the AR session begins, the device may + /// report its position as (0, 0, 0). Detected features, such as planes, will be reported relative + /// to this starting position. The purpose of the ARSessionOrigin is to convert the session space + /// to Unity world space. + /// + /// To facilitate this, the ARSessionOrigin creates a new GameObject called "Trackables" + /// as a sibling of its Camera. This should be the parent GameObject for all + /// detected features. + /// + /// At runtime, a typical scene graph might look like this: + /// - AR Session Origin + /// - Camera + /// - Trackables + /// - Detected plane 1 + /// - Detected plane 2 + /// - Point cloud + /// - etc... + /// + /// You can access the "trackables" GameObject with . + /// + /// Note that the localPosition and localRotation of detected trackables + /// remain in real-world meters relative to the AR device's starting position and rotation. + /// + /// Scale + /// + /// If you want to scale the content rendered by the ARSessionOrigin you should apply + /// the scale to the ARSessionOrigin's transform. This is preferrable to scaling + /// the content directly as that can have undesirable side-effects. Physics and NavMeshes, + /// for example, do not perform well when scaled very small. + /// + [DisallowMultipleComponent] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.0/api/UnityEngine.XR.ARFoundation.ARSessionOrigin.html")] + public class ARSessionOrigin : MonoBehaviour + { + [SerializeField] + [Tooltip("The Camera to associate with the AR device.")] + Camera m_Camera; + + /// + /// The Camera to associate with the AR device. It must be a child of this ARSessionOrigin. + /// + /// + /// The Camera should update its position and rotation according to the AR device. + /// This is typically accomplished by adding a TrackedPoseDriver component to the + /// Camera. + /// +#if UNITY_EDITOR + public new Camera camera +#else + public Camera camera +#endif + { + get { return m_Camera; } + set { m_Camera = value; } + } + + /// + /// The parent Transform for all "trackables", e.g., planes and feature points. + /// + public Transform trackablesParent { get; private set; } + + GameObject m_ContentOffsetGameObject; + + Transform contentOffsetTransform + { + get + { + if (m_ContentOffsetGameObject == null) + { + // Insert a GameObject directly below the rig + m_ContentOffsetGameObject = new GameObject("Content Placement Offset"); + m_ContentOffsetGameObject.transform.SetParent(transform, false); + + // Re-parent any children of the ARSessionOrigin + for (var i = 0; i < transform.childCount; ++i) + { + var child = transform.GetChild(i); + if (child != m_ContentOffsetGameObject.transform) + { + child.SetParent(m_ContentOffsetGameObject.transform, true); + --i; // Decrement because childCount is also one less. + } + } + } + + return m_ContentOffsetGameObject.transform; + } + } + + /// + /// Makes appear to be placed at with orientation . + /// + /// The Transform of the content you wish to affect. + /// The position you wish the content to appear at. This could be + /// a position on a detected plane, for example. + /// The rotation the content should appear to be in, relative + /// to the Camera. + /// + /// This method does not actually change the Transform of content; instead, + /// it updates the ARSessionOrigin's Transform such that it appears the content + /// is now at the given position and rotation. This is useful for placing AR + /// content onto surfaces when the content itself cannot be moved at runtime. + /// For example, if your content includes terrain or a nav mesh, then it cannot + /// be moved or rotated dynamically. + /// + public void MakeContentAppearAt(Transform content, Vector3 position, Quaternion rotation) + { + MakeContentAppearAt(content, position); + MakeContentAppearAt(content, rotation); + } + + /// + /// Makes appear to be placed at . + /// + /// The Transform of the content you wish to affect. + /// The position you wish the content to appear at. This could be + /// a position on a detected plane, for example. + /// + /// This method does not actually change the Transform of content; instead, + /// it updates the ARSessionOrigin's Transform such that it appears the content + /// is now at the given position. + /// + public void MakeContentAppearAt(Transform content, Vector3 position) + { + if (content == null) + throw new ArgumentNullException("content"); + + // Adjust the "point of interest" transform to account + // for the actual position we want the content to appear at. + contentOffsetTransform.position += transform.position - position; + + // The ARSessionOrigin's position needs to match the content's pivot. This is so + // the entire ARSessionOrigin rotates around the content (so the impression is that + // the content is rotating, not the rig). + transform.position = content.position; + } + + /// + /// Makes appear to have orientation relative to the Camera. + /// + /// The Transform of the content you wish to affect. + /// The rotation the content should appear to be in, relative + /// to the Camera. + /// + /// This method does not actually change the Transform of content; instead, + /// it updates the ARSessionOrigin's Transform such that it appears the content + /// is in the requested orientation. + /// + public void MakeContentAppearAt(Transform content, Quaternion rotation) + { + if (content == null) + throw new ArgumentNullException("content"); + + // Since we aren't rotating the content, we need to perform the inverse + // operation on the ARSessionOrigin. For example, if we want the + // content to appear to be rotated 90 degrees on the Y axis, we should + // rotate our rig -90 degrees on the Y axis. + transform.rotation = Quaternion.Inverse(rotation) * content.rotation; + } + + void Awake() + { + // This will be the parent GameObject for any trackables (such as planes) for which + // we want a corresponding GameObject. + trackablesParent = (new GameObject("Trackables")).transform; + trackablesParent.SetParent(transform, false); + trackablesParent.localPosition = Vector3.zero; + trackablesParent.localRotation = Quaternion.identity; + trackablesParent.localScale = Vector3.one; + + if (camera != null) + { + var trackedPoseDriver = camera.GetComponent(); + + // Warn if not using a TrackedPoseDriver + if (trackedPoseDriver == null) + { + Debug.LogWarningFormat( + "Camera \"{0}\" does not use a Tracked Pose Driver, so its transform " + + "will not be updated by an XR device.", camera.name); + } + // If we are using a TrackedPoseDriver, and the user hasn't chosen "make relative" + // then warn if the camera has a non-identity transform (since it will be overwritten). + else if (!trackedPoseDriver.UseRelativeTransform) + { + var cameraTransform = camera.transform; + if ((cameraTransform.localPosition != Vector3.zero) || (cameraTransform.localRotation != Quaternion.identity)) + { + Debug.LogWarningFormat( + "Camera \"{0}\" has a non-identity transform (position = {1}, rotation = {2}). " + + "The camera's local position and rotation will be overwritten by the XR device, " + + "so this starting transform will have no effect. Tick the \"Make Relative\" " + + "checkbox on the camera's Tracked Pose Driver to apply this starting transform.", + camera.name, + cameraTransform.localPosition, + cameraTransform.localRotation); + } + } + } + } + + Pose GetCameraOriginPose() + { + var trackedPoseDriver = camera.GetComponent(); + if (trackedPoseDriver != null) + { + var localOriginPose = trackedPoseDriver.originPose; + var parent = camera.transform.parent; + + if (parent == null) + return localOriginPose; + + return parent.TransformPose(localOriginPose); + } + + return Pose.identity; + } + + void Update() + { + if (camera != null) + { + // Make sure the trackables has the same local transform as the camera's origin + var pose = GetCameraOriginPose(); + trackablesParent.position = pose.position; + trackablesParent.rotation = pose.rotation; + } + } + } +} diff --git a/package/Runtime/AR/ARSessionOrigin.cs.meta b/package/Runtime/AR/ARSessionOrigin.cs.meta index 008b1919c..c95912fbc 100755 --- a/package/Runtime/AR/ARSessionOrigin.cs.meta +++ b/package/Runtime/AR/ARSessionOrigin.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 520bb47c46cf8624fafb307b7d1b862a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 520bb47c46cf8624fafb307b7d1b862a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARSessionState.cs b/package/Runtime/AR/ARSessionState.cs index 4367cd2d3..a56f1386a 100755 --- a/package/Runtime/AR/ARSessionState.cs +++ b/package/Runtime/AR/ARSessionState.cs @@ -1,53 +1,53 @@ -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Represents the current state of the AR system. - /// - public enum ARSessionState - { - /// - /// The AR system has not been initialized. Availability is unknown. - /// . - /// - None, - - /// - /// AR is not supported on the current device. - /// - Unsupported, - - /// - /// The system is checking for the availability of AR. - /// . - /// - CheckingAvailability, - - /// - /// AR is supported, but requires an additional install. - /// . - /// - NeedsInstall, - - /// - /// AR software is being installed. . - /// - Installing, - - /// - /// AR is supported and ready. - /// - Ready, - - /// - /// An AR session is initializing (i.e., starting up). This usually means AR is working - /// but has not yet gathered enough information about the environment. - /// - SessionInitializing, - - /// - /// An AR session is running and is tracking (i.e., the device is able to determine its - /// position and orientation in the world). - /// - SessionTracking - } -} +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Represents the current state of the AR system. + /// + public enum ARSessionState + { + /// + /// The AR system has not been initialized. Availability is unknown. + /// . + /// + None, + + /// + /// AR is not supported on the current device. + /// + Unsupported, + + /// + /// The system is checking for the availability of AR. + /// . + /// + CheckingAvailability, + + /// + /// AR is supported, but requires an additional install. + /// . + /// + NeedsInstall, + + /// + /// AR software is being installed. . + /// + Installing, + + /// + /// AR is supported and ready. + /// + Ready, + + /// + /// An AR session is initializing (i.e., starting up). This usually means AR is working + /// but has not yet gathered enough information about the environment. + /// + SessionInitializing, + + /// + /// An AR session is running and is tracking (i.e., the device is able to determine its + /// position and orientation in the world). + /// + SessionTracking + } +} diff --git a/package/Runtime/AR/ARSessionState.cs.meta b/package/Runtime/AR/ARSessionState.cs.meta index be56ede12..c6e909f9d 100755 --- a/package/Runtime/AR/ARSessionState.cs.meta +++ b/package/Runtime/AR/ARSessionState.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 031d25925d1dbfa46b1d5f40979c2338 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 031d25925d1dbfa46b1d5f40979c2338 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARSessiontateChangedEventArgs.cs b/package/Runtime/AR/ARSessiontateChangedEventArgs.cs index 4e950afe7..d4026cd3f 100755 --- a/package/Runtime/AR/ARSessiontateChangedEventArgs.cs +++ b/package/Runtime/AR/ARSessiontateChangedEventArgs.cs @@ -1,57 +1,57 @@ -using System; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Container for SystemState event arguments. Used by the . - /// - public struct ARSessionStateChangedEventArgs : IEquatable - { - /// - /// The new session state. - /// - public ARSessionState state { get; private set; } - - /// - /// Constructor for these event arguments. - /// - /// The new session state. - public ARSessionStateChangedEventArgs(ARSessionState state) - { - this.state = state; - } - - public override int GetHashCode() - { - return ((int)state).GetHashCode(); - } - - public override bool Equals(object obj) - { - if (!(obj is ARSessionStateChangedEventArgs)) - return false; - - return Equals((ARSessionStateChangedEventArgs)obj); - } - - public override string ToString() - { - return state.ToString(); - } - - public bool Equals(ARSessionStateChangedEventArgs other) - { - return state == other.state; - } - - public static bool operator ==(ARSessionStateChangedEventArgs lhs, ARSessionStateChangedEventArgs rhs) - { - return lhs.Equals(rhs); - } - - public static bool operator !=(ARSessionStateChangedEventArgs lhs, ARSessionStateChangedEventArgs rhs) - { - return !lhs.Equals(rhs); - } - } -} +using System; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Container for SystemState event arguments. Used by the . + /// + public struct ARSessionStateChangedEventArgs : IEquatable + { + /// + /// The new session state. + /// + public ARSessionState state { get; private set; } + + /// + /// Constructor for these event arguments. + /// + /// The new session state. + public ARSessionStateChangedEventArgs(ARSessionState state) + { + this.state = state; + } + + public override int GetHashCode() + { + return ((int)state).GetHashCode(); + } + + public override bool Equals(object obj) + { + if (!(obj is ARSessionStateChangedEventArgs)) + return false; + + return Equals((ARSessionStateChangedEventArgs)obj); + } + + public override string ToString() + { + return state.ToString(); + } + + public bool Equals(ARSessionStateChangedEventArgs other) + { + return state == other.state; + } + + public static bool operator ==(ARSessionStateChangedEventArgs lhs, ARSessionStateChangedEventArgs rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ARSessionStateChangedEventArgs lhs, ARSessionStateChangedEventArgs rhs) + { + return !lhs.Equals(rhs); + } + } +} diff --git a/package/Runtime/AR/ARSessiontateChangedEventArgs.cs.meta b/package/Runtime/AR/ARSessiontateChangedEventArgs.cs.meta index 935857157..b6ccd76c7 100755 --- a/package/Runtime/AR/ARSessiontateChangedEventArgs.cs.meta +++ b/package/Runtime/AR/ARSessiontateChangedEventArgs.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 90c909ed8f70449aa9fca057c2a4d292 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 90c909ed8f70449aa9fca057c2a4d292 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARTrackable.cs b/package/Runtime/AR/ARTrackable.cs index 8ff53f00d..ea57b23e4 100755 --- a/package/Runtime/AR/ARTrackable.cs +++ b/package/Runtime/AR/ARTrackable.cs @@ -1,71 +1,71 @@ -using System; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A generic component for trackables. A "trackable" is a feature in the physical - /// environment that can be detected and tracked by an XR device. - /// - /// The raw, session relative data type used to update this trackable. - /// The concrete class which derives from . - public class ARTrackable : MonoBehaviour - where TSessionRelativeData : struct, ITrackable - where TTrackable : ARTrackable - { - [SerializeField] - [Tooltip("If true, this component's GameObject will be removed immediately when this trackable is removed.")] - bool m_DestroyOnRemoval = true; - - /// - /// If true, this component's GameObject will be removed immediately when the XR device reports this trackable is no longer tracked. - /// - /// - /// Setting this to false will keep the GameObject around. You may want to do this, for example, - /// if you have custom removal logic, such as a fade out. - /// - public bool destroyOnRemoval - { - get { return m_DestroyOnRemoval; } - set { m_DestroyOnRemoval = value; } - } - - /// - /// The TrackableId associated with this trackable. TrackableIds - /// are typically unique to a particular session. - /// - public TrackableId trackableId - { - get { return sessionRelativeData.trackableId; } - } - - /// - /// The tracking state associated with this trackable. - /// - public TrackingState trackingState - { - get { return sessionRelativeData.trackingState; } - } - - /// - /// The session-relative data associated with this trackable. - /// - protected TSessionRelativeData sessionRelativeData { get; private set; } - - /// - /// Invoked just after the session-relative data has been set. - /// The GameObject's transform has already been updated. - /// You may override this method to perform further updates specific - /// to the derived trackable. - /// - internal protected virtual void OnAfterSetSessionRelativeData() - { } - - internal void SetSessionRelativeData(TSessionRelativeData sessionRelativeData) - { - this.sessionRelativeData = sessionRelativeData; - transform.localPosition = sessionRelativeData.pose.position; - transform.localRotation = sessionRelativeData.pose.rotation; - } - } -} +using System; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A generic component for trackables. A "trackable" is a feature in the physical + /// environment that can be detected and tracked by an XR device. + /// + /// The raw, session relative data type used to update this trackable. + /// The concrete class which derives from . + public class ARTrackable : MonoBehaviour + where TSessionRelativeData : struct, ITrackable + where TTrackable : ARTrackable + { + [SerializeField] + [Tooltip("If true, this component's GameObject will be removed immediately when this trackable is removed.")] + bool m_DestroyOnRemoval = true; + + /// + /// If true, this component's GameObject will be removed immediately when the XR device reports this trackable is no longer tracked. + /// + /// + /// Setting this to false will keep the GameObject around. You may want to do this, for example, + /// if you have custom removal logic, such as a fade out. + /// + public bool destroyOnRemoval + { + get { return m_DestroyOnRemoval; } + set { m_DestroyOnRemoval = value; } + } + + /// + /// The TrackableId associated with this trackable. TrackableIds + /// are typically unique to a particular session. + /// + public TrackableId trackableId + { + get { return sessionRelativeData.trackableId; } + } + + /// + /// The tracking state associated with this trackable. + /// + public TrackingState trackingState + { + get { return sessionRelativeData.trackingState; } + } + + /// + /// The session-relative data associated with this trackable. + /// + protected TSessionRelativeData sessionRelativeData { get; private set; } + + /// + /// Invoked just after the session-relative data has been set. + /// The GameObject's transform has already been updated. + /// You may override this method to perform further updates specific + /// to the derived trackable. + /// + internal protected virtual void OnAfterSetSessionRelativeData() + { } + + internal void SetSessionRelativeData(TSessionRelativeData sessionRelativeData) + { + this.sessionRelativeData = sessionRelativeData; + transform.localPosition = sessionRelativeData.pose.position; + transform.localRotation = sessionRelativeData.pose.rotation; + } + } +} diff --git a/package/Runtime/AR/ARTrackable.cs.meta b/package/Runtime/AR/ARTrackable.cs.meta index 7d55a3607..f0c7f47b0 100755 --- a/package/Runtime/AR/ARTrackable.cs.meta +++ b/package/Runtime/AR/ARTrackable.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 5f723af2f89cd6349bef1c871638c452 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 5f723af2f89cd6349bef1c871638c452 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARTrackableManager.cs b/package/Runtime/AR/ARTrackableManager.cs index 550b93d4f..b5229329d 100755 --- a/package/Runtime/AR/ARTrackableManager.cs +++ b/package/Runtime/AR/ARTrackableManager.cs @@ -1,305 +1,305 @@ -using System.Collections.Generic; -using Unity.Collections; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A generic manager for components generated by features detected in the physical environment. - /// - /// - /// When the manager is informed that a trackable has been added, a new GameObject - /// is created with an ARTrackable component on it. If - /// - /// is not null, then that prefab will be instantiated. - /// - /// The Subsystem which provides this manager data. - /// The SubsystemDescriptor required to create the Subsystem. - /// A concrete struct used to hold data provided by the Subsystem. - /// The type of component this component will manage (i.e., create, update, and destroy). - [RequireComponent(typeof(ARSessionOrigin))] - [DisallowMultipleComponent] - public abstract class ARTrackableManager - : SubsystemLifecycleManager - where TSubsystem : TrackingSubsystem - where TSubsystemDescriptor : SubsystemDescriptor - where TSessionRelativeData : struct, ITrackable - where TTrackable : ARTrackable - { - /// - /// A collection of all trackables managed by this component. - /// - public TrackableCollection trackables - { - get - { - return new TrackableCollection(m_Trackables); - } - } - - /// - /// The ARSessionOrigin which will be used to instantiate detected trackables. - /// - protected ARSessionOrigin sessionOrigin { get; private set; } - - /// - /// The name prefix that should be used when instantiating new GameObjects. - /// - protected abstract string gameObjectName { get; } - - /// - /// The prefab that should be instantiated when adding a trackable. - /// - protected virtual GameObject GetPrefab() - { - return null; - } - - /// - /// A dictionary of all trackables, keyed by TrackableId. - /// - protected Dictionary m_Trackables; - - /// - /// A dictionary of trackables added via CreateImmedate but not yet reported as added. - /// - protected Dictionary m_PendingAdds; - - /// - /// Invoked by Unity once when this component wakes up. - /// - protected virtual void Awake() - { - m_Trackables = new Dictionary(); - m_PendingAdds = new Dictionary(); - sessionOrigin = GetComponent(); - } - - /// - /// Update is called once per frame. This component's internal state - /// is first updated, and then the event is invoked. - /// - protected virtual void Update() - { - if (subsystem == null) - return; - - using (var changes = subsystem.GetChanges(Allocator.Temp)) - { - ClearAndSetCapacity(s_Added, changes.added.Length); - foreach (var added in changes.added) - s_Added.Add(CreateOrUpdateTrackable(added)); - - ClearAndSetCapacity(s_Updated, changes.updated.Length); - foreach (var updated in changes.updated) - s_Updated.Add(CreateOrUpdateTrackable(updated)); - - ClearAndSetCapacity(s_Removed, changes.removed.Length); - foreach (var trackableId in changes.removed) - { - TTrackable trackable; - if (m_Trackables.TryGetValue(trackableId, out trackable)) - { - m_Trackables.Remove(trackableId); - s_Removed.Add(trackable); - } - } - } - - try - { - // User events - OnTrackablesChanged(s_Added, s_Updated, s_Removed); - } - finally - { - // Make sure destroy happens even if a user callback throws an exception - foreach (var removed in s_Removed) - DestroyTrackable(removed); - } - } - - /// - /// Invoked when trackables have changed, i.e., added, updated, or removed. - /// Use this to perform additional logic, or to invoke public events - /// related to your trackables. - /// - /// A list of trackables added this frame. - /// A list of trackables updated this frame. - /// A list of trackables removed this frame. - /// The trackable components are not destroyed until after this method returns. - protected virtual void OnTrackablesChanged( - List added, - List updated, - List removed) - { } - - /// - /// Invoked just after session relative data has been set on a trackable. - /// - /// The trackable that has just been updated. - /// The session relative data used to update the trackable. - protected virtual void OnAfterSetSessionRelativeData( - TTrackable trackable, - TSessionRelativeData sessionRelativeData) - { } - - /// - /// Creates a immediately, leaving it in a "pending" state. - /// - /// - /// - /// Trackables are usually created, updated, or destroyed during . - /// This method creates a trackable immediately, and marks it as "pending" - /// until it is reported as added by the subsystem. This is useful for subsystems that deal - /// with trackables that can be both detected and manually created. - /// - /// This method does not invoke , - /// so no "added" notifications will occur until the next call to . - /// However, this method does invoke - /// on the new trackable. - /// - /// The trackable will appear in the collection immediately. - /// - /// - /// A new TTrackable - protected TTrackable CreateTrackableImmediate(TSessionRelativeData sessionRelativeData) - { - var trackable = CreateOrUpdateTrackable(sessionRelativeData); - m_PendingAdds.Add(trackable.trackableId, trackable); - return trackable; - } - - /// - /// If in a "pending" state, the trackable with 's - /// - /// event is invoked, and the trackable's GameObject destroyed if - /// is true. - /// Otherwise, this method has no effect. - /// - /// - /// - /// Trackables are usually removed only when the subsystem reports they - /// have been removed during - /// - /// This method will immediately remove a trackable only if it was created by - /// - /// and has not yet been reported as added by the - /// . - /// - /// This can happen if the trackable is created and removed within the same frame, as the subsystem may never - /// have a chance to report its existence. Derived classes should use this - /// if they support the concept of manual addition and removal of trackables, as there may not - /// be a removal event if the trackable is added and removed quickly. - /// - /// If the trackable is not in a pending state, i.e., it has already been reported as "added", - /// then this method does nothing. - /// - /// - /// This method does not invoke , - /// so no "removed" notifications will occur until the next call to (and only if it was - /// previously reported as "added"). - /// However, this method does invoke - /// on the trackable. - /// - /// - /// True if the trackable is "pending" (i.e., not yet reported as "added"). - protected bool DestroyPendingTrackable(TrackableId trackableId) - { - TTrackable trackable; - if (m_PendingAdds.TryGetValue(trackableId, out trackable)) - { - m_PendingAdds.Remove(trackableId); - m_Trackables.Remove(trackableId); - DestroyTrackable(trackable); - return true; - } - - return false; - } - - static void ClearAndSetCapacity(List list, int capacity) - { - list.Clear(); - if (list.Capacity < capacity) - list.Capacity = capacity; - } - - string GetTrackableName(TrackableId trackableId) - { - return gameObjectName + " " + trackableId.ToString(); - } - - GameObject CreateGameObject() - { - var prefab = GetPrefab(); - if (prefab == null) - { - var go = new GameObject(); - go.transform.parent = sessionOrigin.trackablesParent; - return go; - } - - return Instantiate(prefab, sessionOrigin.trackablesParent); - } - - GameObject CreateGameObject(string name) - { - var go = CreateGameObject(); - go.name = name; - return go; - } - - GameObject CreateGameObject(TrackableId trackableId) - { - return CreateGameObject(GetTrackableName(trackableId)); - } - - TTrackable CreateTrackable(TrackableId trackableId) - { - var go = CreateGameObject(trackableId); - var trackable = go.GetComponent(); - if (trackable == null) - trackable = go.AddComponent(); - - return trackable; - } - - TTrackable GetOrCreateTrackable(TrackableId trackableId) - { - TTrackable trackable; - if (m_Trackables.TryGetValue(trackableId, out trackable)) - { - m_PendingAdds.Remove(trackableId); - } - else - { - trackable = CreateTrackable(trackableId); - m_Trackables.Add(trackableId, trackable); - } - - return trackable; - } - - TTrackable CreateOrUpdateTrackable(TSessionRelativeData sessionRelativeData) - { - var trackable = GetOrCreateTrackable(sessionRelativeData.trackableId); - trackable.SetSessionRelativeData(sessionRelativeData); - OnAfterSetSessionRelativeData(trackable, sessionRelativeData); - trackable.OnAfterSetSessionRelativeData(); - return trackable; - } - - void DestroyTrackable(TTrackable trackable) - { - if (trackable.destroyOnRemoval) - Destroy(trackable.gameObject); - } - - static List s_Added = new List(); - - static List s_Updated = new List(); - - static List s_Removed = new List(); - } -} +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A generic manager for components generated by features detected in the physical environment. + /// + /// + /// When the manager is informed that a trackable has been added, a new GameObject + /// is created with an ARTrackable component on it. If + /// + /// is not null, then that prefab will be instantiated. + /// + /// The Subsystem which provides this manager data. + /// The SubsystemDescriptor required to create the Subsystem. + /// A concrete struct used to hold data provided by the Subsystem. + /// The type of component this component will manage (i.e., create, update, and destroy). + [RequireComponent(typeof(ARSessionOrigin))] + [DisallowMultipleComponent] + public abstract class ARTrackableManager + : SubsystemLifecycleManager + where TSubsystem : TrackingSubsystem + where TSubsystemDescriptor : SubsystemDescriptor + where TSessionRelativeData : struct, ITrackable + where TTrackable : ARTrackable + { + /// + /// A collection of all trackables managed by this component. + /// + public TrackableCollection trackables + { + get + { + return new TrackableCollection(m_Trackables); + } + } + + /// + /// The ARSessionOrigin which will be used to instantiate detected trackables. + /// + protected ARSessionOrigin sessionOrigin { get; private set; } + + /// + /// The name prefix that should be used when instantiating new GameObjects. + /// + protected abstract string gameObjectName { get; } + + /// + /// The prefab that should be instantiated when adding a trackable. + /// + protected virtual GameObject GetPrefab() + { + return null; + } + + /// + /// A dictionary of all trackables, keyed by TrackableId. + /// + protected Dictionary m_Trackables; + + /// + /// A dictionary of trackables added via CreateImmedate but not yet reported as added. + /// + protected Dictionary m_PendingAdds; + + /// + /// Invoked by Unity once when this component wakes up. + /// + protected virtual void Awake() + { + m_Trackables = new Dictionary(); + m_PendingAdds = new Dictionary(); + sessionOrigin = GetComponent(); + } + + /// + /// Update is called once per frame. This component's internal state + /// is first updated, and then the event is invoked. + /// + protected virtual void Update() + { + if (subsystem == null) + return; + + using (var changes = subsystem.GetChanges(Allocator.Temp)) + { + ClearAndSetCapacity(s_Added, changes.added.Length); + foreach (var added in changes.added) + s_Added.Add(CreateOrUpdateTrackable(added)); + + ClearAndSetCapacity(s_Updated, changes.updated.Length); + foreach (var updated in changes.updated) + s_Updated.Add(CreateOrUpdateTrackable(updated)); + + ClearAndSetCapacity(s_Removed, changes.removed.Length); + foreach (var trackableId in changes.removed) + { + TTrackable trackable; + if (m_Trackables.TryGetValue(trackableId, out trackable)) + { + m_Trackables.Remove(trackableId); + s_Removed.Add(trackable); + } + } + } + + try + { + // User events + OnTrackablesChanged(s_Added, s_Updated, s_Removed); + } + finally + { + // Make sure destroy happens even if a user callback throws an exception + foreach (var removed in s_Removed) + DestroyTrackable(removed); + } + } + + /// + /// Invoked when trackables have changed, i.e., added, updated, or removed. + /// Use this to perform additional logic, or to invoke public events + /// related to your trackables. + /// + /// A list of trackables added this frame. + /// A list of trackables updated this frame. + /// A list of trackables removed this frame. + /// The trackable components are not destroyed until after this method returns. + protected virtual void OnTrackablesChanged( + List added, + List updated, + List removed) + { } + + /// + /// Invoked just after session relative data has been set on a trackable. + /// + /// The trackable that has just been updated. + /// The session relative data used to update the trackable. + protected virtual void OnAfterSetSessionRelativeData( + TTrackable trackable, + TSessionRelativeData sessionRelativeData) + { } + + /// + /// Creates a immediately, leaving it in a "pending" state. + /// + /// + /// + /// Trackables are usually created, updated, or destroyed during . + /// This method creates a trackable immediately, and marks it as "pending" + /// until it is reported as added by the subsystem. This is useful for subsystems that deal + /// with trackables that can be both detected and manually created. + /// + /// This method does not invoke , + /// so no "added" notifications will occur until the next call to . + /// However, this method does invoke + /// on the new trackable. + /// + /// The trackable will appear in the collection immediately. + /// + /// + /// A new TTrackable + protected TTrackable CreateTrackableImmediate(TSessionRelativeData sessionRelativeData) + { + var trackable = CreateOrUpdateTrackable(sessionRelativeData); + m_PendingAdds.Add(trackable.trackableId, trackable); + return trackable; + } + + /// + /// If in a "pending" state, the trackable with 's + /// + /// event is invoked, and the trackable's GameObject destroyed if + /// is true. + /// Otherwise, this method has no effect. + /// + /// + /// + /// Trackables are usually removed only when the subsystem reports they + /// have been removed during + /// + /// This method will immediately remove a trackable only if it was created by + /// + /// and has not yet been reported as added by the + /// . + /// + /// This can happen if the trackable is created and removed within the same frame, as the subsystem may never + /// have a chance to report its existence. Derived classes should use this + /// if they support the concept of manual addition and removal of trackables, as there may not + /// be a removal event if the trackable is added and removed quickly. + /// + /// If the trackable is not in a pending state, i.e., it has already been reported as "added", + /// then this method does nothing. + /// + /// + /// This method does not invoke , + /// so no "removed" notifications will occur until the next call to (and only if it was + /// previously reported as "added"). + /// However, this method does invoke + /// on the trackable. + /// + /// + /// True if the trackable is "pending" (i.e., not yet reported as "added"). + protected bool DestroyPendingTrackable(TrackableId trackableId) + { + TTrackable trackable; + if (m_PendingAdds.TryGetValue(trackableId, out trackable)) + { + m_PendingAdds.Remove(trackableId); + m_Trackables.Remove(trackableId); + DestroyTrackable(trackable); + return true; + } + + return false; + } + + static void ClearAndSetCapacity(List list, int capacity) + { + list.Clear(); + if (list.Capacity < capacity) + list.Capacity = capacity; + } + + string GetTrackableName(TrackableId trackableId) + { + return gameObjectName + " " + trackableId.ToString(); + } + + GameObject CreateGameObject() + { + var prefab = GetPrefab(); + if (prefab == null) + { + var go = new GameObject(); + go.transform.parent = sessionOrigin.trackablesParent; + return go; + } + + return Instantiate(prefab, sessionOrigin.trackablesParent); + } + + GameObject CreateGameObject(string name) + { + var go = CreateGameObject(); + go.name = name; + return go; + } + + GameObject CreateGameObject(TrackableId trackableId) + { + return CreateGameObject(GetTrackableName(trackableId)); + } + + TTrackable CreateTrackable(TrackableId trackableId) + { + var go = CreateGameObject(trackableId); + var trackable = go.GetComponent(); + if (trackable == null) + trackable = go.AddComponent(); + + return trackable; + } + + TTrackable GetOrCreateTrackable(TrackableId trackableId) + { + TTrackable trackable; + if (m_Trackables.TryGetValue(trackableId, out trackable)) + { + m_PendingAdds.Remove(trackableId); + } + else + { + trackable = CreateTrackable(trackableId); + m_Trackables.Add(trackableId, trackable); + } + + return trackable; + } + + TTrackable CreateOrUpdateTrackable(TSessionRelativeData sessionRelativeData) + { + var trackable = GetOrCreateTrackable(sessionRelativeData.trackableId); + trackable.SetSessionRelativeData(sessionRelativeData); + OnAfterSetSessionRelativeData(trackable, sessionRelativeData); + trackable.OnAfterSetSessionRelativeData(); + return trackable; + } + + void DestroyTrackable(TTrackable trackable) + { + if (trackable.destroyOnRemoval) + Destroy(trackable.gameObject); + } + + static List s_Added = new List(); + + static List s_Updated = new List(); + + static List s_Removed = new List(); + } +} diff --git a/package/Runtime/AR/ARTrackableManager.cs.meta b/package/Runtime/AR/ARTrackableManager.cs.meta index e31430105..e03859e6d 100755 --- a/package/Runtime/AR/ARTrackableManager.cs.meta +++ b/package/Runtime/AR/ARTrackableManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 5573a38462d52344e933546406be7811 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 5573a38462d52344e933546406be7811 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/ARUpdateOrder.cs b/package/Runtime/AR/ARUpdateOrder.cs index f02f6f0a8..1b4958825 100755 --- a/package/Runtime/AR/ARUpdateOrder.cs +++ b/package/Runtime/AR/ARUpdateOrder.cs @@ -1,61 +1,61 @@ -namespace UnityEngine.XR.ARFoundation -{ - /// - /// The update order for MonoBehaviours in ARFoundation. - /// - public static class ARUpdateOrder - { - /// - /// The 's update order. Should come first. - /// - public const int k_Session = int.MinValue; - - /// - /// The 's update order. Should come after - /// the . - /// - public const int k_PlaneManager = k_Session + 1; - - /// - /// The 's update order. Should come after the - /// . - /// - public const int k_Plane = k_PlaneManager + 1; - - /// - /// The 's update order. Should come - /// after the . - /// - public const int k_PointCloudManager = k_Session + 1; - - /// - /// The 's update order. Should come after - /// the . - /// - public const int k_PointCloud = k_PointCloudManager + 1; - - /// - /// The 's update order. - /// Should come after the . - /// - public const int k_ReferencePointManager = k_Session + 1; - - /// - /// The 's update order. - /// Should come after the . - /// - public const int k_ReferencePoint = k_ReferencePointManager + 1; - - /// - /// The 's update order. Should come after - /// the . - /// - public const int k_InputManager = k_Session + 1; - - /// - /// The 's update order. Should come after - /// the . - /// - public const int k_CameraManager = k_Session + 1; - } -} +namespace UnityEngine.XR.ARFoundation +{ + /// + /// The update order for MonoBehaviours in ARFoundation. + /// + public static class ARUpdateOrder + { + /// + /// The 's update order. Should come first. + /// + public const int k_Session = int.MinValue; + + /// + /// The 's update order. Should come after + /// the . + /// + public const int k_PlaneManager = k_Session + 1; + + /// + /// The 's update order. Should come after the + /// . + /// + public const int k_Plane = k_PlaneManager + 1; + + /// + /// The 's update order. Should come + /// after the . + /// + public const int k_PointCloudManager = k_Session + 1; + + /// + /// The 's update order. Should come after + /// the . + /// + public const int k_PointCloud = k_PointCloudManager + 1; + + /// + /// The 's update order. + /// Should come after the . + /// + public const int k_ReferencePointManager = k_Session + 1; + + /// + /// The 's update order. + /// Should come after the . + /// + public const int k_ReferencePoint = k_ReferencePointManager + 1; + + /// + /// The 's update order. Should come after + /// the . + /// + public const int k_InputManager = k_Session + 1; + + /// + /// The 's update order. Should come after + /// the . + /// + public const int k_CameraManager = k_Session + 1; + } +} diff --git a/package/Runtime/AR/ARUpdateOrder.cs.meta b/package/Runtime/AR/ARUpdateOrder.cs.meta index f3c2559fe..35e11a9d8 100755 --- a/package/Runtime/AR/ARUpdateOrder.cs.meta +++ b/package/Runtime/AR/ARUpdateOrder.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 7051dd1ee16844b9883b7cc83b51dfc6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 7051dd1ee16844b9883b7cc83b51dfc6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/IRaycaster.cs b/package/Runtime/AR/IRaycaster.cs index 95a3c2aa0..a7bb11d50 100755 --- a/package/Runtime/AR/IRaycaster.cs +++ b/package/Runtime/AR/IRaycaster.cs @@ -1,23 +1,23 @@ -using Unity.Collections; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// An interface for performing raycasts against trackables. Generally implemented by - /// derived classes of . - /// - internal interface IRaycaster - { - /// - /// Performs a raycast. - /// - /// A ray, in session space. - /// The types of raycast to perform. - /// An array of raycast results. - NativeArray Raycast( - Ray sessionSpaceRay, - TrackableType trackableTypeMask, - Allocator allocator); - } -} +using Unity.Collections; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// An interface for performing raycasts against trackables. Generally implemented by + /// derived classes of . + /// + internal interface IRaycaster + { + /// + /// Performs a raycast. + /// + /// A ray, in session space. + /// The types of raycast to perform. + /// An array of raycast results. + NativeArray Raycast( + Ray sessionSpaceRay, + TrackableType trackableTypeMask, + Allocator allocator); + } +} diff --git a/package/Runtime/AR/IRaycaster.cs.meta b/package/Runtime/AR/IRaycaster.cs.meta index d2c47d1b7..85699c022 100755 --- a/package/Runtime/AR/IRaycaster.cs.meta +++ b/package/Runtime/AR/IRaycaster.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 6c1d1d1fa92298641b8c8b81ddb7ec51 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 6c1d1d1fa92298641b8c8b81ddb7ec51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs b/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs index efde6e60f..93f383d96 100755 --- a/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs +++ b/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs @@ -1,9 +1,9 @@ -namespace UnityEngine.XR.ARFoundation -{ - /// - /// An attribute that can be placed on MonoBehaviour fields to - /// generate the correct UI for the - /// enum. - /// - public class PlaneDetectionModeMaskAttribute : PropertyAttribute { } -} +namespace UnityEngine.XR.ARFoundation +{ + /// + /// An attribute that can be placed on MonoBehaviour fields to + /// generate the correct UI for the + /// enum. + /// + public class PlaneDetectionModeMaskAttribute : PropertyAttribute { } +} diff --git a/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs.meta b/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs.meta index 64ad1b134..5e2a98c3d 100755 --- a/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs.meta +++ b/package/Runtime/AR/PlaneDetectionModeMaskAttribute.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 9772a881d96bb454b9c893503a57a7e2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 9772a881d96bb454b9c893503a57a7e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/PoseExtensions.cs b/package/Runtime/AR/PoseExtensions.cs index 26efc8200..9c3e022b8 100755 --- a/package/Runtime/AR/PoseExtensions.cs +++ b/package/Runtime/AR/PoseExtensions.cs @@ -1,50 +1,50 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Several method extensions to Pose for inverse-transforming additional Unity types. - /// - public static class PoseExtensions - { - /// - /// Inversely transform the by Pose. - /// - /// The Pose to use. - /// A position to inversely transform - /// An position inversely transformed by the . - public static Vector3 InverseTransformPosition(this Pose pose, Vector3 position) - { - return Quaternion.Inverse(pose.rotation) * (position - pose.position); - } - - /// - /// Inversely transform the by Pose. - /// - /// The Pose to use. - /// A direction to inversely transform - /// An direction inversely transformed by the . - public static Vector3 InverseTransformDirection(this Pose pose, Vector3 direction) - { - return Quaternion.Inverse(pose.rotation) * direction; - } - - /// - /// Inversely transform the by Pose. The transform is made in-place. - /// - /// The Pose to use. - /// A List of positions to inversely transform - public static void InverseTransformPositions(this Pose pose, List positions) - { - if (positions == null) - throw new ArgumentNullException("positions"); - - for (int i = 0; i < positions.Count; ++i) - { - positions[i] = pose.InverseTransformPosition(positions[i]); - } - } - - } -} +using System; +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Several method extensions to Pose for inverse-transforming additional Unity types. + /// + public static class PoseExtensions + { + /// + /// Inversely transform the by Pose. + /// + /// The Pose to use. + /// A position to inversely transform + /// An position inversely transformed by the . + public static Vector3 InverseTransformPosition(this Pose pose, Vector3 position) + { + return Quaternion.Inverse(pose.rotation) * (position - pose.position); + } + + /// + /// Inversely transform the by Pose. + /// + /// The Pose to use. + /// A direction to inversely transform + /// An direction inversely transformed by the . + public static Vector3 InverseTransformDirection(this Pose pose, Vector3 direction) + { + return Quaternion.Inverse(pose.rotation) * direction; + } + + /// + /// Inversely transform the by Pose. The transform is made in-place. + /// + /// The Pose to use. + /// A List of positions to inversely transform + public static void InverseTransformPositions(this Pose pose, List positions) + { + if (positions == null) + throw new ArgumentNullException("positions"); + + for (int i = 0; i < positions.Count; ++i) + { + positions[i] = pose.InverseTransformPosition(positions[i]); + } + } + + } +} diff --git a/package/Runtime/AR/PoseExtensions.cs.meta b/package/Runtime/AR/PoseExtensions.cs.meta index d39fcfed2..70b41938d 100755 --- a/package/Runtime/AR/PoseExtensions.cs.meta +++ b/package/Runtime/AR/PoseExtensions.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 650dbb454746aad4082f238ef25b1cde -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 650dbb454746aad4082f238ef25b1cde +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/SubsystemLifecycleManager.cs b/package/Runtime/AR/SubsystemLifecycleManager.cs index e45b8859b..7fcfbeb92 100755 --- a/package/Runtime/AR/SubsystemLifecycleManager.cs +++ b/package/Runtime/AR/SubsystemLifecycleManager.cs @@ -1,105 +1,105 @@ -using System.Collections.Generic; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A base class for subsystems whose lifetime is managed by a MonoBehaviour. - /// - /// The Subsystem which provides this manager data. - /// The SubsystemDescriptor required to create the Subsystem. - public class SubsystemLifecycleManager : MonoBehaviour - where TSubsystem : Subsystem - where TSubsystemDescriptor : SubsystemDescriptor - { - /// - /// Get the TSubsystem whose lifetime this component manages. - /// - public TSubsystem subsystem { get; private set; } - - /// - /// Creates a TSubsystem. - /// - /// The first Subsystem of matching the TSubsystemDescriptor, or null if there aren't any. - protected virtual TSubsystem CreateSubsystem() - { - SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); - if (s_SubsystemDescriptors.Count > 0) - { - var descriptor = s_SubsystemDescriptors[0]; - if (s_SubsystemDescriptors.Count > 1) - { - Debug.LogWarningFormat("Multiple {0} found. Using {1}", - typeof(TSubsystem).Name, - descriptor.id); - } - - return descriptor.Create(); - } - else - { - return null; - } - } - - /// - /// Creates a subsystem if subsystem is null. - /// - protected void CreateSubsystemIfNecessary() - { - if (subsystem == null) - subsystem = CreateSubsystem(); - } - - /// - /// Creates the TSubsystem. - /// - protected virtual void OnEnable() - { - CreateSubsystemIfNecessary(); - - if (subsystem != null) - { - OnBeforeStart(); - subsystem.Start(); - OnAfterStart(); - } - } - - /// - /// Stops the TSubsystem. - /// - protected virtual void OnDisable() - { - if (subsystem != null) - subsystem.Stop(); - } - - /// - /// Destroys the TSubsystem. - /// - protected virtual void OnDestroy() - { - if (subsystem != null) - subsystem.Destroy(); - - subsystem = null; - } - - /// - /// Invoked after creating the subsystem and before calling Start on it. - /// The is not null. - /// - protected virtual void OnBeforeStart() - { } - - /// - /// Invoked after calling Start on it the Subsystem. - /// The is not null. - /// - protected virtual void OnAfterStart() - { } - - static List s_SubsystemDescriptors = - new List(); - } -} +using System.Collections.Generic; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A base class for subsystems whose lifetime is managed by a MonoBehaviour. + /// + /// The Subsystem which provides this manager data. + /// The SubsystemDescriptor required to create the Subsystem. + public class SubsystemLifecycleManager : MonoBehaviour + where TSubsystem : Subsystem + where TSubsystemDescriptor : SubsystemDescriptor + { + /// + /// Get the TSubsystem whose lifetime this component manages. + /// + public TSubsystem subsystem { get; private set; } + + /// + /// Creates a TSubsystem. + /// + /// The first Subsystem of matching the TSubsystemDescriptor, or null if there aren't any. + protected virtual TSubsystem CreateSubsystem() + { + SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors); + if (s_SubsystemDescriptors.Count > 0) + { + var descriptor = s_SubsystemDescriptors[0]; + if (s_SubsystemDescriptors.Count > 1) + { + Debug.LogWarningFormat("Multiple {0} found. Using {1}", + typeof(TSubsystem).Name, + descriptor.id); + } + + return descriptor.Create(); + } + else + { + return null; + } + } + + /// + /// Creates a subsystem if subsystem is null. + /// + protected void CreateSubsystemIfNecessary() + { + if (subsystem == null) + subsystem = CreateSubsystem(); + } + + /// + /// Creates the TSubsystem. + /// + protected virtual void OnEnable() + { + CreateSubsystemIfNecessary(); + + if (subsystem != null) + { + OnBeforeStart(); + subsystem.Start(); + OnAfterStart(); + } + } + + /// + /// Stops the TSubsystem. + /// + protected virtual void OnDisable() + { + if (subsystem != null) + subsystem.Stop(); + } + + /// + /// Destroys the TSubsystem. + /// + protected virtual void OnDestroy() + { + if (subsystem != null) + subsystem.Destroy(); + + subsystem = null; + } + + /// + /// Invoked after creating the subsystem and before calling Start on it. + /// The is not null. + /// + protected virtual void OnBeforeStart() + { } + + /// + /// Invoked after calling Start on it the Subsystem. + /// The is not null. + /// + protected virtual void OnAfterStart() + { } + + static List s_SubsystemDescriptors = + new List(); + } +} diff --git a/package/Runtime/AR/SubsystemLifecycleManager.cs.meta b/package/Runtime/AR/SubsystemLifecycleManager.cs.meta index ac482ba78..b3d96eef2 100755 --- a/package/Runtime/AR/SubsystemLifecycleManager.cs.meta +++ b/package/Runtime/AR/SubsystemLifecycleManager.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: ae3a8318ae541d645a747de20dced0e9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: ae3a8318ae541d645a747de20dced0e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/TrackableCollection.cs b/package/Runtime/AR/TrackableCollection.cs index 8e30ad9ab..ab44d9a54 100755 --- a/package/Runtime/AR/TrackableCollection.cs +++ b/package/Runtime/AR/TrackableCollection.cs @@ -1,140 +1,140 @@ -using System; -using System.Collections.Generic; -using UnityEngine.XR.ARSubsystems; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// A collection for s. - /// This collection implements an IEnumerable-like interface which can be used - /// in a foreach statement. - /// - /// The concrete . - public struct TrackableCollection - { - /// - /// Creates an Enumerator for this collection. - /// - /// - public Enumerator GetEnumerator() - { - return new Enumerator(m_Trackables); - } - - /// - /// Constructs a . - /// - /// - public TrackableCollection(Dictionary trackables) - { - if (trackables == null) - throw new ArgumentNullException("trackables"); - - m_Trackables = trackables; - } - - /// - /// Returns the number of trackables in this collection. - /// - public int count - { - get - { - if (m_Trackables == null) - throw new InvalidOperationException("This collection has not been initialized."); - - return m_Trackables.Count; - } - } - - /// - /// Retrieves a TTrackables by TrackableId. - /// - /// The trackable id associated with the trackable to retrieve. - /// The TTrackables if present. Throws KeyNotFoundException if the is not found. - public TTrackable this[TrackableId trackableId] - { - get - { - if (m_Trackables == null) - throw new InvalidOperationException("This collection has not been initialized."); - - try - { - return m_Trackables[trackableId]; - } - catch (KeyNotFoundException e) - { - throw new KeyNotFoundException( - string.Format("Trackable with id {0} does not exist in this collection.", trackableId), - e); - } - } - } - - /// - /// Attempts to retrieve a trackable by TrackableId. - /// - /// The trackable id associated with the trackable to retrieve. - /// Set to the trackable with , if present in the collection. - /// true if the trackable with exists. false otherwise. - public bool TryGetTrackable(TrackableId trackableId, out TTrackable trackable) - { - if (m_Trackables == null) - throw new InvalidOperationException("This collection has not been initialized."); - - return m_Trackables.TryGetValue(trackableId, out trackable); - } - - /// - /// An Enumerator for TTrackables. - /// - public struct Enumerator - { - /// - /// Constructs an Enumerator for use with TTrackables. - /// - /// A Dictionary of TTrackables. - public Enumerator(Dictionary trackables) - { - if (trackables == null) - throw new ArgumentNullException("trackables"); - - m_Enumerator = trackables.GetEnumerator(); - } - - /// - /// Moves to the next trackable in the collection. - /// - /// true if the next trackable is valid, or false if it is the end of the collection. - public bool MoveNext() - { - return m_Enumerator.MoveNext(); - } - - /// - /// The current value in the collection. - /// - public TTrackable Current - { - get - { - return m_Enumerator.Current.Value; - } - } - - /// - /// Releases all resources used by this Enumerator. - /// - public void Dispose() - { - m_Enumerator.Dispose(); - } - - Dictionary.Enumerator m_Enumerator; - - } - - Dictionary m_Trackables; - } -} +using System; +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// A collection for s. + /// This collection implements an IEnumerable-like interface which can be used + /// in a foreach statement. + /// + /// The concrete . + public struct TrackableCollection + { + /// + /// Creates an Enumerator for this collection. + /// + /// + public Enumerator GetEnumerator() + { + return new Enumerator(m_Trackables); + } + + /// + /// Constructs a . + /// + /// + public TrackableCollection(Dictionary trackables) + { + if (trackables == null) + throw new ArgumentNullException("trackables"); + + m_Trackables = trackables; + } + + /// + /// Returns the number of trackables in this collection. + /// + public int count + { + get + { + if (m_Trackables == null) + throw new InvalidOperationException("This collection has not been initialized."); + + return m_Trackables.Count; + } + } + + /// + /// Retrieves a TTrackables by TrackableId. + /// + /// The trackable id associated with the trackable to retrieve. + /// The TTrackables if present. Throws KeyNotFoundException if the is not found. + public TTrackable this[TrackableId trackableId] + { + get + { + if (m_Trackables == null) + throw new InvalidOperationException("This collection has not been initialized."); + + try + { + return m_Trackables[trackableId]; + } + catch (KeyNotFoundException e) + { + throw new KeyNotFoundException( + string.Format("Trackable with id {0} does not exist in this collection.", trackableId), + e); + } + } + } + + /// + /// Attempts to retrieve a trackable by TrackableId. + /// + /// The trackable id associated with the trackable to retrieve. + /// Set to the trackable with , if present in the collection. + /// true if the trackable with exists. false otherwise. + public bool TryGetTrackable(TrackableId trackableId, out TTrackable trackable) + { + if (m_Trackables == null) + throw new InvalidOperationException("This collection has not been initialized."); + + return m_Trackables.TryGetValue(trackableId, out trackable); + } + + /// + /// An Enumerator for TTrackables. + /// + public struct Enumerator + { + /// + /// Constructs an Enumerator for use with TTrackables. + /// + /// A Dictionary of TTrackables. + public Enumerator(Dictionary trackables) + { + if (trackables == null) + throw new ArgumentNullException("trackables"); + + m_Enumerator = trackables.GetEnumerator(); + } + + /// + /// Moves to the next trackable in the collection. + /// + /// true if the next trackable is valid, or false if it is the end of the collection. + public bool MoveNext() + { + return m_Enumerator.MoveNext(); + } + + /// + /// The current value in the collection. + /// + public TTrackable Current + { + get + { + return m_Enumerator.Current.Value; + } + } + + /// + /// Releases all resources used by this Enumerator. + /// + public void Dispose() + { + m_Enumerator.Dispose(); + } + + Dictionary.Enumerator m_Enumerator; + + } + + Dictionary m_Trackables; + } +} diff --git a/package/Runtime/AR/TrackableCollection.cs.meta b/package/Runtime/AR/TrackableCollection.cs.meta index 323f38b28..9fd2192b0 100755 --- a/package/Runtime/AR/TrackableCollection.cs.meta +++ b/package/Runtime/AR/TrackableCollection.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 426ec96995a2d2c4b90f4302caa19b32 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 426ec96995a2d2c4b90f4302caa19b32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/AR/TransformExtensions.cs b/package/Runtime/AR/TransformExtensions.cs index 0a426c457..20f393ea1 100755 --- a/package/Runtime/AR/TransformExtensions.cs +++ b/package/Runtime/AR/TransformExtensions.cs @@ -1,168 +1,132 @@ -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.XR; - -namespace UnityEngine.XR.ARFoundation -{ - /// - /// Several method extensions to Transform for transforming and inverse-transforming additional Unity types. - /// - public static class TransformExtensions - { - /// - /// Transforms a Ray - /// - /// The Transform component - /// The Ray to transform - /// A new Ray representing the transformed - public static Ray TransformRay(this Transform transform, Ray ray) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - return new Ray( - transform.TransformPoint(ray.origin), - transform.TransformDirection(ray.direction)); - } - - /// - /// Inverse transforms a Ray - /// - /// The Transform component - /// The Ray to inversely transform - /// A new Ray representing the inversely transformed - public static Ray InverseTransformRay(this Transform transform, Ray ray) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - return new Ray( - transform.InverseTransformPoint(ray.origin), - transform.InverseTransformDirection(ray.direction)); - } - - /// - /// Transforms a Pose - /// - /// The Transform component - /// The Pose to transform - /// A new Pose representing the transformed - public static Pose TransformPose(this Transform transform, Pose pose) - { - return pose.GetTransformedBy(transform); - } - - /// - /// Inverse transforms a Pose - /// - /// The Transform component - /// The Pose to inversely transform - /// A new Pose representing the inversely transformed - public static Pose InverseTransformPose(this Transform transform, Pose pose) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - return new Pose - { - position = transform.InverseTransformPoint(pose.position), - rotation = Quaternion.Inverse(transform.rotation) * pose.rotation - }; - } - - /// - /// Transforms a List of XRRaycastHits. - /// - /// The Transform component - /// The XRRaycastHits to transform. This is done in-place. - public static void TransformXRRaycastHits(this Transform transform, List raycastHits) - { - if (raycastHits == null) - throw new ArgumentNullException("raycastHits"); - - for (int i = 0; i < raycastHits.Count; ++i) - { - var raycastHit = raycastHits[i]; - raycastHit.Pose = transform.TransformPose(raycastHit.Pose); - raycastHits[i] = raycastHit; - } - } - - /// - /// Inverse transforms a List of XRRaycastHits. - /// - /// The Transform component - /// The XRRaycastHits to inverse transform. This is done in-place. - public static void InverseTransformXRRaycastHits(this Transform transform, List raycastHits) - { - if (raycastHits == null) - throw new ArgumentNullException("raycastHits"); - - for (int i = 0; i < raycastHits.Count; ++i) - { - var raycastHit = raycastHits[i]; - raycastHit.Pose = transform.InverseTransformPose(raycastHit.Pose); - raycastHits[i] = raycastHit; - } - } - - /// - /// Transforms a List of positions. - /// - /// The Transform component - /// The points to transform. The points are transformed in-place. - public static void TransformPointList(this Transform transform, List points) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - if (points == null) - throw new ArgumentNullException("points"); - - for (int i = 0; i < points.Count; ++i) - { - points[i] = transform.TransformPoint(points[i]); - } - } - - /// - /// Inverse transforms a List of Vector3s. - /// - /// The Transform component - /// The points to inverse transform. This is done in-place. - public static void InverseTransformPointList(this Transform transform, List points) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - if (points == null) - throw new ArgumentNullException("points"); - - for (int i = 0; i < points.Count; ++i) - { - points[i] = transform.InverseTransformPoint(points[i]); - } - } - - /// - /// Sets the layer for the GameObject associated with and all its children. - /// - /// The Transform component - /// The layer in which the game object should be. - public static void SetLayerRecursively(this Transform transform, int layer) - { - if (transform == null) - throw new ArgumentNullException("transform"); - - // Set self - transform.gameObject.layer = layer; - - // Set all child layers recursively - for (var i = 0; i < transform.childCount; ++i) - { - var child = transform.GetChild(i); - child.SetLayerRecursively(layer); - } - } - } -} +using System; +using System.Collections.Generic; +using UnityEngine.XR.ARSubsystems; + +namespace UnityEngine.XR.ARFoundation +{ + /// + /// Several method extensions to Transform for transforming and inverse-transforming additional Unity types. + /// + public static class TransformExtensions + { + /// + /// Transforms a Ray + /// + /// The Transform component + /// The Ray to transform + /// A new Ray representing the transformed + public static Ray TransformRay(this Transform transform, Ray ray) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + return new Ray( + transform.TransformPoint(ray.origin), + transform.TransformDirection(ray.direction)); + } + + /// + /// Inverse transforms a Ray + /// + /// The Transform component + /// The Ray to inversely transform + /// A new Ray representing the inversely transformed + public static Ray InverseTransformRay(this Transform transform, Ray ray) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + return new Ray( + transform.InverseTransformPoint(ray.origin), + transform.InverseTransformDirection(ray.direction)); + } + + /// + /// Transforms a Pose + /// + /// The Transform component + /// The Pose to transform + /// A new Pose representing the transformed + public static Pose TransformPose(this Transform transform, Pose pose) + { + return pose.GetTransformedBy(transform); + } + + /// + /// Inverse transforms a Pose + /// + /// The Transform component + /// The Pose to inversely transform + /// A new Pose representing the inversely transformed + public static Pose InverseTransformPose(this Transform transform, Pose pose) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + return new Pose + { + position = transform.InverseTransformPoint(pose.position), + rotation = Quaternion.Inverse(transform.rotation) * pose.rotation + }; + } + + /// + /// Transforms a List of positions. + /// + /// The Transform component + /// The points to transform. The points are transformed in-place. + public static void TransformPointList(this Transform transform, List points) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + if (points == null) + throw new ArgumentNullException("points"); + + for (int i = 0; i < points.Count; ++i) + { + points[i] = transform.TransformPoint(points[i]); + } + } + + /// + /// Inverse transforms a List of Vector3s. + /// + /// The Transform component + /// The points to inverse transform. This is done in-place. + public static void InverseTransformPointList(this Transform transform, List points) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + if (points == null) + throw new ArgumentNullException("points"); + + for (int i = 0; i < points.Count; ++i) + { + points[i] = transform.InverseTransformPoint(points[i]); + } + } + + /// + /// Sets the layer for the GameObject associated with and all its children. + /// + /// The Transform component + /// The layer in which the game object should be. + public static void SetLayerRecursively(this Transform transform, int layer) + { + if (transform == null) + throw new ArgumentNullException("transform"); + + // Set self + transform.gameObject.layer = layer; + + // Set all child layers recursively + for (var i = 0; i < transform.childCount; ++i) + { + var child = transform.GetChild(i); + child.SetLayerRecursively(layer); + } + } + } +} diff --git a/package/Runtime/AR/TransformExtensions.cs.meta b/package/Runtime/AR/TransformExtensions.cs.meta index a79ae6731..df0ef779c 100755 --- a/package/Runtime/AR/TransformExtensions.cs.meta +++ b/package/Runtime/AR/TransformExtensions.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 23ac6ce2afe57a64a8bce96ef4774eab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 23ac6ce2afe57a64a8bce96ef4774eab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c78afcd92a9a33748b02af87f8c94208, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Runtime/Unity.XR.ARFoundation.asmdef b/package/Runtime/Unity.XR.ARFoundation.asmdef index 929d3a5c3..44c51b8d1 100755 --- a/package/Runtime/Unity.XR.ARFoundation.asmdef +++ b/package/Runtime/Unity.XR.ARFoundation.asmdef @@ -1,11 +1,16 @@ -{ - "name": "Unity.XR.ARFoundation", - "references": [ - "UnityEngine.SpatialTracking", - "Unity.XR.ARExtensions", - "Unity.XR.FaceSubsystem" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": true -} +{ + "name": "Unity.XR.ARFoundation", + "references": [ + "UnityEngine.SpatialTracking", + "Unity.XR.ARSubsystems" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [] +} \ No newline at end of file diff --git a/package/Runtime/Unity.XR.ARFoundation.asmdef.meta b/package/Runtime/Unity.XR.ARFoundation.asmdef.meta index aacdb0a2f..c1e2d257a 100755 --- a/package/Runtime/Unity.XR.ARFoundation.asmdef.meta +++ b/package/Runtime/Unity.XR.ARFoundation.asmdef.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: a9420e37d7990b54abdef6688edbe313 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: a9420e37d7990b54abdef6688edbe313 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Tests.meta b/package/Tests.meta index c9e308135..819abf002 100755 --- a/package/Tests.meta +++ b/package/Tests.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 0cf662c7f60ed97418aeb0531e68b75a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: bbc970fb209dd41d6970da4a87b976e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Tests/Runtime.meta b/package/Tests/Runtime.meta index bdf93a26a..b3f0625b2 100755 --- a/package/Tests/Runtime.meta +++ b/package/Tests/Runtime.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 414d8185f529b2b41a367f671d3fd406 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 554908fd6237944259cc7f3868a820ff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Tests/Runtime/ARFoundationTests.cs b/package/Tests/Runtime/ARFoundationTests.cs index 6f30c115e..f13a54c51 100755 --- a/package/Tests/Runtime/ARFoundationTests.cs +++ b/package/Tests/Runtime/ARFoundationTests.cs @@ -1,27 +1,27 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -using NUnit.Framework; - -using UnityEngine; -using UnityEngine.TestTools; -using UnityEngine.XR.ARFoundation; - -namespace UnityEngine.XR.ARFoundation -{ - [TestFixture] - public class PoseExtensionsTestFixture - { - [Test] - public void InverseTransformPositionTest() - { - Pose pose = default(Pose); - Vector3 vec = new Vector3(1,2,3); - - Assert.That(vec == pose.InverseTransformPosition(vec), "Inverse transform position not the same as input for a default pose."); - } - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +using NUnit.Framework; + +using UnityEngine; +using UnityEngine.TestTools; +using UnityEngine.XR.ARFoundation; + +namespace UnityEngine.XR.ARFoundation +{ + [TestFixture] + public class PoseExtensionsTestFixture + { + [Test] + public void InverseTransformPositionTest() + { + Pose pose = default(Pose); + Vector3 vec = new Vector3(1,2,3); + + Assert.That(vec == pose.InverseTransformPosition(vec), "Inverse transform position not the same as input for a default pose."); + } + } } \ No newline at end of file diff --git a/package/Tests/Runtime/ARFoundationTests.cs.meta b/package/Tests/Runtime/ARFoundationTests.cs.meta index fbc3774b2..578a37b10 100755 --- a/package/Tests/Runtime/ARFoundationTests.cs.meta +++ b/package/Tests/Runtime/ARFoundationTests.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 2fa37e7785fc437bb8c4cc7df1aa9e19 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 2fa37e7785fc437bb8c4cc7df1aa9e19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef b/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef index 1e379370a..dcb6ba521 100755 --- a/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef +++ b/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef @@ -1,16 +1,16 @@ -{ - "name": "Unity.XR.ARFoundation.Runtime.Tests", - "references": [ - "Unity.XR.ARFoundation" - ], - "optionalUnityReferences": [ - "TestAssemblies" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [] +{ + "name": "Unity.XR.ARFoundation.Runtime.Tests", + "references": [ + "Unity.XR.ARFoundation" + ], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] } \ No newline at end of file diff --git a/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef.meta b/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef.meta index 652ec3a6c..ac761b9a3 100755 --- a/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef.meta +++ b/package/Tests/Runtime/Unity.XR.ARFoundation.Runtime.Tests.asmdef.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 837c14ed651d4f64b6a0abb5eb836fdc -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 837c14ed651d4f64b6a0abb5eb836fdc +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/package.json b/package/package.json index 484a5628b..b2911acd6 100755 --- a/package/package.json +++ b/package/package.json @@ -1,8 +1,8 @@ { "name": "com.unity.xr.arfoundation", "displayName": "AR Foundation", - "version": "1.1.0-preview.6", - "unity": "2019.1", + "version": "2.0.1", + "unity": "2019.2", "description": "A collection of MonoBehaviours and C# utilities for working with AR Subsystems. \n\nIncludes: \n▪ GameObject menu items for creating an AR setup \n▪ MonoBehaviours that control AR session lifecycle and create GameObjects from detected, real-world trackable features \n▪ Scale handling \n▪ Face tracking", "keywords": [ "xr", @@ -16,12 +16,11 @@ ], "dependencies": { "com.unity.xr.legacyinputhelpers": "1.0.0", - "com.unity.xr.arextensions": "1.0.0-preview.7", - "com.unity.xr.facesubsystem": "1.0.0-preview.5" + "com.unity.xr.arsubsystems": "2.0.1" }, "repository": { "type": "git", - "url": "https://gitlab.cds.internal.unity3d.com/upm-packages/XR/arfoundation.git", - "revision": "07ac809e75f1b95bd63fd0b166cd822dce7a219b" + "url": "git@github.cds.internal.unity3d.com:unity/com.unity.xr.arfoundation.git", + "revision": "99f782fe02a8711eed237c9e6d2b21320ce36a69" } } diff --git a/package/package.json.meta b/package/package.json.meta index d51f1a3e6..110c505c4 100755 --- a/package/package.json.meta +++ b/package/package.json.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 08e6a1d1bc87fb6408c3e916a260691b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 08e6a1d1bc87fb6408c3e916a260691b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/versions.txt b/versions.txt index c279ee8ee..47a44bda4 100755 --- a/versions.txt +++ b/versions.txt @@ -22,3 +22,4 @@ 1.1.0-preview.3 1.1.0-preview.5 1.1.0-preview.6 +2.0.1