WebXRFeaturePointSystem.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { WebXRFeaturesManager, WebXRFeatureName } from "../webXRFeaturesManager";
  2. import { WebXRSessionManager } from "../webXRSessionManager";
  3. import { Observable } from "../../Misc/observable";
  4. import { Vector3 } from "../../Maths/math.vector";
  5. import { WebXRAbstractFeature } from "./WebXRAbstractFeature";
  6. /**
  7. * A babylon interface for a "WebXR" feature point.
  8. * Represents the position and confidence value of a given feature point.
  9. */
  10. export interface IWebXRFeaturePoint {
  11. /**
  12. * Represents the position of the feature point in world space.
  13. */
  14. position : Vector3;
  15. /**
  16. * Represents the confidence value of the feature point in world space. 0 being least confident, and 1 being most confident.
  17. */
  18. confidenceValue : number;
  19. /**
  20. * The ID of the feature point, stable across frames.
  21. */
  22. id : number;
  23. }
  24. /**
  25. * The feature point system is used to detect feature points from real world geometry.
  26. * This feature is currently experimental and only supported on BabylonNative, and should not be used in the browser.
  27. * The newly introduced API can be seen in webxr.nativeextensions.d.ts and described in FeaturePoints.md.
  28. */
  29. export class WebXRFeaturePointSystem extends WebXRAbstractFeature {
  30. private _enabled: boolean = false;
  31. private _featurePointCloud: Array<IWebXRFeaturePoint> = [];
  32. /**
  33. * The module's name
  34. */
  35. public static readonly Name = WebXRFeatureName.FEATURE_POINTS;
  36. /**
  37. * The (Babylon) version of this module.
  38. * This is an integer representing the implementation version.
  39. * This number does not correspond to the WebXR specs version
  40. */
  41. public static readonly Version = 1;
  42. /**
  43. * Observers registered here will be executed whenever new feature points are added (on XRFrame while the session is tracking).
  44. * Will notify the observers about which feature points have been added.
  45. */
  46. public readonly onFeaturePointsAddedObservable: Observable<number[]> = new Observable();
  47. /**
  48. * Observers registered here will be executed whenever a feature point has been updated (on XRFrame while the session is tracking).
  49. * Will notify the observers about which feature points have been updated.
  50. */
  51. public readonly onFeaturePointsUpdatedObservable: Observable<number[]> = new Observable();
  52. /**
  53. * The currrent feature point cloud maintained across frames.
  54. */
  55. public readonly featurePointCloud: Array<IWebXRFeaturePoint> = this._featurePointCloud;
  56. /**
  57. * construct the feature point system
  58. * @param _xrSessionManager an instance of xr Session manager
  59. */
  60. constructor(_xrSessionManager: WebXRSessionManager) {
  61. super(_xrSessionManager);
  62. if (this._xrSessionManager.session) {
  63. this._init();
  64. } else {
  65. this._xrSessionManager.onXRSessionInit.addOnce(() => {
  66. this._init();
  67. });
  68. }
  69. }
  70. /**
  71. * Detach this feature.
  72. * Will usually be called by the features manager
  73. *
  74. * @returns true if successful.
  75. */
  76. public detach(): boolean {
  77. if (!super.detach()) {
  78. return false;
  79. }
  80. this.featurePointCloud.length = 0;
  81. return true;
  82. }
  83. /**
  84. * Dispose this feature and all of the resources attached
  85. */
  86. public dispose(): void {
  87. super.dispose();
  88. this._featurePointCloud.length = 0;
  89. this.onFeaturePointsUpdatedObservable.clear();
  90. }
  91. /**
  92. * On receiving a new XR frame if this feature is attached notify observers new feature point data is available.
  93. */
  94. protected _onXRFrame(frame: XRFrame) {
  95. if (!this.attached || !this._enabled || !frame) {
  96. return;
  97. }
  98. const featurePointRawData: number[] | undefined = frame.featurePointCloud;
  99. if (!featurePointRawData || featurePointRawData.length == 0) {
  100. return;
  101. } else {
  102. if (featurePointRawData.length % 5 != 0) {
  103. throw new Error("Received malformed feature point cloud of length: " + featurePointRawData.length);
  104. }
  105. const numberOfFeaturePoints : number = featurePointRawData.length / 5;
  106. let updatedFeaturePoints = new Array();
  107. let addedFeaturePoints = new Array();
  108. for (var i = 0; i < numberOfFeaturePoints; i++) {
  109. const rawIndex: number = i * 5;
  110. const id = featurePointRawData[rawIndex + 4];
  111. // IDs should be durable across frames and strictly increasing from 0 up, so use them as indexing into the feature point array.
  112. if (id == this._featurePointCloud.length) {
  113. this._featurePointCloud.push({
  114. position: new Vector3(
  115. featurePointRawData[rawIndex],
  116. featurePointRawData[rawIndex + 1],
  117. featurePointRawData[rawIndex + 2]),
  118. confidenceValue: featurePointRawData[rawIndex + 3],
  119. id: id
  120. });
  121. addedFeaturePoints.push(id);
  122. } else {
  123. this._featurePointCloud[id].position.x = featurePointRawData[rawIndex];
  124. this._featurePointCloud[id].position.y = featurePointRawData[rawIndex + 1];
  125. this._featurePointCloud[id].position.z = featurePointRawData[rawIndex + 2];
  126. this._featurePointCloud[id].confidenceValue = featurePointRawData[rawIndex + 3];
  127. updatedFeaturePoints.push(id);
  128. }
  129. }
  130. // Signal observers that feature points have been added if necessary.
  131. if (addedFeaturePoints.length > 0) {
  132. this.onFeaturePointsAddedObservable.notifyObservers(addedFeaturePoints);
  133. }
  134. // Signal observers that feature points have been updated if necessary.
  135. if (updatedFeaturePoints.length > 0) {
  136. this.onFeaturePointsUpdatedObservable.notifyObservers(updatedFeaturePoints);
  137. }
  138. }
  139. }
  140. /**
  141. * Initializes the feature. If the feature point feature is not available for this environment do not mark the feature as enabled.
  142. */
  143. private _init() {
  144. if (!this._xrSessionManager.session.setFeaturePointCloudEnabled || !this._xrSessionManager.session.setFeaturePointCloudEnabled(true)) {
  145. // fail silently
  146. return;
  147. }
  148. this._enabled = true;
  149. }
  150. }
  151. // register the plugin
  152. WebXRFeaturesManager.AddWebXRFeature(
  153. WebXRFeaturePointSystem.Name,
  154. (xrSessionManager) => {
  155. return () => new WebXRFeaturePointSystem(xrSessionManager);
  156. },
  157. WebXRFeaturePointSystem.Version
  158. );