Use physics in scene

Share on Twitter Share on Facebook Share on LinkedIn

Use physics in scene

Description

We will use physics in the scene. i.e gravity.

To do this we add a 2d horizontal plane to the scene and set PhysicsBody = SCNPhysicsBody.CreateKinematicBody().

Then we add 3d cubes at the location the user touches the screen and make it so they mimic gravity using PhysicsBody = SCNPhysicsBody.CreateDynamicBody().

We can see that the cubes are able to fall off the 2d plane.


Video


Code

using ARKit;
using Foundation;
using SceneKit;
using System;
using System.Linq;
using UIKit;

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

        public ViewController(IntPtr handle) : base(handle)
        {
            this.sceneView = new ARSCNView
            {
                AutoenablesDefaultLighting = true,
                AutomaticallyUpdatesLighting = 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.GravityAndHeading
            }, ARSessionRunOptions.ResetTracking | ARSessionRunOptions.RemoveExistingAnchors);

            var width = 0.5f;
            var length = 0.5f;

            var planeNode = new PlaneNode(width, length, UIColor.DarkGray);

            this.sceneView.Scene.RootNode.AddChildNode(planeNode);
        }

        public override void TouchesEnded(NSSet touches, UIEvent evt)
        {
            base.TouchesEnded(touches, evt);

            if (touches.AnyObject is UITouch touch)
            {
                var point = touch.LocationInView(this.sceneView);

                var hitTestOptions = new SCNHitTestOptions();

                var hits = this.sceneView.HitTest(point, hitTestOptions);
                var hit = hits.FirstOrDefault();

                if (hit == null)
                    return;

                var node = hit.Node;

                if (node == null)
                    return;

                var cubeNode = new CubeNode(0.05f, UIColor.Green)
                {
                    Position = new SCNVector3(
                        hit.WorldCoordinates.X,
                        hit.WorldCoordinates.Y + 0.1f,
                        hit.WorldCoordinates.Z
                    )
                };

                this.sceneView.Scene.RootNode.AddChildNode(cubeNode);
            }
        }

        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, UIColor color)
        {
            var rootNode = new SCNNode
            {
                Geometry = CreateGeometry(width, length, color),
                Position = new SCNVector3(0, 0, 0),
                PhysicsBody = SCNPhysicsBody.CreateKinematicBody(),
                EulerAngles = new SCNVector3((float)(-Math.PI / 2), 0, 0)
            };

            AddChildNode(rootNode);
        }

        private static SCNGeometry CreateGeometry(float width, float length, UIColor color)
        {
            var material = new SCNMaterial();
            material.Diffuse.Contents = color;
            material.DoubleSided = true;

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

            return geometry;
        }
    }

    public class CubeNode : SCNNode
    {
        public CubeNode(float size, UIColor color)
        {
            var rootNode = new SCNNode
            {
                Geometry = CreateGeometry(size, color),
                Position = new SCNVector3(0, size / 2, 0),
                PhysicsBody = SCNPhysicsBody.CreateDynamicBody(),
            };

            AddChildNode(rootNode);
        }

        private static SCNGeometry CreateGeometry(float size, UIColor color)
        {
            var material = new SCNMaterial();
            material.Diffuse.Contents = color;

            var geometry = SCNBox.Create(size, size, size, 0);
            geometry.Materials = new[] { material };
            geometry.ChamferRadius = 0.001f;

            return geometry;
        }
    }
}

Next Step : 3d photo gallery surround

After you have mastered this you should try 3d photo gallery surround