{"id":33597,"date":"2017-10-04T14:09:02","date_gmt":"2017-10-04T21:09:02","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=33597"},"modified":"2017-10-04T14:09:02","modified_gmt":"2017-10-04T21:09:02","slug":"the-solar-system-with-arkit-and-f","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/the-solar-system-with-arkit-and-f\/","title":{"rendered":"The Solar System with ARKit and F#"},"content":{"rendered":"<p>\t\t\t\tA few years ago, my colleague <a href=\"https:\/\/twitter.com\/joelmartinez\">Joel Martinez<\/a> and I wrote a F# program we called \u201c<a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios8\/SceneKitFSharp\/\">Oculus Thrift<\/a>\u201d that demonstrated iOS SceneKit in a Google Cardboard stereoscopic viewer. With the recent release of iOS 11, I wanted to see if we could do something similar with ARKit, Apple\u2019s augmented-reality framework. It took just 8 lines of F# code.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-33600\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/u_are_here.png\" alt=\"\" width=\"1508\" height=\"1052\" \/><\/p>\n<h2>Let&#8217;s get\u00a03D with\u00a0ARKit<\/h2>\n<p>I do most of my exploratory iOS programming in F#. I typically start with Xamarin\u2019s \u201cSingle View App\u201d project and build my UI programmatically.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/fig1.png\"><img decoding=\"async\" class=\"alignnone wp-image-33602\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/fig1.png\" alt=\"\" width=\"800\" height=\"259\" \/><\/a><\/p>\n<p>In the case of a simple ARKit application, this is especially easy: create an <code>ARSCNView<\/code>, set its <code>Frame<\/code> property, and add it to the view hierarchy. However, to create a Cardboard-compatible experience, you need two views, each of which consumes half the screen:<\/p>\n<pre><code>\nlet halfWidth = this.View.Frame.Width \/ nfloat(2.)\nlet leftEyeView &lt;- new ARSCNView()\nleftEyeView.Frame &lt;- new CGRect(nfloat(0.), nfloat(0.), halfWidth, this.View.Frame.Height)\n \nlet rightEyeView = new ARSCNView()\nrightEyeView.Frame &lt;- new CGRect(halfWidth, nfloat(0.), halfWidth, this.View.Frame.Height)\n \nthis.View.AddSubview leftEyeView\nthis.View.AddSubview rightEyeView\n<\/code><\/pre>\n<p>As I discussed in an <a href=\"https:\/\/blog.xamarin.com\/augment-reality-xamarin-ios-11\/\">earlier blog post<\/a>, the <code>ARSCNView<\/code> class displays SceneKit-based 3D geometry. SceneKit itself uses a scene-graph model, in which nodes are positioned relative to their <code>ParentNode<\/code>.<\/p>\n<p>In our original \u201cOculus Thrift\u201d code, Joel and I created stereo vision by using two different camera nodes, offset slightly in space. That strategy won\u2019t work with ARKit, since the camera in an <code>ARSCNView<\/code> is managed by the ARKit subsystem which moves the camera relative to real-world coordinates (more accurately: relative to an origin that is the real-world position and orientation of the device at the time the <code>ARSession<\/code> begins).<\/p>\n<p>So instead of using two camera nodes, duplicate the left eye\u2019s scene-graph geometry, offset it by the inter-pupillary distance (mine is 64mm), and add the cloned geometry to this offset node:<\/p>\n<pre><code>\nlet offsetNode = new SCNNode()\noffsetNode.Position &lt;- new SCNVector3(0.064f, 0.f, 0.f)\nrightEyeView.Scene.RootNode.Add offsetNode\nlet ems2 = earthMoonSystem.Clone()\noffsetNode.Add ems2\n<\/code><\/pre>\n<p>The final trick is to get both views to use the same <code>ARSession<\/code>, which is simply a matter of assignment. Then, we kick off the session:<\/p>\n<pre><code>\nrightEyeView.Session &lt;- leftEyeView.Session\nleftEyeView.Session.Run (configuration, ARSessionRunOptions.RemoveExistingAnchors)\n<\/pre>\n<p><\/code><\/p>\n<p>The result is side-by-side augmented-reality views whose computer-generated 3D imagery invites the mind to fuse into a 3D view:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/fig2.jpeg\"><img decoding=\"async\" class=\"alignnone wp-image-33601\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/fig2.jpeg\" alt=\"\" width=\"800\" height=\"450\" \/><\/a><\/p>\n<p>Ironically, because the device's camera is shared between views, when viewed in a Google Cardboard device, the real-world view is flat and only the computer-generated imagery appears in 3D.\u00a0Let's\u00a0explore our solar system a little more with ARKit and see what else there is to learn.<\/p>\n<h2>Exploring the Solar System with ARKit<\/h2>\n<p>I think one of the real educational opportunities relating to mixed-reality is scale and proportion. It\u2019s very difficult to relate to geological age or atomic scale or cosmic scale. Having just experienced the amazing total solar eclipse, I thought it might be interesting to do an AR experience that showed the Earth and Moon in their actual proportions. Of course, F#\u2019s units-of-measure came in handy:<\/p>\n<pre><code>\n[] type km\n[] type m\n \n\/\/ 100 * 10^6 : 1\nlet scale = 100000.0\/1.0\n \n[\n(\"earth\", {Name = \"Earth\"; Radius = 6371.0; Surface = material \"Earth.png\" } );\n(\"moon\", {Name = \"Moon\"; Radius = 1079.0; Surface = material \"moon-4k.png\" } );\n(\"jupiter\", { Name = \"Jupiter\"; Radius = 139822.; Surface = material \"jupiter2k.jpg\" }) ;\n(\"sun\", { Name = \"Sun\"; Radius = 1391400.; Surface = material \"sdo.jpg\"})\n] |&gt; Map.ofList\n \nlet moonDistance = 384400.0\n \nlet globeGeometry body =\n    let scaledRadius = float(body.Radius \/ scale) |&gt; nfloat\n    let geo = SCNSphere.Create scaledRadius\n    geo.Materials &lt;- [| body.Surface; body.Surface;body.Surface;body.Surface;body.Surface;body.Surface; |]\n    geo\n<\/code><\/pre>\n<p>The problem with the above scale is that you lose the moon; it becomes a 1cm ball that orbits at a distance of 3.8m. For most of its orbit, it's barely a few pixels high. So, instead of going for realistic distances, I decided to go for realistic proportions.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/close_earth.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-33604\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/close_earth.png\" alt=\"\" width=\"800\" height=\"450\" \/><\/a><\/p>\n<p>The <a href=\"https:\/\/github.com\/lobrien\/Orrery\">Orrery<\/a>\u00a0project puts the Moon, Earth, Jupiter, and Sun in an augmented-reality view. To get the whole Sun in the view, I find I have to stand about 30m away. To create a realistic eclipse simulator with the 1cm Moon, the Sun would have to be 1.5K away!<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/u_are_here.png\"><img decoding=\"async\" class=\"alignnone wp-image-33600\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/u_are_here.png\" alt=\"\" width=\"800\" height=\"558\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Since I'm a glutton for punishment, I calculated the distance to Proxima Centauri at this scale. Imagine a\u00a06cm Earth and the\u00a014m Sun an appropriate kilometer-and-a-half away... a properly-distant Proxima Centauri would be\u00a0pretty much sitting on the surface of the Moon, 400,000km away!<\/p>\n<p>As Douglas Adams said: \"<a href=\"https:\/\/www.amazon.com\/dp\/B000XUBC2C\/ref=dp-kindle-redirect?_encoding=UTF8&amp;btkr=1\">You may think it's a long way down the road to the chemist's, but that's just peanuts to space.<\/a>\"<\/p>\n<p>All source code for both the realistically-proportioned <a href=\"https:\/\/github.com\/lobrien\/Orrery\">Orrery<\/a>\u00a0project and the <a href=\"https:\/\/github.com\/lobrien\/ARKit_Oculus_Thrift\">Google Cardboard compatible stereoscopic AR project<\/a>\u00a0are available on Github. Pull-requests and questions welcome! Make sure to also check out the <a href=\"https:\/\/developer.xamarin.com\/guides\/ios\/platform_features\/introduction-to-ios11\/\">Introduction to iOS 11 guide<\/a> in the Xamarin Developer Center.<\/p>\n<p><a href=\"https:\/\/forums.xamarin.com\/104409\">Discuss this post in the Xamarin Forums!<\/a>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few years ago, my colleague Joel Martinez and I wrote a F# program we called \u201cOculus Thrift\u201d that demonstrated iOS SceneKit in a Google Cardboard stereoscopic viewer. With the recent release of iOS 11, I wanted to see if we could do something similar with ARKit, Apple\u2019s augmented-reality framework. It took just 8 lines [&hellip;]<\/p>\n","protected":false},"author":556,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[6,4],"class_list":["post-33597","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-ios","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>A few years ago, my colleague Joel Martinez and I wrote a F# program we called \u201cOculus Thrift\u201d that demonstrated iOS SceneKit in a Google Cardboard stereoscopic viewer. With the recent release of iOS 11, I wanted to see if we could do something similar with ARKit, Apple\u2019s augmented-reality framework. It took just 8 lines [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/33597","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/556"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=33597"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/33597\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=33597"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=33597"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=33597"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}