Place webview in scene

Share on Twitter Share on Facebook Share on LinkedIn

Place webview in scene

Description

In this lesson you can see how to place a virtual webpage into an augmented reality scene.

Specifically, we place an interactive UIWebView onto a 2d plane as a material and load a webpage to show. What is rather clever is that the webpage can still be interacted with i.e. scrolling and clicking links.

Please Note: That whilst the UIWebView is deprecated and replaced by the newer WKWebView, the latter doesn't seem to work in an augmented reality scene.


Video


Code

using ARKit;
using CoreGraphics;
using Foundation;
using SceneKit;
using System;
using UIKit;

namespace XamarinArkitSample
{
    public partial class ViewController : UIViewController
    {
        private readonly ARSCNView sceneView;
        SCNNode centerNode;

        public ViewController(IntPtr handle) : base(handle)
        {
            this.sceneView = new ARSCNView
            {
                AutoenablesDefaultLighting = true
            };

            this.View.AddSubview(this.sceneView);
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            this.sceneView.Frame = this.View.Frame;
        }

        public override void ViewDidAppear(bool animated)
        {
            base.ViewDidAppear(animated);

            this.sceneView.Session.Run(new ARWorldTrackingConfiguration
            {
                AutoFocusEnabled = true,
                PlaneDetection = ARPlaneDetection.Horizontal,
                LightEstimationEnabled = true,
                WorldAlignment = ARWorldAlignment.Gravity
            }, ARSessionRunOptions.ResetTracking | ARSessionRunOptions.RemoveExistingAnchors);

            centerNode = new SCNNode();
            this.sceneView.Scene.RootNode.AddChildNode(centerNode);

            var width = 0.29f;
            var length = 0.25f;

            var planeNode1 = new PlaneNode(width, length, "https://www.bbc.co.uk/news", -0.31f, 0, -0.3f, centerNode);
            var planeNode2 = new PlaneNode(width, length, "https://www.theguardian.com/uk", 0f, 0, -0.3f, centerNode);

            this.sceneView.Scene.RootNode.AddChildNode(planeNode1);
            this.sceneView.Scene.RootNode.AddChildNode(planeNode2);
        }

        public override void ViewDidDisappear(bool animated)
        {
            base.ViewDidDisappear(animated);

            this.sceneView.Session.Pause();
        }

        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
        }
    }

    public class PlaneNode : SCNNode
    {
        public PlaneNode(float width, float length, string url, float x, float y, float z, SCNNode lookAtNode)
        {
            var rootNode = new SCNNode
            {
                Geometry = CreateGeometry(width, length, url),
                Position = new SCNVector3(x, y, z),
            };

            AddChildNode(rootNode);
        }

        private static SCNGeometry CreateGeometry(float width, float length, string url)
        {
            // Note: UIWebView is deprecated and replaced with WKWebView (but doesn't seem to work in ARKit?)
            var webView = new UIWebView(new CGRect(0, 0, 800, 1024));

            var request = new NSUrlRequest(new NSUrl(url));
            webView.LoadRequest(request);

            var material = new SCNMaterial();
            material.Diffuse.Contents = webView;
            material.DoubleSided = true;

            var geometry = SCNPlane.Create(width, length);
            geometry.Materials = new[] { material };

            return geometry;
        }
    }
}

Next Step : Periodic table

After you have mastered this you should try Periodic table