babylon.poseEnabledController.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. module BABYLON {
  2. export enum PoseEnabledControllerType {
  3. VIVE,
  4. OCULUS,
  5. WINDOWS,
  6. GENERIC
  7. }
  8. export interface MutableGamepadButton {
  9. value: number;
  10. touched: boolean;
  11. pressed: boolean;
  12. }
  13. export interface ExtendedGamepadButton extends GamepadButton {
  14. readonly pressed: boolean;
  15. readonly touched: boolean;
  16. readonly value: number;
  17. }
  18. export class PoseEnabledControllerHelper {
  19. public static InitiateController(vrGamepad: any) {
  20. // Oculus Touch
  21. if (vrGamepad.id.indexOf('Oculus Touch') !== -1) {
  22. return new OculusTouchController(vrGamepad);
  23. }
  24. // Windows Mixed Reality controllers
  25. else if (vrGamepad.id.indexOf(WindowsMotionController.GAMEPAD_ID_PREFIX) === 0) {
  26. return new WindowsMotionController(vrGamepad);
  27. }
  28. // HTC Vive
  29. else if (vrGamepad.id.toLowerCase().indexOf('openvr') !== -1) {
  30. return new ViveController(vrGamepad);
  31. }
  32. // Generic
  33. else {
  34. return new GenericController(vrGamepad);
  35. }
  36. }
  37. }
  38. export class PoseEnabledController extends Gamepad implements PoseControlled {
  39. // Represents device position and rotation in room space. Should only be used to help calculate babylon space values
  40. private _deviceRoomPosition = Vector3.Zero();
  41. private _deviceRoomRotationQuaternion = new Quaternion();
  42. // Represents device position and rotation in babylon space
  43. public devicePosition = Vector3.Zero();
  44. public deviceRotationQuaternion = new Quaternion();
  45. deviceScaleFactor: number = 1;
  46. public position: Vector3;
  47. public rotationQuaternion: Quaternion;
  48. public controllerType: PoseEnabledControllerType;
  49. private _calculatedPosition: Vector3;
  50. private _calculatedRotation: Quaternion;
  51. public rawPose: DevicePose; //GamepadPose;
  52. public _mesh: Nullable<AbstractMesh>; // a node that will be attached to this Gamepad
  53. private _poseControlledCamera: TargetCamera;
  54. private _leftHandSystemQuaternion: Quaternion = new Quaternion();
  55. public _deviceToWorld = Matrix.Identity();
  56. constructor(browserGamepad: any) {
  57. super(browserGamepad.id, browserGamepad.index, browserGamepad);
  58. this.type = Gamepad.POSE_ENABLED;
  59. this.controllerType = PoseEnabledControllerType.GENERIC;
  60. this.position = Vector3.Zero();
  61. this.rotationQuaternion = new Quaternion();
  62. this._calculatedPosition = Vector3.Zero();
  63. this._calculatedRotation = new Quaternion();
  64. Quaternion.RotationYawPitchRollToRef(Math.PI, 0, 0, this._leftHandSystemQuaternion);
  65. }
  66. private _workingMatrix = Matrix.Identity();
  67. public update() {
  68. super.update();
  69. var pose: GamepadPose = this.browserGamepad.pose;
  70. this.updateFromDevice(pose);
  71. Vector3.TransformCoordinatesToRef(this._calculatedPosition, this._deviceToWorld, this.devicePosition)
  72. this._deviceToWorld.getRotationMatrixToRef(this._workingMatrix);
  73. Quaternion.FromRotationMatrixToRef(this._workingMatrix, this.deviceRotationQuaternion);
  74. if (this._mesh) {
  75. this._mesh.position.copyFrom(this.devicePosition);
  76. if (this._mesh.rotationQuaternion) {
  77. this._mesh.rotationQuaternion.copyFrom(this.deviceRotationQuaternion.multiplyInPlace(this._calculatedRotation));
  78. }
  79. }
  80. }
  81. updateFromDevice(poseData: DevicePose) {
  82. if (poseData) {
  83. this.rawPose = poseData;
  84. if (poseData.position) {
  85. this._deviceRoomPosition.copyFromFloats(poseData.position[0], poseData.position[1], -poseData.position[2]);
  86. if (this._mesh && this._mesh.getScene().useRightHandedSystem) {
  87. this._deviceRoomPosition.z *= -1;
  88. }
  89. this._deviceRoomPosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
  90. this._calculatedPosition.addInPlace(this.position);
  91. }
  92. let pose = this.rawPose;
  93. if (poseData.orientation && pose.orientation) {
  94. this._deviceRoomRotationQuaternion.copyFromFloats(pose.orientation[0], pose.orientation[1], -pose.orientation[2], -pose.orientation[3]);
  95. if (this._mesh) {
  96. if (this._mesh.getScene().useRightHandedSystem) {
  97. this._deviceRoomRotationQuaternion.z *= -1;
  98. this._deviceRoomRotationQuaternion.w *= -1;
  99. } else {
  100. this._deviceRoomRotationQuaternion.multiplyToRef(this._leftHandSystemQuaternion, this._deviceRoomRotationQuaternion);
  101. }
  102. }
  103. // if the camera is set, rotate to the camera's rotation
  104. this._deviceRoomRotationQuaternion.multiplyToRef(this.rotationQuaternion, this._calculatedRotation);
  105. }
  106. }
  107. }
  108. public attachToMesh(mesh: AbstractMesh) {
  109. if (this._mesh) {
  110. this._mesh.parent = null;
  111. }
  112. this._mesh = mesh;
  113. if (this._poseControlledCamera) {
  114. this._mesh.parent = this._poseControlledCamera;
  115. }
  116. if (!this._mesh.rotationQuaternion) {
  117. this._mesh.rotationQuaternion = new Quaternion();
  118. }
  119. }
  120. public attachToPoseControlledCamera(camera: TargetCamera) {
  121. this._poseControlledCamera = camera;
  122. if (this._mesh) {
  123. this._mesh.parent = this._poseControlledCamera;
  124. }
  125. }
  126. public dispose() {
  127. if (this._mesh) {
  128. this._mesh.dispose();
  129. }
  130. this._mesh = null;
  131. super.dispose();
  132. }
  133. public get mesh(): Nullable<AbstractMesh> {
  134. return this._mesh;
  135. }
  136. public getForwardRay(length = 100): Ray {
  137. if (!this.mesh) {
  138. return new Ray(Vector3.Zero(), new BABYLON.Vector3(0, 0, 1), length);
  139. }
  140. var m = this.mesh.getWorldMatrix();
  141. var origin = m.getTranslation();
  142. var forward = new BABYLON.Vector3(0, 0, -1);
  143. var forwardWorld = BABYLON.Vector3.TransformNormal(forward, m);
  144. var direction = BABYLON.Vector3.Normalize(forwardWorld);
  145. return new Ray(origin, direction, length);
  146. }
  147. }
  148. }