WebXRFeaturePointSystem.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 available (on XRFrame while the session is tracking).
  44. * Will notify the observers about which feature points have been updated.
  45. */
  46. public onFeaturePointsUpdatedObservable: Observable<number[]> = new Observable();
  47. /**
  48. * The currrent feature point cloud maintained across frames.
  49. */
  50. public readonly featurePointCloud: Array<IWebXRFeaturePoint> = this._featurePointCloud;
  51. /**
  52. * construct the feature point system
  53. * @param _xrSessionManager an instance of xr Session manager
  54. */
  55. constructor(_xrSessionManager: WebXRSessionManager) {
  56. super(_xrSessionManager);
  57. if (this._xrSessionManager.session) {
  58. this._init();
  59. } else {
  60. this._xrSessionManager.onXRSessionInit.addOnce(() => {
  61. this._init();
  62. });
  63. }
  64. }
  65. /**
  66. * Detach this feature.
  67. * Will usually be called by the features manager
  68. *
  69. * @returns true if successful.
  70. */
  71. public detach(): boolean {
  72. if (!super.detach()) {
  73. return false;
  74. }
  75. this.featurePointCloud.length = 0;
  76. return true;
  77. }
  78. /**
  79. * Dispose this feature and all of the resources attached
  80. */
  81. public dispose(): void {
  82. super.dispose();
  83. this._featurePointCloud.length = 0;
  84. this.onFeaturePointsUpdatedObservable.clear();
  85. }
  86. /**
  87. * On receiving a new XR frame if this feature is attached notify observers new feature point data is available.
  88. */
  89. protected _onXRFrame(frame: XRFrame) {
  90. if (!this.attached || !this._enabled || !frame) {
  91. return;
  92. }
  93. let featurePointRawData : number[] | undefined = frame.featurePointCloud;
  94. if (!featurePointRawData || featurePointRawData.length == 0) {
  95. return;
  96. } else {
  97. let numberOfFeaturePoints : number = featurePointRawData.length / 5;
  98. let updatedFeaturePoints = new Array(numberOfFeaturePoints);
  99. for (var i = 0; i < numberOfFeaturePoints; i++) {
  100. let rawIndex : number = i * 5;
  101. let id = featurePointRawData[rawIndex + 4];
  102. updatedFeaturePoints[i] = id;
  103. // IDs should be durable across frames and strictly increasing from 0 up, so use them as indexing into the feature point array.
  104. if (id == this._featurePointCloud.length) {
  105. this._featurePointCloud.push({
  106. position: new Vector3(
  107. featurePointRawData[rawIndex],
  108. featurePointRawData[rawIndex + 1],
  109. featurePointRawData[rawIndex + 2]),
  110. confidenceValue: featurePointRawData[rawIndex + 3],
  111. id: id
  112. });
  113. } else {
  114. this._featurePointCloud[id].position.x = featurePointRawData[rawIndex];
  115. this._featurePointCloud[id].position.y = featurePointRawData[rawIndex + 1];
  116. this._featurePointCloud[id].position.z = featurePointRawData[rawIndex + 2];
  117. this._featurePointCloud[id].confidenceValue = featurePointRawData[rawIndex + 3];
  118. }
  119. }
  120. // Return the list of updating feature point IDs for the current frame.
  121. this.onFeaturePointsUpdatedObservable.notifyObservers(updatedFeaturePoints);
  122. }
  123. }
  124. /**
  125. * Initializes the feature. If the feature point feature is not available for this environment do not mark the feature as enabled.
  126. */
  127. private _init() {
  128. if (!this._xrSessionManager.session.setFeaturePointCloudEnabled || !this._xrSessionManager.session.setFeaturePointCloudEnabled(true)) {
  129. // fail silently
  130. return;
  131. }
  132. this._enabled = true;
  133. }
  134. }
  135. // register the plugin
  136. WebXRFeaturesManager.AddWebXRFeature(
  137. WebXRFeaturePointSystem.Name,
  138. (xrSessionManager) => {
  139. return () => new WebXRFeaturePointSystem(xrSessionManager);
  140. },
  141. WebXRFeaturePointSystem.Version
  142. );