webXROculusTouchMotionController.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { WebXRAbstractMotionController } from "./webXRAbstractMotionController.js";
  2. import { WebXRMotionControllerManager } from "./webXRMotionControllerManager.js";
  3. import { Mesh } from "../../Meshes/mesh.js";
  4. import { Quaternion } from "../../Maths/math.vector.js";
  5. /**
  6. * The motion controller class for oculus touch (quest, rift).
  7. * This class supports legacy mapping as well the standard xr mapping
  8. */
  9. export class WebXROculusTouchMotionController extends WebXRAbstractMotionController {
  10. constructor(scene, gamepadObject, handedness, _legacyMapping = false, _forceLegacyControllers = false) {
  11. super(scene, OculusTouchLayouts[handedness], gamepadObject, handedness);
  12. this._forceLegacyControllers = _forceLegacyControllers;
  13. this.profileId = "oculus-touch";
  14. }
  15. _getFilenameAndPath() {
  16. let filename = "";
  17. if (this.handedness === "left") {
  18. filename = WebXROculusTouchMotionController.MODEL_LEFT_FILENAME;
  19. }
  20. else {
  21. // Right is the default if no hand is specified
  22. filename = WebXROculusTouchMotionController.MODEL_RIGHT_FILENAME;
  23. }
  24. const path = this._isQuest() ? WebXROculusTouchMotionController.QUEST_MODEL_BASE_URL : WebXROculusTouchMotionController.MODEL_BASE_URL;
  25. return {
  26. filename,
  27. path,
  28. };
  29. }
  30. _getModelLoadingConstraints() {
  31. return true;
  32. }
  33. _processLoadedModel(_meshes) {
  34. const isQuest = this._isQuest();
  35. const triggerDirection = this.handedness === "right" ? -1 : 1;
  36. this.getComponentIds().forEach((id) => {
  37. const comp = id && this.getComponent(id);
  38. if (comp) {
  39. comp.onButtonStateChangedObservable.add((component) => {
  40. if (!this.rootMesh || this.disableAnimation) {
  41. return;
  42. }
  43. switch (id) {
  44. case "xr-standard-trigger": // index trigger
  45. if (!isQuest) {
  46. this._modelRootNode.getChildren()[3].rotation.x = -component.value * 0.2;
  47. this._modelRootNode.getChildren()[3].position.y = -component.value * 0.005;
  48. this._modelRootNode.getChildren()[3].position.z = -component.value * 0.005;
  49. }
  50. return;
  51. case "xr-standard-squeeze": // secondary trigger
  52. if (!isQuest) {
  53. this._modelRootNode.getChildren()[4].position.x = triggerDirection * component.value * 0.0035;
  54. }
  55. return;
  56. case "xr-standard-thumbstick": // thumbstick
  57. return;
  58. case "a-button":
  59. case "x-button":
  60. if (!isQuest) {
  61. if (component.pressed) {
  62. this._modelRootNode.getChildren()[1].position.y = -0.001;
  63. }
  64. else {
  65. this._modelRootNode.getChildren()[1].position.y = 0;
  66. }
  67. }
  68. return;
  69. case "b-button":
  70. case "y-button":
  71. if (!isQuest) {
  72. if (component.pressed) {
  73. this._modelRootNode.getChildren()[2].position.y = -0.001;
  74. }
  75. else {
  76. this._modelRootNode.getChildren()[2].position.y = 0;
  77. }
  78. }
  79. return;
  80. }
  81. }, undefined, true);
  82. }
  83. });
  84. }
  85. _setRootMesh(meshes) {
  86. this.rootMesh = new Mesh(this.profileId + " " + this.handedness, this.scene);
  87. if (!this.scene.useRightHandedSystem) {
  88. this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
  89. }
  90. meshes.forEach((mesh) => {
  91. mesh.isPickable = false;
  92. });
  93. if (this._isQuest()) {
  94. this._modelRootNode = meshes[0];
  95. }
  96. else {
  97. this._modelRootNode = meshes[1];
  98. this.rootMesh.position.y = 0.034;
  99. this.rootMesh.position.z = 0.052;
  100. }
  101. this._modelRootNode.parent = this.rootMesh;
  102. }
  103. _updateModel() {
  104. // no-op. model is updated using observables.
  105. }
  106. /**
  107. * Is this the new type of oculus touch. At the moment both have the same profile and it is impossible to differentiate
  108. * between the touch and touch 2.
  109. * @returns true if this is the new type of oculus touch controllers.
  110. */
  111. _isQuest() {
  112. // this is SADLY the only way to currently check. Until proper profiles will be available.
  113. return !!navigator.userAgent.match(/Quest/gi) && !this._forceLegacyControllers;
  114. }
  115. }
  116. /**
  117. * The base url used to load the left and right controller models
  118. */
  119. WebXROculusTouchMotionController.MODEL_BASE_URL = "https://controllers.babylonjs.com/oculus/";
  120. /**
  121. * The name of the left controller model file
  122. */
  123. WebXROculusTouchMotionController.MODEL_LEFT_FILENAME = "left.babylon";
  124. /**
  125. * The name of the right controller model file
  126. */
  127. WebXROculusTouchMotionController.MODEL_RIGHT_FILENAME = "right.babylon";
  128. /**
  129. * Base Url for the Quest controller model.
  130. */
  131. WebXROculusTouchMotionController.QUEST_MODEL_BASE_URL = "https://controllers.babylonjs.com/oculusQuest/";
  132. // register the profile
  133. WebXRMotionControllerManager.RegisterController("oculus-touch", (xrInput, scene) => {
  134. return new WebXROculusTouchMotionController(scene, xrInput.gamepad, xrInput.handedness);
  135. });
  136. WebXRMotionControllerManager.RegisterController("oculus-touch-legacy", (xrInput, scene) => {
  137. return new WebXROculusTouchMotionController(scene, xrInput.gamepad, xrInput.handedness, true);
  138. });
  139. const OculusTouchLayouts = {
  140. left: {
  141. selectComponentId: "xr-standard-trigger",
  142. components: {
  143. "xr-standard-trigger": {
  144. type: "trigger",
  145. gamepadIndices: {
  146. button: 0,
  147. },
  148. rootNodeName: "xr_standard_trigger",
  149. visualResponses: {},
  150. },
  151. "xr-standard-squeeze": {
  152. type: "squeeze",
  153. gamepadIndices: {
  154. button: 1,
  155. },
  156. rootNodeName: "xr_standard_squeeze",
  157. visualResponses: {},
  158. },
  159. "xr-standard-thumbstick": {
  160. type: "thumbstick",
  161. gamepadIndices: {
  162. button: 3,
  163. xAxis: 2,
  164. yAxis: 3,
  165. },
  166. rootNodeName: "xr_standard_thumbstick",
  167. visualResponses: {},
  168. },
  169. "x-button": {
  170. type: "button",
  171. gamepadIndices: {
  172. button: 4,
  173. },
  174. rootNodeName: "x_button",
  175. visualResponses: {},
  176. },
  177. "y-button": {
  178. type: "button",
  179. gamepadIndices: {
  180. button: 5,
  181. },
  182. rootNodeName: "y_button",
  183. visualResponses: {},
  184. },
  185. thumbrest: {
  186. type: "button",
  187. gamepadIndices: {
  188. button: 6,
  189. },
  190. rootNodeName: "thumbrest",
  191. visualResponses: {},
  192. },
  193. },
  194. gamepadMapping: "xr-standard",
  195. rootNodeName: "oculus-touch-v2-left",
  196. assetPath: "left.glb",
  197. },
  198. right: {
  199. selectComponentId: "xr-standard-trigger",
  200. components: {
  201. "xr-standard-trigger": {
  202. type: "trigger",
  203. gamepadIndices: {
  204. button: 0,
  205. },
  206. rootNodeName: "xr_standard_trigger",
  207. visualResponses: {},
  208. },
  209. "xr-standard-squeeze": {
  210. type: "squeeze",
  211. gamepadIndices: {
  212. button: 1,
  213. },
  214. rootNodeName: "xr_standard_squeeze",
  215. visualResponses: {},
  216. },
  217. "xr-standard-thumbstick": {
  218. type: "thumbstick",
  219. gamepadIndices: {
  220. button: 3,
  221. xAxis: 2,
  222. yAxis: 3,
  223. },
  224. rootNodeName: "xr_standard_thumbstick",
  225. visualResponses: {},
  226. },
  227. "a-button": {
  228. type: "button",
  229. gamepadIndices: {
  230. button: 4,
  231. },
  232. rootNodeName: "a_button",
  233. visualResponses: {},
  234. },
  235. "b-button": {
  236. type: "button",
  237. gamepadIndices: {
  238. button: 5,
  239. },
  240. rootNodeName: "b_button",
  241. visualResponses: {},
  242. },
  243. thumbrest: {
  244. type: "button",
  245. gamepadIndices: {
  246. button: 6,
  247. },
  248. rootNodeName: "thumbrest",
  249. visualResponses: {},
  250. },
  251. },
  252. gamepadMapping: "xr-standard",
  253. rootNodeName: "oculus-touch-v2-right",
  254. assetPath: "right.glb",
  255. },
  256. };
  257. //# sourceMappingURL=webXROculusTouchMotionController.js.map