public static ARHitTestResult SmartHitTest(this ARSCNView self, CGPoint point) { // Perform the hit test. var results = self.HitTest(point, ARHitTestResultType.ExistingPlaneUsingGeometry); // 1. Check for a result on an existing plane using geometry. var existingPlaneUsingGeometryResult = results.FirstOrDefault(result => result.Type == ARHitTestResultType.ExistingPlaneUsingGeometry); if (existingPlaneUsingGeometryResult != null) { return(existingPlaneUsingGeometryResult); } // 2. Check for a result on an existing plane, assuming its dimensions are infinite. var infinitePlaneResults = self.HitTest(point, ARHitTestResultType.ExistingPlane); var infinitePlaneResult = infinitePlaneResults.FirstOrDefault(); if (infinitePlaneResult != null) { return(infinitePlaneResult); } // 3. As a final fallback, check for a result on estimated planes. return(results.FirstOrDefault(result => result.Type == ARHitTestResultType.EstimatedHorizontalPlane)); }
public void TapAction(UITapGestureRecognizer gestureRecognizer) { var location = gestureRecognizer.LocationOfTouch(0, scnView); var hits = scnView.HitTest(location, new SCNHitTestOptions()); if (hits.Count() != 0) { var tappedNodeName = hits.FirstOrDefault().Node.Name; UIAlertView alert = new UIAlertView() { Title = tappedNodeName, Message = "You found a " + tappedNodeName }; alert.AddButton("OK"); alert.Show(); } }
private static SCNVector3?HitTestExistingPlanes(CGPoint point, ARSCNView sceneView) { var hitResult = sceneView.HitTest(point, ARHitTestResultType.ExistingPlaneUsingExtent); if (hitResult.Count() > 0) { var xPos = hitResult[0].WorldTransform.Column3.X; var yPos = hitResult[0].WorldTransform.Column3.Y; var zPos = hitResult[0].WorldTransform.Column3.Z; return(new SCNVector3(xPos, yPos, zPos)); } return(null); }
//Getting world position from touch hit Tuple <SCNVector3?, ARAnchor> WorldPositionFromHitTest(CGPoint pt) { //Hit test against existing anchors var hits = scnView.HitTest(pt, ARHitTestResultType.ExistingPlaneUsingExtent); if (hits != null && hits.Length > 0) { var anchors = hits.Where(r => r.Anchor is ARPlaneAnchor); if (anchors.Count() > 0) { var first = anchors.First(); var pos = PositionFromTransform(first.WorldTransform); return(new Tuple <SCNVector3?, ARAnchor>(pos, (ARPlaneAnchor)first.Anchor)); } } return(new Tuple <SCNVector3?, ARAnchor>(null, null)); }
internal static ARHitTestResult SmartHitTest(this ARSCNView self, CGPoint point) { var hitTestResults = self.HitTest(point, ARHitTestResultType.FeaturePoint); if (hitTestResults == null || hitTestResults.Length == 0) { return(null); } foreach (var result in hitTestResults) { // Return the first result which is between 20 cm and 3 m away from the user. if (result.Distance > 0.2 && result.Distance < 3) { return(result); } } return(null); }
private void HandleTap(UITapGestureRecognizer recognizer) { var tapLocation = recognizer.LocationInView(sceneView); var hitTestResults = sceneView.HitTest(tapLocation, ARHitTestResultType.ExistingPlaneUsingExtent); if (hitTestResults != null && hitTestResults.Length > 0) { var hitTestResult = hitTestResults[0]; var translation = PositionFromTransform(hitTestResult.WorldTransform); var x = translation.X; var y = translation.Y; var z = translation.Z; var shipScene = SCNScene.FromFile("Sprites/ship.scn"); var shipNode = shipScene.RootNode.FindChildNode("ship", false); shipNode.Position = new SCNVector3(x, y, z); sceneView.Scene.RootNode.AddChildNode(shipNode); } }
public override void TouchesBegan(Foundation.NSSet touches, UIEvent evt) { if (touches.Count != 0) { var touch = touches.ToArray <UITouch>()[0]; var location = touch.LocationInView(sceneView); var hitList = sceneView.HitTest(location, new SCNHitTestOptions()); if (hitList.Length > 0) { var hitObject = hitList[0]; if (hitObject.Node.Name == "ARShip") { hitObject.Node.RemoveFromParentNode(); AddObject(); } } } }
internal (SCNVector3?, ARPlaneAnchor, Boolean) WorldPositionFromScreenPosition(CGPoint position, ARSCNView sceneView, SCNVector3?objectPos, bool infinitePlane = false) { var dragOnInfinitePlanesEnabled = AppSettings.DragOnInfinitePlanes; // ------------------------------------------------------------------------------- // 1. Always do a hit test against exisiting plane anchors first. // (If any such anchors exist & only within their extents.) var planeHitTestResults = sceneView.HitTest(position, ARHitTestResultType.ExistingPlaneUsingExtent); var result = planeHitTestResults.FirstOrDefault(); if (result != null) { var planeHitTestPosition = result.WorldTransform.Translation(); var planeAnchor = result.Anchor; return(planeHitTestPosition, (ARPlaneAnchor)planeAnchor, true); } // ------------------------------------------------------------------------------- // 2. Collect more information about the environment by hit testing against // the feature point cloud, but do not return the result yet. SCNVector3?featureHitTestPosition = null; var highQualityFeatureHitTestResult = false; var highQualityfeatureHitTestResults = sceneView.HitTestWithFeatures(position, 18, 0.2, 2.0); if (highQualityfeatureHitTestResults.Count() > 0) { var highQualityFeatureHit = highQualityfeatureHitTestResults.First(); featureHitTestPosition = highQualityFeatureHit.Position; highQualityFeatureHitTestResult = true; } // ------------------------------------------------------------------------------- // 3. If desired or necessary (no good feature hit test result): Hit test // against an infinite, horizontal plane (ignoring the real world). if ((infinitePlane && dragOnInfinitePlanesEnabled) || !highQualityFeatureHitTestResult) { if (objectPos.HasValue) { var pointOnInfinitePlane = sceneView.HitTestWithInfiniteHorizontalPlane(position, objectPos.Value); if (pointOnInfinitePlane != null) { return(pointOnInfinitePlane, null, true); } } } // ------------------------------------------------------------------------------- // 4. If available, return the result of the hit test against high quality // features if the hit tests against infinite planes were skipped or no // infinite plane was hit. if (highQualityFeatureHitTestResult) { return(featureHitTestPosition, null, false); } // ------------------------------------------------------------------------------- // 5. As a last resort, perform a second, unfiltered hit test against features. // If there are no features in the scene, the result returned here will be nil. var unfilteredFeatureHitTestResults = sceneView.HitTestWithFeatures(position); if (unfilteredFeatureHitTestResults.Count() > 0) { var unfilteredFeaturesResult = unfilteredFeatureHitTestResults.First(); return(unfilteredFeaturesResult.Position, null, false); } return(null, null, false); }
public static (SCNVector3?, ARPlaneAnchor, bool) WorldPositionFromScreenPosition(CGPoint position, ARSCNView sceneView, SCNVector3?objectPos, bool infinitePlane = false) { // ------------------------------------------------------------------------------- // 1. Always do a hit test against existing plane anchors first. // (If any such anchors exist & only within their extents.) var result = sceneView.HitTest(position, ARHitTestResultType.ExistingPlaneUsingExtent)?.FirstOrDefault(); if (result != null) { var planeHitTestPosition = result.WorldTransform.GetTranslation(); var planeAnchor = result.Anchor; // Return immediately - this is the best possible outcome. return(planeHitTestPosition, planeAnchor as ARPlaneAnchor, true); } // ------------------------------------------------------------------------------- // 2. Collect more information about the environment by hit testing against // the feature point cloud, but do not return the result yet. SCNVector3?featureHitTestPosition = null; var highQualityFeatureHitTestResult = false; var highQualityfeatureHitTestResults = sceneView.HitTestWithFeatures(position, 18f, 0.2f, 2f); if (highQualityfeatureHitTestResults.Any()) { featureHitTestPosition = highQualityfeatureHitTestResults[0].Position; highQualityFeatureHitTestResult = true; } // ------------------------------------------------------------------------------- // 3. If desired or necessary (no good feature hit test result): Hit test // against an infinite, horizontal plane (ignoring the real world). if (infinitePlane || !highQualityFeatureHitTestResult) { if (objectPos.HasValue) { var pointOnInfinitePlane = sceneView.HitTestWithInfiniteHorizontalPlane(position, objectPos.Value); if (pointOnInfinitePlane.HasValue) { return(pointOnInfinitePlane, null, true); } } } // ------------------------------------------------------------------------------- // 4. If available, return the result of the hit test against high quality // features if the hit tests against infinite planes were skipped or no // infinite plane was hit. if (highQualityFeatureHitTestResult) { return(featureHitTestPosition, null, false); } // ------------------------------------------------------------------------------- // 5. As a last resort, perform a second, unfiltered hit test against features. // If there are no features in the scene, the result returned here will be nil. var unfilteredFeatureHitTestResults = sceneView.HitTestWithFeatures(position); if (unfilteredFeatureHitTestResults.Any()) { var first = unfilteredFeatureHitTestResults[0]; return(first.Position, null, false); } return(null, null, false); }