How to use _getMojoFromViewerWithOffset method in wpt

Best JavaScript code snippet using wpt

webxr-test.js

Source:webxr-test.js Github

copy

Full Screen

...630 downDegrees: 50.099,631 leftDegrees: 50.899,632 rightDegrees: 35.197633 },634 mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({635 position: [-0.032, 0, 0],636 orientation: [0, 0, 0, 1]637 })),638 viewport: { x: 0, y: 0, width: viewport_size, height: viewport_size }639 },640 {641 eye: vrMojom.XREye.kRight,642 fieldOfView: {643 upDegrees: 48.316,644 downDegrees: 50.099,645 leftDegrees: 50.899,646 rightDegrees: 35.197647 },648 mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({649 position: [0.032, 0, 0],650 orientation: [0, 0, 0, 1]651 })),652 viewport: { x: viewport_size, y: 0, width: viewport_size, height: viewport_size }653 }]654 };655 }656 // This function converts between the matrix provided by the WebXR test API657 // and the internal data representation.658 _getView(fakeXRViewInit, xOffset) {659 let fov = null;660 if (fakeXRViewInit.fieldOfView) {661 fov = {662 upDegrees: fakeXRViewInit.fieldOfView.upDegrees,663 downDegrees: fakeXRViewInit.fieldOfView.downDegrees,664 leftDegrees: fakeXRViewInit.fieldOfView.leftDegrees,665 rightDegrees: fakeXRViewInit.fieldOfView.rightDegrees666 };667 } else {668 const m = fakeXRViewInit.projectionMatrix;669 function toDegrees(tan) {670 return Math.atan(tan) * 180 / Math.PI;671 }672 const leftTan = (1 - m[8]) / m[0];673 const rightTan = (1 + m[8]) / m[0];674 const upTan = (1 + m[9]) / m[5];675 const downTan = (1 - m[9]) / m[5];676 fov = {677 upDegrees: toDegrees(upTan),678 downDegrees: toDegrees(downTan),679 leftDegrees: toDegrees(leftTan),680 rightDegrees: toDegrees(rightTan)681 };682 }683 let viewEye = vrMojom.XREye.kNone;684 // The eye passed in corresponds to the values in the WebXR spec, which are685 // the strings "none", "left", and "right". They should be converted to the686 // corresponding values of XREye in vr_service.mojom.687 switch(fakeXRViewInit.eye) {688 case "none":689 viewEye = vrMojom.XREye.kNone;690 break;691 case "left":692 viewEye = vrMojom.XREye.kLeft;693 break;694 case "right":695 viewEye = vrMojom.XREye.kRight;696 break;697 }698 return {699 eye: viewEye,700 fieldOfView: fov,701 mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform(fakeXRViewInit.viewOffset)),702 viewport: {703 x: xOffset,704 y: 0,705 width: fakeXRViewInit.resolution.width,706 height: fakeXRViewInit.resolution.height707 },708 isFirstPersonObserver: fakeXRViewInit.isFirstPersonObserver ? true : false,709 viewOffset: composeGFXTransform(fakeXRViewInit.viewOffset)710 };711 }712 _setFeatures(supportedFeatures) {713 function convertFeatureToMojom(feature) {714 if (feature in MockRuntime._featureToMojoMap) {715 return MockRuntime._featureToMojoMap[feature];716 } else {717 return vrMojom.XRSessionFeature.INVALID;718 }719 }720 this.supportedFeatures_ = [];721 for (let i = 0; i < supportedFeatures.length; i++) {722 const feature = convertFeatureToMojom(supportedFeatures[i]);723 if (feature !== vrMojom.XRSessionFeature.INVALID) {724 this.supportedFeatures_.push(feature);725 }726 }727 }728 // These methods are intended to be used by MockXRInputSource only.729 _addInputSource(source) {730 if (!this.input_sources_.has(source.source_id_)) {731 this.input_sources_.set(source.source_id_, source);732 }733 }734 _removeInputSource(source) {735 this.input_sources_.delete(source.source_id_);736 }737 // These methods are intended to be used by FakeXRAnchorController only.738 _deleteAnchorController(controllerId) {739 this.anchor_controllers_.delete(controllerId);740 }741 // Extension point for non-standard modules.742 _injectAdditionalFrameData(options, frameData) {743 }744 // Mojo function implementations.745 // XRFrameDataProvider implementation.746 getFrameData(options) {747 return new Promise((resolve) => {748 const populatePose = () => {749 const mojo_space_reset = this.send_mojo_space_reset_;750 this.send_mojo_space_reset_ = false;751 if (this.pose_) {752 this.pose_.poseIndex++;753 }754 // Setting the input_state to null tests a slightly different path than755 // the browser tests where if the last input source is removed, the device756 // code always sends up an empty array, but it's also valid mojom to send757 // up a null array.758 let input_state = null;759 if (this.input_sources_.size > 0) {760 input_state = [];761 for (const input_source of this.input_sources_.values()) {762 input_state.push(input_source._getInputSourceState());763 }764 }765 let frame_views = this.primaryViews_;766 for (let i = 0; i < this.primaryViews_.length; i++) {767 this.primaryViews_[i].mojoFromView =768 this._getMojoFromViewerWithOffset(this.primaryViews_[i].viewOffset);769 }770 if (this.enabledFeatures_.includes(vrMojom.XRSessionFeature.SECONDARY_VIEWS)) {771 for (let i = 0; i < this.secondaryViews_.length; i++) {772 this.secondaryViews_[i].mojoFromView =773 this._getMojoFromViewerWithOffset(this.secondaryViews_[i].viewOffset);774 }775 frame_views = frame_views.concat(this.secondaryViews_);776 }777 const frameData = {778 mojoFromViewer: this.pose_,779 views: frame_views,780 mojoSpaceReset: mojo_space_reset,781 inputState: input_state,782 timeDelta: {783 // window.performance.now() is in milliseconds, so convert to microseconds.784 microseconds: BigInt(Math.floor(window.performance.now() * 1000)),785 },786 frameId: this.next_frame_id_,787 bufferHolder: null,788 bufferSize: {},789 renderingTimeRatio: 0,790 stageParameters: this.stageParameters_,791 stageParametersId: this.stageParametersId_,792 lightEstimationData: this.light_estimate_793 };794 this.next_frame_id_++;795 this._calculateHitTestResults(frameData);796 this._calculateAnchorInformation(frameData);797 this._calculateDepthInformation(frameData);798 this._injectAdditionalFrameData(options, frameData);799 resolve({frameData});800 };801 if(this.sessionOptions_.mode == vrMojom.XRSessionMode.kInline) {802 // Inline sessions should not have a delay introduced since it causes them803 // to miss a vsync blink-side and delays propagation of changes that happened804 // within a rAFcb by one frame (e.g. setViewerOrigin() calls would take 2 frames805 // to propagate).806 populatePose();807 } else {808 // For immerive sessions, add additional delay to allow for anchor creation809 // promises to run.810 setTimeout(populatePose, 3); // note: according to MDN, the timeout is not exact811 }812 });813 }814 getEnvironmentIntegrationProvider(environmentProviderRequest) {815 if (this.environmentProviderReceiver_) {816 this.environmentProviderReceiver_.$.close();817 }818 this.environmentProviderReceiver_ =819 new vrMojom.XREnvironmentIntegrationProviderReceiver(this);820 this.environmentProviderReceiver_.$.bindHandle(821 environmentProviderRequest.handle);822 }823 setInputSourceButtonListener(listener) { listener.$.close(); }824 // XREnvironmentIntegrationProvider implementation:825 subscribeToHitTest(nativeOriginInformation, entityTypes, ray) {826 if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {827 // Reject outside of AR.828 return Promise.resolve({829 result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,830 subscriptionId : 0n831 });832 }833 if (!this._nativeOriginKnown(nativeOriginInformation)) {834 return Promise.resolve({835 result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,836 subscriptionId : 0n837 });838 }839 // Reserve the id for hit test source:840 const id = this.next_hit_test_id_++;841 const hitTestParameters = { isTransient: false, profileName: null };842 const controller = new FakeXRHitTestSourceController(id);843 return this._shouldHitTestSourceCreationSucceed(hitTestParameters, controller)844 .then((succeeded) => {845 if(succeeded) {846 // Store the subscription information as-is (including controller):847 this.hitTestSubscriptions_.set(id, { nativeOriginInformation, entityTypes, ray, controller });848 return Promise.resolve({849 result : vrMojom.SubscribeToHitTestResult.SUCCESS,850 subscriptionId : id851 });852 } else {853 return Promise.resolve({854 result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,855 subscriptionId : 0n856 });857 }858 });859 }860 subscribeToHitTestForTransientInput(profileName, entityTypes, ray){861 if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {862 // Reject outside of AR.863 return Promise.resolve({864 result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,865 subscriptionId : 0n866 });867 }868 const id = this.next_hit_test_id_++;869 const hitTestParameters = { isTransient: true, profileName: profileName };870 const controller = new FakeXRHitTestSourceController(id);871 // Check if we have hit test source creation callback.872 // If yes, ask it if the hit test source creation should succeed.873 // If no, for back-compat, assume the hit test source creation succeeded.874 return this._shouldHitTestSourceCreationSucceed(hitTestParameters, controller)875 .then((succeeded) => {876 if(succeeded) {877 // Store the subscription information as-is (including controller):878 this.transientHitTestSubscriptions_.set(id, { profileName, entityTypes, ray, controller });879 return Promise.resolve({880 result : vrMojom.SubscribeToHitTestResult.SUCCESS,881 subscriptionId : id882 });883 } else {884 return Promise.resolve({885 result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,886 subscriptionId : 0n887 });888 }889 });890 }891 unsubscribeFromHitTest(subscriptionId) {892 let controller = null;893 if(this.transientHitTestSubscriptions_.has(subscriptionId)){894 controller = this.transientHitTestSubscriptions_.get(subscriptionId).controller;895 this.transientHitTestSubscriptions_.delete(subscriptionId);896 } else if(this.hitTestSubscriptions_.has(subscriptionId)){897 controller = this.hitTestSubscriptions_.get(subscriptionId).controller;898 this.hitTestSubscriptions_.delete(subscriptionId);899 }900 if(controller) {901 controller.deleted = true;902 }903 }904 createAnchor(nativeOriginInformation, nativeOriginFromAnchor) {905 return new Promise((resolve) => {906 if(this.anchor_creation_callback_ == null) {907 resolve({908 result : vrMojom.CreateAnchorResult.FAILURE,909 anchorId : 0n910 });911 return;912 }913 const mojoFromNativeOrigin = this._getMojoFromNativeOrigin(nativeOriginInformation);914 if(mojoFromNativeOrigin == null) {915 resolve({916 result : vrMojom.CreateAnchorResult.FAILURE,917 anchorId : 0n918 });919 return;920 }921 const mojoFromAnchor = XRMathHelper.mul4x4(mojoFromNativeOrigin, nativeOriginFromAnchor);922 const anchorCreationParameters = {923 requestedAnchorOrigin: mojoFromAnchor,924 isAttachedToEntity: false,925 };926 const anchorController = new FakeXRAnchorController();927 this.anchor_creation_callback_(anchorCreationParameters, anchorController)928 .then((result) => {929 if(result) {930 // If the test allowed the anchor creation,931 // store the anchor controller & return success.932 const anchor_id = this.next_anchor_id_;933 this.next_anchor_id_++;934 this.anchor_controllers_.set(anchor_id, anchorController);935 anchorController.device = this;936 anchorController.id = anchor_id;937 resolve({938 result : vrMojom.CreateAnchorResult.SUCCESS,939 anchorId : anchor_id940 });941 } else {942 // The test has rejected anchor creation.943 resolve({944 result : vrMojom.CreateAnchorResult.FAILURE,945 anchorId : 0n946 });947 }948 })949 .catch(() => {950 // The test threw an error, treat anchor creation as failed.951 resolve({952 result : vrMojom.CreateAnchorResult.FAILURE,953 anchorId : 0n954 });955 });956 });957 }958 createPlaneAnchor(planeFromAnchor, planeId) {959 return new Promise((resolve) => {960 // Not supported yet.961 resolve({962 result : vrMojom.CreateAnchorResult.FAILURE,963 anchorId : 0n,964 });965 });966 }967 detachAnchor(anchorId) {}968 // Utility function969 _requestRuntimeSession(sessionOptions) {970 return this._runtimeSupportsSession(sessionOptions).then((result) => {971 // The JavaScript bindings convert c_style_names to camelCase names.972 const options = {973 transportMethod:974 vrMojom.XRPresentationTransportMethod.SUBMIT_AS_MAILBOX_HOLDER,975 waitForTransferNotification: true,976 waitForRenderNotification: true,977 waitForGpuFence: false,978 };979 let submit_frame_sink;980 if (result.supportsSession) {981 submit_frame_sink = {982 clientReceiver: this.presentation_provider_._getClientReceiver(),983 provider: this.presentation_provider_._bindProvider(sessionOptions),984 transportOptions: options985 };986 const dataProviderPtr = new vrMojom.XRFrameDataProviderRemote();987 this.dataProviderReceiver_ =988 new vrMojom.XRFrameDataProviderReceiver(this);989 this.dataProviderReceiver_.$.bindHandle(990 dataProviderPtr.$.bindNewPipeAndPassReceiver().handle);991 this.sessionOptions_ = sessionOptions;992 this.sessionClient_ = new vrMojom.XRSessionClientRemote();993 const clientReceiver = this.sessionClient_.$.bindNewPipeAndPassReceiver();994 const enabled_features = [];995 for (let i = 0; i < sessionOptions.requiredFeatures.length; i++) {996 if (this.supportedFeatures_.indexOf(sessionOptions.requiredFeatures[i]) !== -1) {997 enabled_features.push(sessionOptions.requiredFeatures[i]);998 } else {999 return Promise.resolve({session: null});1000 }1001 }1002 for (let i =0; i < sessionOptions.optionalFeatures.length; i++) {1003 if (this.supportedFeatures_.indexOf(sessionOptions.optionalFeatures[i]) !== -1) {1004 enabled_features.push(sessionOptions.optionalFeatures[i]);1005 }1006 }1007 this.enabledFeatures_ = enabled_features;1008 return Promise.resolve({1009 session: {1010 submitFrameSink: submit_frame_sink,1011 dataProvider: dataProviderPtr,1012 clientReceiver: clientReceiver,1013 displayInfo: this.displayInfo_,1014 enabledFeatures: enabled_features,1015 deviceConfig: {1016 usesInputEventing: false,1017 defaultFramebufferScale: this.defaultFramebufferScale_,1018 supportsViewportScaling: true,1019 depthConfiguration:1020 enabled_features.includes(vrMojom.XRSessionFeature.DEPTH) ? {1021 depthUsage: vrMojom.XRDepthUsage.kCPUOptimized,1022 depthDataFormat: vrMojom.XRDepthDataFormat.kLuminanceAlpha,1023 } : null,1024 },1025 enviromentBlendMode: this.enviromentBlendMode_,1026 interactionMode: this.interactionMode_1027 }1028 });1029 } else {1030 return Promise.resolve({session: null});1031 }1032 });1033 }1034 _runtimeSupportsSession(options) {1035 let result = this.supportedModes_.includes(options.mode);1036 if (options.requiredFeatures.includes(vrMojom.XRSessionFeature.DEPTH)1037 || options.optionalFeatures.includes(vrMojom.XRSessionFeature.DEPTH)) {1038 result &= options.depthOptions.usagePreferences.includes(vrMojom.XRDepthUsage.kCPUOptimized);1039 result &= options.depthOptions.dataFormatPreferences.includes(vrMojom.XRDepthDataFormat.kLuminanceAlpha);1040 }1041 return Promise.resolve({1042 supportsSession: result,1043 });1044 }1045 // Private functions - utilities:1046 _nativeOriginKnown(nativeOriginInformation){1047 if (nativeOriginInformation.inputSourceSpaceInfo !== undefined) {1048 if (!this.input_sources_.has(nativeOriginInformation.inputSourceSpaceInfo.inputSourceId)) {1049 // Unknown input source.1050 return false;1051 }1052 return true;1053 } else if (nativeOriginInformation.referenceSpaceType !== undefined) {1054 // Bounded_floor & unbounded ref spaces are not yet supported for AR:1055 if (nativeOriginInformation.referenceSpaceType == vrMojom.XRReferenceSpaceType.kUnbounded1056 || nativeOriginInformation.referenceSpaceType == vrMojom.XRReferenceSpaceType.kBoundedFloor) {1057 return false;1058 }1059 return true;1060 } else {1061 // Planes and anchors are not yet supported by the mock interface.1062 return false;1063 }1064 }1065 // Private functions - anchors implementation:1066 // Modifies passed in frameData to add anchor information.1067 _calculateAnchorInformation(frameData) {1068 if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {1069 return;1070 }1071 frameData.anchorsData = {allAnchorsIds: [], updatedAnchorsData: []};1072 for(const [id, controller] of this.anchor_controllers_) {1073 frameData.anchorsData.allAnchorsIds.push(id);1074 // Send the entire anchor data over if there was a change since last GetFrameData().1075 if(controller.dirty) {1076 const anchorData = {id};1077 if(!controller.paused) {1078 anchorData.mojoFromAnchor = getPoseFromTransform(1079 XRMathHelper.decomposeRigidTransform(1080 controller._getAnchorOrigin()));1081 }1082 controller._markProcessed();1083 frameData.anchorsData.updatedAnchorsData.push(anchorData);1084 }1085 }1086 }1087 // Private functions - depth sensing implementation:1088 // Modifies passed in frameData to add anchor information.1089 _calculateDepthInformation(frameData) {1090 if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {1091 return;1092 }1093 if (!this.enabledFeatures_.includes(vrMojom.XRSessionFeature.DEPTH)) {1094 return;1095 }1096 // If we don't have a current depth data, we'll return null1097 // (i.e. no data is not a valid data, so it cannot be "StillValid").1098 if (this.depthSensingData_ == null) {1099 frameData.depthData = null;1100 return;1101 }1102 if(!this.depthSensingDataDirty_) {1103 frameData.depthData = { dataStillValid: {}};1104 return;1105 }1106 frameData.depthData = {1107 updatedDepthData: {1108 timeDelta: frameData.timeDelta,1109 normTextureFromNormView: this.depthSensingData_.normDepthBufferFromNormView,1110 rawValueToMeters: this.depthSensingData_.rawValueToMeters,1111 size: { width: this.depthSensingData_.width, height: this.depthSensingData_.height },1112 pixelData: { bytes: this.depthSensingData_.depthData }1113 }1114 };1115 this.depthSensingDataDirty_ = false;1116 }1117 // Private functions - hit test implementation:1118 // Returns a Promise<bool> that signifies whether hit test source creation should succeed.1119 // If we have a hit test source creation callback installed, invoke it and return its result.1120 // If it's not installed, for back-compat just return a promise that resolves to true.1121 _shouldHitTestSourceCreationSucceed(hitTestParameters, controller) {1122 if(this.hit_test_source_creation_callback_) {1123 return this.hit_test_source_creation_callback_(hitTestParameters, controller);1124 } else {1125 return Promise.resolve(true);1126 }1127 }1128 // Modifies passed in frameData to add hit test results.1129 _calculateHitTestResults(frameData) {1130 if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {1131 return;1132 }1133 frameData.hitTestSubscriptionResults = {results: [],1134 transientInputResults: []};1135 if (!this.world_) {1136 return;1137 }1138 // Non-transient hit test:1139 for (const [id, subscription] of this.hitTestSubscriptions_) {1140 const mojo_from_native_origin = this._getMojoFromNativeOrigin(subscription.nativeOriginInformation);1141 if (!mojo_from_native_origin) continue;1142 const [mojo_ray_origin, mojo_ray_direction] = this._transformRayToMojoSpace(1143 subscription.ray,1144 mojo_from_native_origin1145 );1146 const results = this._hitTestWorld(mojo_ray_origin, mojo_ray_direction, subscription.entityTypes);1147 frameData.hitTestSubscriptionResults.results.push(1148 {subscriptionId: id, hitTestResults: results});1149 }1150 // Transient hit test:1151 const mojo_from_viewer = this._getMojoFromViewer();1152 for (const [id, subscription] of this.transientHitTestSubscriptions_) {1153 const result = {subscriptionId: id,1154 inputSourceIdToHitTestResults: new Map()};1155 // Find all input sources that match the profile name:1156 const matching_input_sources = Array.from(this.input_sources_.values())1157 .filter(input_source => input_source.profiles_.includes(subscription.profileName));1158 for (const input_source of matching_input_sources) {1159 const mojo_from_native_origin = input_source._getMojoFromInputSource(mojo_from_viewer);1160 const [mojo_ray_origin, mojo_ray_direction] = this._transformRayToMojoSpace(1161 subscription.ray,1162 mojo_from_native_origin1163 );1164 const results = this._hitTestWorld(mojo_ray_origin, mojo_ray_direction, subscription.entityTypes);1165 result.inputSourceIdToHitTestResults.set(input_source.source_id_, results);1166 }1167 frameData.hitTestSubscriptionResults.transientInputResults.push(result);1168 }1169 }1170 // Returns 2-element array [origin, direction] of a ray in mojo space.1171 // |ray| is expressed relative to native origin.1172 _transformRayToMojoSpace(ray, mojo_from_native_origin) {1173 const ray_origin = {1174 x: ray.origin.x,1175 y: ray.origin.y,1176 z: ray.origin.z,1177 w: 11178 };1179 const ray_direction = {1180 x: ray.direction.x,1181 y: ray.direction.y,1182 z: ray.direction.z,1183 w: 01184 };1185 const mojo_ray_origin = XRMathHelper.transform_by_matrix(1186 mojo_from_native_origin,1187 ray_origin);1188 const mojo_ray_direction = XRMathHelper.transform_by_matrix(1189 mojo_from_native_origin,1190 ray_direction);1191 return [mojo_ray_origin, mojo_ray_direction];1192 }1193 // Hit tests the passed in ray (expressed as origin and direction) against the mocked world data.1194 _hitTestWorld(origin, direction, entityTypes) {1195 let result = [];1196 for (const region of this.world_.hitTestRegions) {1197 const partial_result = this._hitTestRegion(1198 region,1199 origin, direction,1200 entityTypes);1201 result = result.concat(partial_result);1202 }1203 return result.sort((lhs, rhs) => lhs.distance - rhs.distance).map((hitTest) => {1204 delete hitTest.distance;1205 return hitTest;1206 });1207 }1208 // Hit tests the passed in ray (expressed as origin and direction) against world region.1209 // |entityTypes| is a set of FakeXRRegionTypes.1210 // |region| is FakeXRRegion.1211 // Returns array of XRHitResults, each entry will be decorated with the distance from the ray origin (along the ray).1212 _hitTestRegion(region, origin, direction, entityTypes) {1213 const regionNameToMojoEnum = {1214 "point": vrMojom.EntityTypeForHitTest.POINT,1215 "plane": vrMojom.EntityTypeForHitTest.PLANE,1216 "mesh":null1217 };1218 if (!entityTypes.includes(regionNameToMojoEnum[region.type])) {1219 return [];1220 }1221 const result = [];1222 for (const face of region.faces) {1223 const maybe_hit = this._hitTestFace(face, origin, direction);1224 if (maybe_hit) {1225 result.push(maybe_hit);1226 }1227 }1228 // The results should be sorted by distance and there should be no 2 entries with1229 // the same distance from ray origin - that would mean they are the same point.1230 // This situation is possible when a ray intersects the region through an edge shared1231 // by 2 faces.1232 return result.sort((lhs, rhs) => lhs.distance - rhs.distance)1233 .filter((val, index, array) => index === 0 || val.distance !== array[index - 1].distance);1234 }1235 // Hit tests the passed in ray (expressed as origin and direction) against a single face.1236 // |face|, |origin|, and |direction| are specified in world (aka mojo) coordinates.1237 // |face| is an array of DOMPointInits.1238 // Returns null if the face does not intersect with the ray, otherwise the result is1239 // an XRHitResult with matrix describing the pose of the intersection point.1240 _hitTestFace(face, origin, direction) {1241 const add = XRMathHelper.add;1242 const sub = XRMathHelper.sub;1243 const mul = XRMathHelper.mul;1244 const normalize = XRMathHelper.normalize;1245 const dot = XRMathHelper.dot;1246 const cross = XRMathHelper.cross;1247 const neg = XRMathHelper.neg;1248 //1. Calculate plane normal in world coordinates.1249 const point_A = face.vertices[0];1250 const point_B = face.vertices[1];1251 const point_C = face.vertices[2];1252 const edge_AB = sub(point_B, point_A);1253 const edge_AC = sub(point_C, point_A);1254 const normal = normalize(cross(edge_AB, edge_AC));1255 const numerator = dot(sub(point_A, origin), normal);1256 const denominator = dot(direction, normal);1257 if (Math.abs(denominator) < XRMathHelper.EPSILON) {1258 // Planes are nearly parallel - there's either infinitely many intersection points or 0.1259 // Both cases signify a "no hit" for us.1260 return null;1261 } else {1262 // Single intersection point between the infinite plane and the line (*not* ray).1263 // Need to calculate the hit test matrix taking into account the face vertices.1264 const distance = numerator / denominator;1265 if (distance < 0) {1266 // Line - plane intersection exists, but not the half-line - plane does not.1267 return null;1268 } else {1269 const intersection_point = add(origin, mul(distance, direction));1270 // Since we are treating the face as a solid, flip the normal so that its1271 // half-space will contain the ray origin.1272 const y_axis = denominator > 0 ? neg(normal) : normal;1273 let z_axis = null;1274 const cos_direction_and_y_axis = dot(direction, y_axis);1275 if (Math.abs(cos_direction_and_y_axis) > (1 - XRMathHelper.EPSILON)) {1276 // Ray and the hit test normal are co-linear - try using the 'up' or 'right' vector's projection on the face plane as the Z axis.1277 // Note: this edge case is currently not covered by the spec.1278 const up = {x: 0.0, y: 1.0, z: 0.0, w: 0.0};1279 const right = {x: 1.0, y: 0.0, z: 0.0, w: 0.0};1280 z_axis = Math.abs(dot(up, y_axis)) > (1 - XRMathHelper.EPSILON)1281 ? sub(up, mul(dot(right, y_axis), y_axis)) // `up is also co-linear with hit test normal, use `right`1282 : sub(up, mul(dot(up, y_axis), y_axis)); // `up` is not co-linear with hit test normal, use it1283 } else {1284 // Project the ray direction onto the plane, negate it and use as a Z axis.1285 z_axis = neg(sub(direction, mul(cos_direction_and_y_axis, y_axis))); // Z should point towards the ray origin, not away.1286 }1287 z_axis = normalize(z_axis);1288 const x_axis = normalize(cross(y_axis, z_axis));1289 // Filter out the points not in polygon.1290 if (!XRMathHelper.pointInFace(intersection_point, face)) {1291 return null;1292 }1293 const hitResult = {planeId: 0n};1294 hitResult.distance = distance; // Extend the object with additional information used by higher layers.1295 // It will not be serialized over mojom.1296 const matrix = new Array(16);1297 matrix[0] = x_axis.x;1298 matrix[1] = x_axis.y;1299 matrix[2] = x_axis.z;1300 matrix[3] = 0;1301 matrix[4] = y_axis.x;1302 matrix[5] = y_axis.y;1303 matrix[6] = y_axis.z;1304 matrix[7] = 0;1305 matrix[8] = z_axis.x;1306 matrix[9] = z_axis.y;1307 matrix[10] = z_axis.z;1308 matrix[11] = 0;1309 matrix[12] = intersection_point.x;1310 matrix[13] = intersection_point.y;1311 matrix[14] = intersection_point.z;1312 matrix[15] = 1;1313 hitResult.mojoFromResult = getPoseFromTransform(1314 XRMathHelper.decomposeRigidTransform(matrix));1315 return hitResult;1316 }1317 }1318 }1319 _getMojoFromViewer() {1320 if (!this.pose_) {1321 return XRMathHelper.identity();1322 }1323 const transform = {1324 position: [1325 this.pose_.position.x,1326 this.pose_.position.y,1327 this.pose_.position.z],1328 orientation: [1329 this.pose_.orientation.x,1330 this.pose_.orientation.y,1331 this.pose_.orientation.z,1332 this.pose_.orientation.w],1333 };1334 return getMatrixFromTransform(transform);1335 }1336 _getMojoFromViewerWithOffset(viewOffset) {1337 return { matrix: XRMathHelper.mul4x4(this._getMojoFromViewer(), viewOffset.matrix) };1338 }1339 _getMojoFromNativeOrigin(nativeOriginInformation) {1340 const mojo_from_viewer = this._getMojoFromViewer();1341 if (nativeOriginInformation.inputSourceSpaceInfo !== undefined) {1342 if (!this.input_sources_.has(nativeOriginInformation.inputSourceSpaceInfo.inputSourceId)) {1343 return null;1344 } else {1345 const inputSource = this.input_sources_.get(nativeOriginInformation.inputSourceSpaceInfo.inputSourceId);1346 return inputSource._getMojoFromInputSource(mojo_from_viewer);1347 }1348 } else if (nativeOriginInformation.referenceSpaceType !== undefined) {1349 switch (nativeOriginInformation.referenceSpaceType) {1350 case vrMojom.XRReferenceSpaceType.kLocal:...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2wptools.page(url, options, function(err, page) {3 page.get(function(err, data) {4 console.log(data);5 });6});7 page.get(function(err, data) {8 console.log(data);9 });10});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require("wptoolkit");2var viewer = wpt.getViewer();3var mojo = wpt._getMojoFromViewerWithOffset(viewer, 0, 0);4console.log("Mojo: " + mojo);5var wpt = require("wptoolkit");6var viewer = wpt.getViewer();7var mojo = wpt._getMojoFromViewer(viewer);8console.log("Mojo: " + mojo);9var wpt = require("wptoolkit");10var viewer = wpt.getViewer();11var mojo = wpt._getMojoFromViewerWithOffset(viewer, 0, 0);12console.log("Mojo: " + mojo);13var wpt = require("wptoolkit");14var viewer = wpt.getViewer();15var mojo = wpt._getMojoFromViewer(viewer);16console.log("Mojo: " + mojo);17var wpt = require("wptoolkit");18var viewer = wpt.getViewer();19var mojo = wpt._getMojoFromViewerWithOffset(viewer, 0, 0);20console.log("Mojo: " + mojo);21var wpt = require("wptoolkit");22var viewer = wpt.getViewer();23var mojo = wpt._getMojoFromViewer(viewer);24console.log("Mojo: " + mojo);25var wpt = require("wptoolkit");26var viewer = wpt.getViewer();27var mojo = wpt._getMojoFromViewerWithOffset(viewer, 0, 0);28console.log("Mojo: " + mojo);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptbPreview = new WPTB_Preview();2var viewer = wptbPreview._getMojoFromViewerWithOffset( 0, 0 );3var mojo = viewer.mojo;4var offset = viewer.offset;5WPTB_Preview.prototype._getMojoFromViewerWithOffset = function( x, y ) {6 var viewer = this._getViewer();7 var mojo = viewer.mojo;8 var offset = viewer.offset;9 while ( viewer ) {10 offset.x += viewer.offsetLeft;11 offset.y += viewer.offsetTop;12 viewer = viewer.offsetParent;13 }14 x += offset.x;15 y += offset.y;16 var element = document.elementFromPoint( x, y );17 if ( !element ) {18 return null;19 }20 while ( element ) {21 if ( element.mojo ) {22 mojo = element.mojo;23 break;24 }25 element = element.parentNode;26 }27 return { mojo: mojo, offset: offset };28};29Mojo.prototype._getViewer = function() {30 var viewer = this._viewer;31 if ( !viewer ) {32 viewer = document.getElementById( 'wptb-preview' );33 this._viewer = viewer;34 }35 return viewer;36};37Mojo.prototype._getOffset = function() {38 var offset = this._offset;39 if ( !offset ) {40 offset = { x: 0, y: 0 };41 this._offset = offset;42 }43 return offset;44};45Mojo.prototype._getOffset = function() {46 var offset = this._offset;47 if ( !offset ) {48 offset = { x: 0, y: 0 };49 this._offset = offset;50 }51 return offset;52};53Mojo.prototype._getOffset = function() {54 var offset = this._offset;55 if ( !offset ) {56 offset = { x: 0, y: 0 };57 this._offset = offset;58 }59 return offset;60};

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var offset = 3;3wptools._getMojoFromViewerWithOffset(viewer, offset, function(err, mojo) {4 if (err) {5 console.log(err);6 } else {7 console.log(mojo);8 }9});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('WebPageTest');2var wpt = new WebPageTest('www.webpagetest.org', 'A.2e2b9d9b0c6d7e8c1c6f7d6e7e6c7e8b');3var options = {4};5wpt.runTest(url, options, function(err, data) {6 if (err) return console.log(err);7 console.log(data);8});9var wpt = require('WebPageTest');10var wpt = new WebPageTest('www.webpagetest.org', 'A.2e2b9d9b0c6d7e8c1c6f7d6e7e6c7e8b');11var options = {12};13wpt.runTest(url, options, function(err, data) {14 if (err) return console.log(err);15 console.log(data);16});17wpt._getMojoFromViewerWithOffset(data.data.testId, 0, function(err, data) {18 if (err) return console.log(err);19 console.log(data);20});21wpt.getTestResults(data.data.testId, function(err, data) {22 if (err) return console.log(err);23 console.log(data);24});

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful