WebXRFeaturePointSystem.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. /**
  21. * The feature point system is used to detect feature points from real world geometry.
  22. * This feature is currently experimental and only supported on BabylonNative, and should not be used in the browser.
  23. * The newly introduced API can be seen in webxr.nativeextensions.d.ts and described in FeaturePoints.md.
  24. */
  25. export class WebXRFeaturePointSystem extends WebXRAbstractFeature {
  26. private _enabled: boolean = false;
  27. private _featurePointCloud: Array<IWebXRFeaturePoint> = [];
  28. /**
  29. * The module's name
  30. */
  31. public static readonly Name = WebXRFeatureName.FEATURE_POINTS;
  32. /**
  33. * The (Babylon) version of this module.
  34. * This is an integer representing the implementation version.
  35. * This number does not correspond to the WebXR specs version
  36. */
  37. public static readonly Version = 1;
  38. /**
  39. * Observers registered here will be executed whenever new feature points are added (on XRFrame while the session is tracking).
  40. * Will notify the observers about which feature points have been added.
  41. */
  42. public readonly onFeaturePointsAddedObservable: Observable<number[]> = new Observable();
  43. /**
  44. * Observers registered here will be executed whenever a feature point has been updated (on XRFrame while the session is tracking).
  45. * Will notify the observers about which feature points have been updated.
  46. */
  47. public readonly onFeaturePointsUpdatedObservable: Observable<number[]> = new Observable();
  48. /**
  49. * The current feature point cloud maintained across frames.
  50. */
  51. public get featurePointCloud() : Array<IWebXRFeaturePoint> {
  52. return this._featurePointCloud;
  53. }
  54. /**
  55. * construct the feature point system
  56. * @param _xrSessionManager an instance of xr Session manager
  57. */
  58. constructor(_xrSessionManager: WebXRSessionManager) {
  59. super(_xrSessionManager);
  60. this.xrNativeFeatureName = "bjsfeature-points";
  61. if (this._xrSessionManager.session) {
  62. this._init();
  63. } else {
  64. this._xrSessionManager.onXRSessionInit.addOnce(() => {
  65. this._init();
  66. });
  67. }
  68. }
  69. /**
  70. * Detach this feature.
  71. * Will usually be called by the features manager
  72. *
  73. * @returns true if successful.
  74. */
  75. public detach(): boolean {
  76. if (!super.detach()) {
  77. return false;
  78. }
  79. this.featurePointCloud.length = 0;
  80. return true;
  81. }
  82. /**
  83. * Dispose this feature and all of the resources attached
  84. */
  85. public dispose(): void {
  86. super.dispose();
  87. this._featurePointCloud.length = 0;
  88. this.onFeaturePointsUpdatedObservable.clear();
  89. this.onFeaturePointsAddedObservable.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 (!this._featurePointCloud[id]) {
  113. this._featurePointCloud[id] = { position: new Vector3(), confidenceValue: 0 };
  114. addedFeaturePoints.push(id);
  115. } else {
  116. updatedFeaturePoints.push(id);
  117. }
  118. // Set the feature point values.
  119. this._featurePointCloud[id].position.x = featurePointRawData[rawIndex];
  120. this._featurePointCloud[id].position.y = featurePointRawData[rawIndex + 1];
  121. this._featurePointCloud[id].position.z = featurePointRawData[rawIndex + 2];
  122. this._featurePointCloud[id].confidenceValue = featurePointRawData[rawIndex + 3];
  123. }
  124. // Signal observers that feature points have been added if necessary.
  125. if (addedFeaturePoints.length > 0) {
  126. this.onFeaturePointsAddedObservable.notifyObservers(addedFeaturePoints);
  127. }
  128. // Signal observers that feature points have been updated if necessary.
  129. if (updatedFeaturePoints.length > 0) {
  130. this.onFeaturePointsUpdatedObservable.notifyObservers(updatedFeaturePoints);
  131. }
  132. }
  133. }
  134. /**
  135. * Initializes the feature. If the feature point feature is not available for this environment do not mark the feature as enabled.
  136. */
  137. private _init() {
  138. if (!this._xrSessionManager.session.trySetFeaturePointCloudEnabled || !this._xrSessionManager.session.trySetFeaturePointCloudEnabled(true)) {
  139. // fail silently
  140. return;
  141. }
  142. this._enabled = true;
  143. }
  144. }
  145. // register the plugin
  146. WebXRFeaturesManager.AddWebXRFeature(
  147. WebXRFeaturePointSystem.Name,
  148. (xrSessionManager) => {
  149. return () => new WebXRFeaturePointSystem(xrSessionManager);
  150. },
  151. WebXRFeaturePointSystem.Version
  152. );