text:
//-----------------------------------------------------------------------
// <copyright file="ApiTrackableTypeExtensions.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCoreInternal
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using GoogleARCore;

    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
    Justification = "Internal")]
    public static class ApiTrackableTypeExtensions
    {
        public static ApiTrackableType GetApiTrackableType(this Type type)
        {
            if (type == typeof(TrackedPlane))
            {
                return ApiTrackableType.Plane;
            }
            else if (type == typeof(Trackable))
            {
                return ApiTrackableType.BaseTrackable;
            }
            else
            {
                return ApiTrackableType.Invalid;
            }
        }
    }
}


text:
fileFormatVersion: 2
guid: d6fca0e25bb6e4612acb66cacc00f8ff
timeCreated: 1509468914
licenseType: Free
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:

repo_name: jonas-johansson/ARCoreUtils

repo_language: C#

mime_type: text/plain


text:
fileFormatVersion: 2
guid: d972b11e53fb14a5cb38b3b81e420a7a
timeCreated: 1511395337
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="PlaneApi.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCoreInternal
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using GoogleARCore;
    using UnityEngine;

    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
    Justification = "Internal")]
    public class PlaneApi
    {
        private const int k_MaxPolygonSize = 1024;
        private NativeSession m_NativeSession;
        private float[] m_TmpPoints;
        private GCHandle m_TmpPointsHandle;

        public PlaneApi(NativeSession nativeSession)
        {
            m_NativeSession = nativeSession;
            m_TmpPoints = new float[k_MaxPolygonSize * 2];
            m_TmpPointsHandle = GCHandle.Alloc(m_TmpPoints, GCHandleType.Pinned);
        }

        ~PlaneApi()
        {
            m_TmpPointsHandle.Free();
        }

        public Pose GetCenterPose(IntPtr planeHandle)
        {
            var poseHandle = m_NativeSession.PoseApi.Create();
            ExternApi.ArPlane_getCenterPose(m_NativeSession.SessionHandle, planeHandle, poseHandle);
            Pose resultPose = m_NativeSession.PoseApi.ExtractPoseValue(poseHandle);
            m_NativeSession.PoseApi.Destroy(poseHandle);
            return resultPose;
        }

        public float GetExtentX(IntPtr planeHandle)
        {
            float extentX = 0.0f;
            ExternApi.ArPlane_getExtentX(m_NativeSession.SessionHandle, planeHandle, ref extentX);
            return extentX;
        }

        public float GetExtentZ(IntPtr planeHandle)
        {
            float extentZ = 0.0f;
            ExternApi.ArPlane_getExtentZ(m_NativeSession.SessionHandle, planeHandle, ref extentZ);
            return extentZ;
        }

        public void GetPolygon(IntPtr planeHandle, List<Vector3> points)
        {
            points.Clear();
            int pointCount = 0;
            ExternApi.ArPlane_getPolygonSize(m_NativeSession.SessionHandle, planeHandle, ref pointCount);
            if (pointCount < 1)
            {
                return;
            }
            else if (pointCount > k_MaxPolygonSize)
            {
                Debug.LogError("GetPolygon::Plane polygon size exceeds buffer capacity.");
                pointCount = k_MaxPolygonSize;
            }

            ExternApi.ArPlane_getPolygon(m_NativeSession.SessionHandle, planeHandle, m_TmpPointsHandle.AddrOfPinnedObject());

            var planeCenter = GetCenterPose(planeHandle);
            var unityWorldTPlane = Matrix4x4.TRS(planeCenter.position, planeCenter.rotation, Vector3.one);
            for (int i = pointCount - 2; i >= 0; i -= 2)
            {
                var point = unityWorldTPlane.MultiplyPoint3x4(new Vector3(m_TmpPoints[i], 0, -m_TmpPoints[i + 1]));
                points.Add(point);
            }
        }

        public TrackedPlane GetSubsumedBy(IntPtr planeHandle)
        {
            IntPtr subsumerHandle = IntPtr.Zero;
            ExternApi.ArPlane_acquireSubsumedBy(m_NativeSession.SessionHandle, planeHandle, ref subsumerHandle);
            return m_NativeSession.TrackableFactory(subsumerHandle) as TrackedPlane;
        }

        public bool IsPoseInExtents(IntPtr planeHandle, Pose pose)
        {
            // The int is used as a boolean value as the C API expects a int32_t value to represent a boolean.
            int isPoseInExtents = 0;
            var poseHandle = m_NativeSession.PoseApi.Create(pose);
            ExternApi.ArPlane_isPoseInExtents(m_NativeSession.SessionHandle, planeHandle, poseHandle, ref isPoseInExtents);
            m_NativeSession.PoseApi.Destroy(poseHandle);
            return isPoseInExtents != 0;
        }

        public bool IsPoseInExtents(IntPtr planeHandle, IntPtr poseHandle)
        {
            // The int is used as a boolean value as the C API expects a int32_t value to represent a boolean.
            int isPoseInExtents = 0;
            ExternApi.ArPlane_isPoseInExtents(m_NativeSession.SessionHandle, planeHandle, poseHandle, ref isPoseInExtents);
            return isPoseInExtents != 0;
        }

        public bool IsPoseInPolygon(IntPtr planeHandle, Pose pose)
        {
            // The int is used as a boolean value as the C API expects a int32_t value to represent a boolean.
            int isPoseInPolygon = 0;
            var poseHandle = m_NativeSession.PoseApi.Create(pose);
            ExternApi.ArPlane_isPoseInPolygon(m_NativeSession.SessionHandle, planeHandle, poseHandle, ref isPoseInPolygon);
            m_NativeSession.PoseApi.Destroy(poseHandle);
            return isPoseInPolygon != 0;
        }

        public bool IsPoseInPolygon(IntPtr planeHandle, IntPtr poseHandle)
        {
            // The int is used as a boolean value as the C API expects a int32_t value to represent a boolean.
            int isPoseInPolygon = 0;
            ExternApi.ArPlane_isPoseInPolygon(m_NativeSession.SessionHandle, planeHandle, poseHandle, ref isPoseInPolygon);
            return isPoseInPolygon != 0;
        }

        private struct ExternApi
        {
            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_getCenterPose(IntPtr sessionHandle, IntPtr planeHandle,
                IntPtr poseHandle);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_acquireSubsumedBy(IntPtr sessionHandle, IntPtr planeHandle,
                ref IntPtr subsumerHandle);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_getExtentX(IntPtr sessionHandle, IntPtr planeHandle,
                ref float extentX);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_getExtentZ(IntPtr sessionHandle, IntPtr planeHandle,
                ref float extentZ);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_getPolygonSize(IntPtr sessionHandle, IntPtr planeHandle,
                ref int polygonSize);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_getPolygon(IntPtr sessionHandle, IntPtr planeHandle,
                IntPtr polygonXZ);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_isPoseInExtents(IntPtr sessionHandle, IntPtr planeHandle,
                IntPtr poseHandle, ref int isPoseInExtents);

            [DllImport(ApiConstants.ARCoreNativeApi)]
            public static extern void ArPlane_isPoseInPolygon(IntPtr sessionHandle, IntPtr planeHandle,
                IntPtr poseHandle, ref int isPoseInPolygon);
        }
    }
}


text:
fileFormatVersion: 2
guid: 2ba38d18d01304b4ab5105846c55aff1
timeCreated: 1502330118
licenseType: Free
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="WaitForTaskCompletionYieldInstruction.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCoreInternal
{
    using System.Diagnostics.CodeAnalysis;
    using GoogleARCore;
    using UnityEngine;

    /// <summary>
    /// A yield instruction that blocks a coroutine until an AsyncTask has completed.
    /// </summary>
    /// <typeparam name="T">The type of the AsyncTask result.</typeparam>
    public class WaitForTaskCompletionYieldInstruction<T> : CustomYieldInstruction
    {
        /// <summary>
        /// The AsyncTask the yield instruction waits on.
        /// </summary>
        private AsyncTask<T> m_Task;

        /// <summary>
        /// Constructor for WaitForTaskCompletionYieldInstruction.
        /// </summary>
        /// <param name="task">The task to wait for completion.</param>
        public WaitForTaskCompletionYieldInstruction(AsyncTask<T> task)
        {
            m_Task = task;
        }

        /// <summary>
        /// Gets a value indicating whether the coroutine instruction should keep waiting.
        /// </summary>
        /// <value><c>true</c> if the task is incomplete, otherwise <c>false</c>.</value>
        [SuppressMessage("UnityRules.UnityStyleRules", "US1000:FieldsMustBeUpperCamelCase",
         Justification = "Overridden method.")]
        public override bool keepWaiting
        {
            get
            {
                return !m_Task.IsComplete;
            }
        }
    }
}


text:
fileFormatVersion: 2
guid: d9b715dad41754ff39bd62a2954dadf9
timeCreated: 1510001161
licenseType: Free
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Android: 0
        Exclude Editor: 1
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
        Exclude iOS: 1
  - first:
      Android: Android
    second:
      enabled: 1
      settings:
        CPU: ARMv7
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
        DefaultValueInitialized: true
        OS: AnyOS
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Facebook: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: x86
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: LinuxUniversal
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      iPhone: iOS
    second:
      enabled: 0
      settings:
        CompileFlags:
        FrameworkDependencies:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: bd091fc8013c942f586c1672b8ee2b27
timeCreated: 1500400815
licenseType: Free
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      Android: Android
    second:
      enabled: 1
      settings: {}
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 19eddef6ceb6961489b26fb8bf19f1e5
timeCreated: 1517361316
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Android: 0
        Exclude Editor: 1
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
  - first:
      Android: Android
    second:
      enabled: 1
      settings:
        CPU: ARMv7
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
        DefaultValueInitialized: true
        OS: AnyOS
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Facebook: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: x86
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: cb4b89ba21eac484797cfca938a1a5ea
timeCreated: 1518222591
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      Android: Android
    second:
      enabled: 1
      settings: {}
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: ccde220b10a8b441a9b728f80d014cfe
timeCreated: 1513372698
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Android: 0
        Exclude Editor: 1
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
  - first:
      Android: Android
    second:
      enabled: 1
      settings:
        CPU: ARMv7
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
        DefaultValueInitialized: true
        OS: AnyOS
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Facebook: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: x86
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: LinuxUniversal
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: e2fd4640a9f7349438a5920ea2fb35f2
timeCreated: 1518222616
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      Android: Android
    second:
      enabled: 1
      settings: {}
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: f62612db4b24deb43ada3a769754a2f7
timeCreated: 1503511556
licenseType: Free
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      Android: Android
    second:
      enabled: 1
      settings: {}
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 0
      settings:
        DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
  serializedVersion: 6
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 0}
  m_Name: ARBackground
  m_Shader: {fileID: 4800000, guid: 025775b2b3616154f9eec0261bb8a581, type: 3}
  m_ShaderKeywords:
  m_LightmapFlags: 4
  m_EnableInstancingVariants: 0
  m_DoubleSidedGI: 0
  m_CustomRenderQueue: -1
  stringTagMap: {}
  disabledShaderPasses: []
  m_SavedProperties:
    serializedVersion: 3
    m_TexEnvs:
    - _BumpMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _DetailAlbedoMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _DetailMask:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _DetailNormalMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _EmissionMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _MainTex:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _MetallicGlossMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _OcclusionMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _ParallaxMap:
        m_Texture: {fileID: 0}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    m_Floats:
    - _BumpScale: 1
    - _Cutoff: 0.5
    - _DetailNormalMapScale: 1
    - _DstBlend: 0
    - _GlossMapScale: 1
    - _Glossiness: 0.5
    - _GlossyReflections: 1
    - _Metallic: 0
    - _Mode: 0
    - _OcclusionStrength: 1
    - _Parallax: 0.02
    - _SmoothnessTextureChannel: 0
    - _SpecularHighlights: 1
    - _SrcBlend: 1
    - _UVSec: 0
    - _ZWrite: 1
    m_Colors:
    - _Color: {r: 1, g: 1, b: 1, a: 1}
    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}


text:
fileFormatVersion: 2
guid: 03ad0130a037647aeb60218f61aca114
timeCreated: 1498003566
licenseType: Pro
NativeFormatImporter:
  mainObjectFileID: 2100000
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 025775b2b3616154f9eec0261bb8a581
timeCreated: 1510285086
licenseType: Pro
ShaderImporter:
  externalObjects: {}
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:


text:
Shader "ARCore/ARBackground"
{
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _UvTopLeftRight ("UV of top corners", Vector) = (0, 1, 1, 1)
        _UvBottomLeftRight ("UV of bottom corners", Vector) = (0 , 0, 1, 0)
    }

    // For GLES3
    SubShader
    {
        Pass
        {
            ZWrite Off

            GLSLPROGRAM

            #pragma only_renderers gles3

            #ifdef SHADER_API_GLES3
            #extension GL_OES_EGL_image_external_essl3 : require
            #endif

            uniform vec4 _UvTopLeftRight;
            uniform vec4 _UvBottomLeftRight;

            #ifdef VERTEX

            varying vec2 textureCoord;

            void main()
            {
                #ifdef SHADER_API_GLES3
                vec2 uvTop = mix(_UvTopLeftRight.xy, _UvTopLeftRight.zw, gl_MultiTexCoord0.x);
                vec2 uvBottom = mix(_UvBottomLeftRight.xy, _UvBottomLeftRight.zw, gl_MultiTexCoord0.x);
                textureCoord = mix(uvTop, uvBottom, gl_MultiTexCoord0.y);

                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                #endif
            }

            #endif

            #ifdef FRAGMENT
            varying vec2 textureCoord;
            uniform samplerExternalOES _MainTex;

            void main()
            {
                #ifdef SHADER_API_GLES3
                gl_FragColor = texture(_MainTex, textureCoord);
                #endif
            }

            #endif

            ENDGLSL
        }
    }

  Subshader
  {
    Pass
    {
      ZWrite Off

      CGPROGRAM

      #pragma exclude_renderers gles3
      #pragma vertex vert
      #pragma fragment frag

      #include "UnityCG.cginc"

      uniform float4 _UvTopLeftRight;
      uniform float4 _UvBottomLeftRight;

      struct appdata
      {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
      };

      struct v2f
      {
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
      };

      v2f vert(appdata v)
      {
        float2 uvTop = lerp(_UvTopLeftRight.xy, _UvTopLeftRight.zw, v.uv.x);
        float2 uvBottom = lerp(_UvBottomLeftRight.xy, _UvBottomLeftRight.zw, v.uv.x);

        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex);
        o.uv = lerp(uvTop, uvBottom, v.uv.y);

        // Instant preview's texture is transformed differently.
        o.uv = o.uv.yx;
        o.uv.x = 1.0 - o.uv.x;

        return o;
      }

      sampler2D _MainTex;

      fixed4 frag(v2f i) : SV_Target
      {
        return tex2D(_MainTex, i.uv);
      }
      ENDCG
    }
  }

  FallBack Off
}


text:
fileFormatVersion: 2
guid: ede998a9371e74aa6a759743f41b3eb6
folderAsset: yes
timeCreated: 1513969093
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: a10b012db03ac404a87dcb0519846527
folderAsset: yes
timeCreated: 1513969093
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="InstantPreviewTrackedPoseDriver.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCore
{
    using UnityEngine;

    /// <summary>
    /// Drives cameras when using Instant Preview, since there is no easy way to
    /// provide data to Unity's TrackedPoseDriver.
    /// </summary>
    public class InstantPreviewTrackedPoseDriver : MonoBehaviour
    {
        /// <summary>
        /// Updates the game object's transform to that of the latest pose
        /// received by Instant Preview.
        /// </summary>
        public void Update()
        {
            if (!Application.isEditor)
            {
                return;
            }

            transform.position = Frame.Pose.position;
            transform.rotation = Frame.Pose.rotation;
        }
    }
}


text:
fileFormatVersion: 2
guid: 307167e96a9af144789862588807c91b
timeCreated: 1512450063
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: ed2d2995c742a6c4490fa51080dbf4cf
timeCreated: 1512422473
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 8d78f35e6ec68ed4ba199eddf266e308
timeCreated: 1513720134
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: cf7b10762fe921e40a18151a6c92a8a6
timeCreated: 1515546772
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="InstantPreviewInput.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCore
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using GoogleARCoreInternal;
    using UnityEngine;

    /// <summary>
    /// Helper class that provides touch input in lieu of Input.GetTouch when
    /// running the Unity Editor.
    /// </summary>
    public static class InstantPreviewInput
    {
        private static Touch[] s_Touches = new Touch[0];

        /// <summary>
        /// Gets the available touch inputs from Instant Preview since the last
        /// update.
        /// </summary>
        [SuppressMessage("UnityRules.UnityStyleRules", "US1000:FieldsMustBeUpperCamelCase",
         Justification = "Overridden field.")]
        public static Touch[] touches
        {
            get
            {
                return s_Touches;
            }
        }

        /// <summary>
        /// Gets the number of touches available from Instant preview since the
        /// last update.
        /// </summary>
        [SuppressMessage("UnityRules.UnityStyleRules", "US1000:FieldsMustBeUpperCamelCase",
         Justification = "Overridden field.")]
        public static int touchCount
        {
            get
            {
                return touches.Length;
            }
        }

        /// <summary>
        /// Gets return value of Input.mousePosition.
        /// </summary>
        [SuppressMessage("UnityRules.UnityStyleRules", "US1000:FieldsMustBeUpperCamelCase",
         Justification = "Overridden field.")]
        public static Vector3 mousePosition
        {
            get
            {
                return Input.mousePosition;
            }
        }

        /// <summary>
        /// Gets a value indicating whether a mouse device is detected.
        /// </summary>
        [SuppressMessage("UnityRules.UnityStyleRules", "US1000:FieldsMustBeUpperCamelCase",
         Justification = "Overridden field.")]
        public static bool mousePresent
        {
            get
            {
                return Input.mousePresent;
            }
        }

        /// <summary>
        /// Gets a specific touch input from Instant Preview by index.
        /// </summary>
        /// <param name="index">Index of touch input to get.</param>
        /// <returns>Touch data.</returns>
        public static Touch GetTouch(int index)
        {
            return touches[index];
        }

        /// <summary>
        /// Passthrough function to Input.GetKey.
        /// </summary>
        /// <param name="keyCode">Key parameter to pass to Input.GetKey.</param>
        /// <returns>Key state returned from Input.GetKey.</returns>
        public static bool GetKey(KeyCode keyCode)
        {
            return Input.GetKey(keyCode);
        }

        /// <summary>
        /// Passthrough function to Input.GetMouseButton.
        /// </summary>
        /// <param name="button">Button index.</param>
        /// <returns>Return value of Input.GetMouseButton.</returns>
        public static bool GetMouseButton(int button)
        {
            return Input.GetMouseButton(button);
        }

        /// <summary>
        /// Passthrough function to Input.GetMouseButtonDown.
        /// </summary>
        /// <param name="button">Button index.</param>
        /// <returns>Return value of Input.GetMouseButtonDown.</returns>
        public static bool GetMouseButtonDown(int button)
        {
            return Input.GetMouseButtonDown(button);
        }

        /// <summary>
        /// Passthrough function to Input.GetMouseButtonUp.
        /// </summary>
        /// <param name="button">Button index.</param>
        /// <returns>Return value of Input.GetMouseButtonUp.</returns>
        public static bool GetMouseButtonUp(int button)
        {
            return Input.GetMouseButtonUp(button);
        }

        /// <summary>
        /// Refreshes touch inputs from Instant Preview to reflect the state
        /// since the last time Update was called.
        /// </summary>
        public static void Update()
        {
            if (!Application.isEditor)
            {
                return;
            }

            IntPtr nativeTouchesPtr;
            int nativeTouchCount;
            NativeApi.GetTouches(out nativeTouchesPtr, out nativeTouchCount);

            var structSize = Marshal.SizeOf(typeof(NativeTouch));
            s_Touches = new Touch[nativeTouchCount];
            for (var i = 0; i < nativeTouchCount; ++i)
            {
                var source = new IntPtr(nativeTouchesPtr.ToInt64() + (i * structSize));
                var nativeTouch = (NativeTouch)Marshal.PtrToStructure(source, typeof(NativeTouch));

                s_Touches[i] = new Touch()
                {
                    phase = nativeTouch.Phase,

                    // Note that the Unity's screen coordinate (0, 0) starts from bottom left.
                    position = new Vector2(nativeTouch.X, Screen.height - nativeTouch.Y),
                };
            }
        }

        private struct NativeTouch
        {
            public TouchPhase Phase;
            public float X;
            public float Y;
        }

        private struct NativeApi
        {
            [DllImport(InstantPreviewManager.InstantPreviewNativeApi)]
            public static extern void GetTouches(out IntPtr touches, out int count);
        }
    }
}


text:
//-----------------------------------------------------------------------
// <copyright file="InstantPreviewManager.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCoreInternal
{
    using System;
    using System.Collections;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using GoogleARCore;
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.SpatialTracking;

    /// <summary>
    /// Contains methods for managing communication to the Instant Preview
    /// plugin.
    /// </summary>
    public static class InstantPreviewManager
    {
        /// <summary>
        /// Name of the Instant Preview plugin library.
        /// </summary>
        public const string InstantPreviewNativeApi = "instant_preview_unity_plugin";

        // Guid is taken from meta file and should never change.
        private const string k_ApkGuid = "cf7b10762fe921e40a18151a6c92a8a6";
        private const string k_NoDevicesFoundAdbResult = "error: no devices/emulators found";
        private const float k_MaxTolerableAspectRatioDifference = 0.1f;
        private const string k_MismatchedAspectRatioWarningFormatString =
            "The aspect ratio of your game window is different from the aspect ratio of your Instant Preview camera " +
            "texture. Please resize your game window's aspect ratio to match, or your preview will be distorted. The " +
            "camera texture resolution is {0}, {1}.";

        private static readonly WaitForEndOfFrame k_WaitForEndOfFrame = new WaitForEndOfFrame();

        private static bool s_PauseWarned = false;
        private static bool s_DisabledLightEstimationWarned = false;
        private static bool s_DisabledPlaneFindingWarned = false;

        /// <summary>
        /// Coroutine method that communicates to the Instant Preview plugin
        /// every frame.
        ///
        /// If not running in the editor, this does nothing.
        /// </summary>
        /// <returns>Enumerator for a coroutine that updates Instant Preview
        /// every frame.</returns>
        public static IEnumerator InitializeIfNeeded()
        {
            // Terminates if not running in editor.
            if (!Application.isEditor)
            {
                yield break;
            }

            // User may have explicitly disabled Instant Preview.
            if (ARCoreProjectSettings.Instance != null &&
                !ARCoreProjectSettings.Instance.IsInstantPreviewEnabled)
            {
                yield break;
            }

            var adbPath = InstantPreviewManager.GetAdbPath();
            if (adbPath == null)
            {
                Debug.LogError("Instant Preview requires your Unity Android SDK path to be set. Please set it under " +
                               "Preferences/External Tools/Android. You may need to install the Android SDK first.");
                yield break;
            }
            else if (!File.Exists(adbPath))
            {
                Debug.LogErrorFormat("adb not found at \"{0}\". Please add adb to your SDK path and restart the Unity editor.", adbPath);
                yield break;
            }

            string localVersion;
            if (!StartServer(adbPath, out localVersion))
            {
                yield break;
            }

            yield return InstallApkAndRunIfConnected(adbPath, localVersion);

            yield return UpdateLoop();
        }

        /// <summary>
        /// Uploads the latest camera video frame received from Instant Preview
        /// to the specified texture. The texture might be recreated if it is
        /// not the right size or null.
        /// </summary>
        /// <param name="backgroundTexture">Texture variable to store the latest
        /// Instant Preview video frame.</param>
        /// <returns>True if InstantPreview updated the background texture,
        /// false if it did not and the texture still needs updating.</returns>
        public static bool UpdateBackgroundTextureIfNeeded(ref Texture2D backgroundTexture)
        {
            if (!Application.isEditor)
            {
                return false;
            }

            IntPtr pixelBytes;
            int width;
            int height;
            if (NativeApi.LockCameraTexture(out pixelBytes, out width, out height))
            {
                if (backgroundTexture == null || width != backgroundTexture.width ||
                    height != backgroundTexture.height)
                {
                    backgroundTexture = new Texture2D(width, height, TextureFormat.BGRA32, false);
                }

                backgroundTexture.LoadRawTextureData(pixelBytes, width * height * 4);
                backgroundTexture.Apply();

                NativeApi.UnlockCameraTexture();
            }

            return true;
        }

        /// <summary>
        /// Handles Instant Preview logic when ARCore's EarlyUpdate method is called.
        /// </summary>
        /// <param name="session">Relevant ARCoreSession object being updated.</param>
        public static void OnEarlyUpdate(ARCoreSession session)
        {
            if (Application.isEditor || session == null)
            {
                return;
            }

            if (!s_PauseWarned && !session.enabled)
            {
                Debug.LogWarning("Disabling ARCore session is not available in editor.");
                s_PauseWarned = true;
            }

            var config = session.SessionConfig;
            if (config == null)
            {
                return;
            }

            if (!s_DisabledLightEstimationWarned && !config.EnableLightEstimation)
            {
                Debug.LogWarning("ARCore light estimation cannot be disabled in editor.");
                s_DisabledLightEstimationWarned = true;
            }

            if (!s_DisabledPlaneFindingWarned && !config.EnablePlaneFinding)
            {
                Debug.LogWarning("ARCore plane finding cannot be disabled in editor.");
                s_DisabledPlaneFindingWarned = true;
            }
        }

        private static IEnumerator UpdateLoop()
        {
            var renderEventFunc = NativeApi.GetRenderEventFunc();
            var shouldConvertToBgra = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11;
            var loggedAspectRatioWarning = false;

            // Waits until the end of the first frame until capturing the screen size,
            // because it might be incorrect when first querying it.
            yield return k_WaitForEndOfFrame;

            // Creates a target texture to capture the preview window onto.
            // Some video encoders prefer the dimensions to be a multiple of 16.
            var targetWidth = RoundUpToNearestMultipleOf16(Screen.width);
            var targetHeight = RoundUpToNearestMultipleOf16(Screen.height);
            var screenTexture = new RenderTexture(targetWidth, targetHeight, 0);
            var targetTexture = screenTexture;
            RenderTexture bgrTexture = null;

            if (shouldConvertToBgra)
            {
                bgrTexture = new RenderTexture(screenTexture.width, screenTexture.height, 0, RenderTextureFormat.BGRA32);
                targetTexture = bgrTexture;
            }

            // Begins update loop. The coroutine will cease when the
            // ARCoreSession component it's called from is destroyed.
            for (;;)
            {
                yield return k_WaitForEndOfFrame;

                NativeApi.Update();
                InstantPreviewInput.Update();
                AddInstantPreviewTrackedPoseDriverWhenNeeded();

                Graphics.Blit(null, screenTexture);

                if (shouldConvertToBgra)
                {
                    Graphics.Blit(screenTexture, bgrTexture);
                }

                var cameraTexture = Frame.CameraImage.Texture;
                if (!loggedAspectRatioWarning && cameraTexture != null)
                {
                    var sourceWidth = cameraTexture.width;
                    var sourceHeight = cameraTexture.height;
                    var sourceAspectRatio = (float)sourceWidth / sourceHeight;
                    var destinationWidth = Screen.width;
                    var destinationHeight = Screen.height;
                    var destinationAspectRatio = (float)destinationWidth / destinationHeight;

                    if (Mathf.Abs(sourceAspectRatio - destinationAspectRatio) >
                        k_MaxTolerableAspectRatioDifference)
                    {
                        Debug.LogWarning(string.Format(k_MismatchedAspectRatioWarningFormatString, sourceWidth,
                                                       sourceHeight));
                        loggedAspectRatioWarning = true;
                    }
                }

                NativeApi.SendFrame(targetTexture.GetNativeTexturePtr());
                GL.IssuePluginEvent(renderEventFunc, 1);
            }
        }

        private static void AddInstantPreviewTrackedPoseDriverWhenNeeded()
        {
            foreach (var poseDriver in Component.FindObjectsOfType<TrackedPoseDriver>())
            {
                poseDriver.enabled = false;
                var gameObject = poseDriver.gameObject;
                var hasInstantPreviewTrackedPoseDriver =
                    gameObject.GetComponent<InstantPreviewTrackedPoseDriver>() != null;
                if (!hasInstantPreviewTrackedPoseDriver)
                {
                    gameObject.AddComponent<InstantPreviewTrackedPoseDriver>();
                }
            }
        }

        private static string GetAdbPath()
        {
            string sdkRoot = null;
#if UNITY_EDITOR
            // Gets adb path and starts instant preview server.
            sdkRoot = UnityEditor.EditorPrefs.GetString("AndroidSdkRoot");
#endif // UNITY_EDITOR

            if (string.IsNullOrEmpty(sdkRoot))
            {
                return null;
            }

            // Gets adb path from known directory.
            var adbPath = Path.Combine(Path.GetFullPath(sdkRoot), "platform-tools" + Path.DirectorySeparatorChar + "adb");

            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                adbPath = Path.ChangeExtension(adbPath, "exe");
            }

            return adbPath;
        }

        /// <summary>
        /// Tries to install and run the Instant Preview android app.
        /// </summary>
        /// <param name="adbPath">Path to adb to use for installing.</param>
        /// <param name="localVersion">Local version of Instant Preview plugin to compare installed APK against.</param>
        /// <returns>Enumerator for coroutine that handles installation if necessary.</returns>
        private static IEnumerator InstallApkAndRunIfConnected(string adbPath, string localVersion)
        {
            string apkPath = null;

#if UNITY_EDITOR
            apkPath = UnityEditor.AssetDatabase.GUIDToAssetPath(k_ApkGuid);
#endif // !UNITY_EDITOR

            // Early outs if set to install but the apk can't be found.
            if (!File.Exists(apkPath))
            {
                Debug.LogError(
                    string.Format("Trying to install Instant Preview apk but reference to InstantPreview.apk is " +
                                  "broken. Couldn't find an asset with .meta file guid={0}", k_ApkGuid));
                yield break;
            }

            Result result = new Result();

            Thread checkAdbThread = new Thread((object obj) =>
            {
                Result res = (Result)obj;
                string output;
                string errors;

                // Gets version of installed apk.
                RunAdbCommand(adbPath, "shell dumpsys package com.google.ar.core.instantpreview | grep versionName",
                              out output, out errors);
                string installedVersion = null;
                if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(errors))
                {
                    installedVersion = output.Substring(output.IndexOf('=') + 1);
                }

                // Early outs if no device is connected.
                if (string.Compare(errors, k_NoDevicesFoundAdbResult) == 0)
                {
                    return;
                }

                // Prints errors and exits on failure.
                if (!string.IsNullOrEmpty(errors))
                {
                    Debug.LogError(errors);
                    return;
                }

                if (installedVersion == null)
                {
                    Debug.Log(string.Format(
                        "Instant Preview: app not found on device, attempting to install it from {0}.",
                        apkPath));
                }
                else if (installedVersion != localVersion)
                {
                    Debug.Log(string.Format(
                        "Instant Preview: installed version \"{0}\" does not match local version \"{1}\", attempting upgrade.",
                        installedVersion, localVersion));
                }

                res.ShouldPromptForInstall = installedVersion != localVersion;
            });
            checkAdbThread.Start(result);

            while (!checkAdbThread.Join(0))
            {
                yield return 0;
            }

            if (result.ShouldPromptForInstall)
            {
                if (PromptToInstall())
                {
                    Thread installThread = new Thread(() =>
                    {
                        string output;
                        string errors;

                        RunAdbCommand(adbPath,
                            string.Format("uninstall com.google.ar.core.instantpreview", apkPath),
                            out output, out errors);

                        RunAdbCommand(adbPath,
                            string.Format("install \"{0}\"", apkPath),
                            out output, out errors);

                        // Prints any output from trying to install.
                        if (!string.IsNullOrEmpty(output))
                        {
                            Debug.Log(output);
                        }

                        if (!string.IsNullOrEmpty(errors))
                        {
                            if (string.Equals(errors, "Success"))
                            {
                                Debug.Log("Successfully installed Instant Preview app.");
                            }
                            else
                            {
                                Debug.LogError(errors);
                            }
                        }
                    });
                    installThread.Start();

                    while (!installThread.Join(0))
                    {
                        yield return 0;
                    }
                }
                else
                {
                    yield break;
                }
            }

            if (!NativeApi.IsConnected())
            {
                string activityName = Screen.width < Screen.height ? "InstantPreviewActivity" : "InstantPreviewLandscapeActivity";
                new Thread(() =>
                {
                    string output;
                    string errors;
                    RunAdbCommand(adbPath,
                        "shell am start -n com.google.ar.core.instantpreview/." + activityName,
                        out output, out errors);
                }).Start();
            }
        }

        private static bool PromptToInstall()
        {
#if UNITY_EDITOR
            return UnityEditor.EditorUtility.DisplayDialog("Instant Preview",
                        "To instantly reflect your changes on device, the " +
                        "Instant Preview app will be installed on your " +
                        "connected phone.\n\nTo permanently disable Instant Preview, " +
                        "uncheck the InstantPreviewEnabled checkbox in Edit/Project Settings/ARCore Instant Preview Enabled.", "Okay", "Don't Install This Time");
#else
            return false;
#endif
        }

        private static void RunAdbCommand(string fileName, string arguments, out string output, out string errors)
        {
            using (var process = new System.Diagnostics.Process())
            {
                var startInfo = new System.Diagnostics.ProcessStartInfo(fileName, arguments);
                startInfo.UseShellExecute = false;
                startInfo.RedirectStandardError = true;
                startInfo.RedirectStandardOutput = true;
                startInfo.CreateNoWindow = true;
                process.StartInfo = startInfo;

                var outputBuilder = new StringBuilder();
                var errorBuilder = new StringBuilder();
                process.OutputDataReceived += (sender, ef) => outputBuilder.Append(ef.Data);
                process.ErrorDataReceived += (sender, ef) => errorBuilder.Append(ef.Data);

                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();
                process.Close();

                // Trims the output strings to make comparison easier.
                output = outputBuilder.ToString().Trim();
                errors = errorBuilder.ToString().Trim();
            }
        }

        private static bool StartServer(string adbPath, out string version)
        {
            // Tries to start server.
            const int k_InstantPreviewVersionStringMaxLength = 64;
            var versionStringBuilder = new StringBuilder(k_InstantPreviewVersionStringMaxLength);
            var started = NativeApi.InitializeInstantPreview(adbPath, versionStringBuilder,
                                                             versionStringBuilder.Capacity);
            if (!started)
            {
                Debug.LogErrorFormat("Couldn't start Instant Preview server with adb path: {0}.", adbPath);
                version = null;
                return false;
            }

            version = versionStringBuilder.ToString();
            Debug.Log("Instant Preview Version: " + version);
            return true;
        }

        private static int RoundUpToNearestMultipleOf16(int value)
        {
            return (value + 15) & ~15;
        }

        private struct NativeApi
        {
            [DllImport(InstantPreviewNativeApi)]
            public static extern bool InitializeInstantPreview(
                string adbPath, StringBuilder version, int versionStringLength);

            [DllImport(InstantPreviewNativeApi)]
            public static extern void Update();

            [DllImport(InstantPreviewNativeApi)]
            public static extern IntPtr GetRenderEventFunc();

            [DllImport(InstantPreviewNativeApi)]
            public static extern void SendFrame(IntPtr renderTexture);

            [DllImport(InstantPreviewNativeApi)]
            public static extern bool LockCameraTexture(out IntPtr pixelBytes, out int width,
                out int height);

            [DllImport(InstantPreviewNativeApi)]
            public static extern void UnlockCameraTexture();

            [DllImport(InstantPreviewNativeApi)]
            public static extern bool IsConnected();
        }

        private class Result
        {
            public bool ShouldPromptForInstall = false;
        }
    }
}


text:
fileFormatVersion: 2
guid: bf60f00878ba64ac2a641bb7b7b905f1
folderAsset: yes
timeCreated: 1518465123
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="InstantPreviewEnabledMenuItem.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCoreInternal
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using UnityEditor;
    using UnityEngine;

    [InitializeOnLoad]
    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
     Justification = "Internal")]
    public static class InstantPreviewEnabledMenuItem
    {
        private const string k_MenuName = "Edit/Project Settings/ARCore/Instant Preview Enabled";
        private const int k_MenuPriority = 902;

        [MenuItem(k_MenuName, false, k_MenuPriority)]
        private static void ToggleARCoreRequiredMenuItem()
        {
            ARCoreProjectSettings.Instance.IsInstantPreviewEnabled =
                !ARCoreProjectSettings.Instance.IsInstantPreviewEnabled;
            ARCoreProjectSettings.Instance.Save();
        }

        [MenuItem(k_MenuName, true, k_MenuPriority)]
        private static bool ValidateARCoreRequiredMenuItem()
        {
            Menu.SetChecked(k_MenuName, ARCoreProjectSettings.Instance.IsInstantPreviewEnabled);
            return true;
        }
    }
}


text:
fileFormatVersion: 2
guid: 70ba264bba46c40329f9b113916a95c8
timeCreated: 1518465123
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 42098948be8564f678777d26e6906df3
folderAsset: yes
timeCreated: 1513969093
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 3a5f7d59b4b729446a1d2a9999f62bdb
timeCreated: 1513200317
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Android: 1
        Exclude Editor: 0
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
  - first:
      Android: Android
    second:
      enabled: 0
      settings:
        CPU: ARMv7
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 1
      settings:
        CPU: x86_64
        DefaultValueInitialized: true
        OS: Windows
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Facebook: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: x86
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: LinuxUniversal
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: d80cb1919279b7348924bc747e2ada70
timeCreated: 1513200317
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Android: 1
        Exclude Editor: 0
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
  - first:
      Android: Android
    second:
      enabled: 0
      settings:
        CPU: ARMv7
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 1
      settings:
        CPU: x86_64
        DefaultValueInitialized: true
        OS: Windows
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Facebook: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: x86
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: LinuxUniversal
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 1785ef67a37b1402f8f80e1f0658e486
folderAsset: yes
timeCreated: 1515110710
licenseType: Pro
PluginImporter:
  externalObjects: {}
  serializedVersion: 2
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  isOverridable: 0
  platformData:
  - first:
      '': Any
    second:
      enabled: 0
      settings:
        Exclude Editor: 0
        Exclude Linux: 1
        Exclude Linux64: 1
        Exclude LinuxUniversal: 1
        Exclude OSXUniversal: 1
        Exclude Win: 1
        Exclude Win64: 1
  - first:
      '': OSXIntel
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      '': OSXIntel64
    second:
      enabled: 1
      settings:
        CPU: AnyCPU
  - first:
      Any:
    second:
      enabled: 0
      settings: {}
  - first:
      Editor: Editor
    second:
      enabled: 1
      settings:
        CPU: x86_64
        DefaultValueInitialized: true
        OS: OSX
  - first:
      Facebook: Win
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Facebook: Win64
    second:
      enabled: 1
      settings:
        CPU: AnyCPU
  - first:
      Standalone: Linux
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: Linux64
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: LinuxUniversal
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: OSXUniversal
    second:
      enabled: 0
      settings:
        CPU: x86_64
  - first:
      Standalone: Win
    second:
      enabled: 0
      settings:
        CPU: None
  - first:
      Standalone: Win64
    second:
      enabled: 0
      settings:
        CPU: AnyCPU
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: c22c793c4b5f447bbb532e92cb93d5ac
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 33d076be2f74340b98cb58cefe9122f7
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 27a7f7613c41541ef8517d1b5390962b
timeCreated: 1516418595
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 9a49dee3272c24e7794351bb17e92bd3
timeCreated: 1516418595
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: c10877f7cd5764de18d46d7b777d1faa
timeCreated: 1501460862
licenseType: Free
NativeFormatImporter:
  externalObjects: {}
  mainObjectFileID: 100100000
  userData:
  assetBundleName:
  assetBundleVariant:


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 1248447649449928}
  m_IsPrefabParent: 1
--- !u!1 &1248447649449928
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4461716624848968}
  - component: {fileID: 114136752755502098}
  m_Layer: 0
  m_Name: Environmental Light
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &4461716624848968
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1248447649449928}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &114136752755502098
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1248447649449928}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 92a4cf446a0c7334aaceb5457be27894, type: 3}
  m_Name:
  m_EditorClassIdentifier:


text:
fileFormatVersion: 2
guid: cf498fc35b538884db557f7a9a2c0ef9
timeCreated: 1512062703
licenseType: Pro
NativeFormatImporter:
  externalObjects: {}
  mainObjectFileID: 0
  userData:
  assetBundleName:
  assetBundleVariant:


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 1772147192650458}
  m_IsPrefabParent: 1
--- !u!1 &1637996540812124
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4497055787654456}
  - component: {fileID: 20155940112608238}
  - component: {fileID: 114963366853050710}
  - component: {fileID: 114876698896786350}
  m_Layer: 0
  m_Name: First Person Camera
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!1 &1772147192650458
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4442908887562770}
  - component: {fileID: 114451889682527732}
  m_Layer: 0
  m_Name: ARCore Device
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &4442908887562770
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1772147192650458}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  - {fileID: 4497055787654456}
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4497055787654456
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1637996540812124}
  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 4442908887562770}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!20 &20155940112608238
Camera:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1637996540812124}
  m_Enabled: 1
  serializedVersion: 2
  m_ClearFlags: 2
  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
  m_NormalizedViewPortRect:
    serializedVersion: 2
    x: 0
    y: 0
    width: 1
    height: 1
  near clip plane: 0.05
  far clip plane: 200
  field of view: 60
  orthographic: 0
  orthographic size: 5
  m_Depth: 0
  m_CullingMask:
    serializedVersion: 2
    m_Bits: 4294967295
  m_RenderingPath: -1
  m_TargetTexture: {fileID: 0}
  m_TargetDisplay: 0
  m_TargetEye: 3
  m_HDR: 1
  m_AllowMSAA: 1
  m_AllowDynamicResolution: 0
  m_ForceIntoRT: 0
  m_OcclusionCulling: 1
  m_StereoConvergence: 10
  m_StereoSeparation: 0.022
--- !u!114 &114451889682527732
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1772147192650458}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: d4ca0c6a3af6b4635b7e98c6ea0a0cf9, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  SessionConfig: {fileID: 11400000, guid: 9586a84d6c32f46b6ab7aeb6042f160d, type: 2}
--- !u!114 &114876698896786350
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1637996540812124}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: eb172c260d42e4f62945afda50892c0c, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  BackgroundMaterial: {fileID: 2100000, guid: 03ad0130a037647aeb60218f61aca114, type: 2}
--- !u!114 &114963366853050710
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1637996540812124}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 1742909100, guid: 3a84de5cd0624681b6b6dcd8921d912a, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  m_Device: 0
  m_PoseSource: 6
  m_TrackingType: 0
  m_UpdateType: 2
  m_UseRelativeTransform: 1


text:
fileFormatVersion: 2
guid: 9fc78f95b5b944e5fa1707fdc27c441a
folderAsset: yes
timeCreated: 1512755448
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 7af44c1128a614f72a62d613e2c5b61d
folderAsset: yes
timeCreated: 1512755870
licenseType: Pro
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: a49f0770e9fb042259c00241828b5858
folderAsset: yes
timeCreated: 1501206109
licenseType: Free
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: f66655b38428d40769e9e41ee237cbdc
timeCreated: 1503346684
licenseType: Free
TrueTypeFontImporter:
  externalObjects: {}
  serializedVersion: 4
  fontSize: 16
  forceTextureCase: -2
  characterSpacing: 0
  characterPadding: 1
  includeFontData: 1
  fontName: Roboto
  fontNames:
  - Roboto
  fallbackFontReferences: []
  customCharacters:
  fontRenderingMode: 0
  ascentCalculationMode: 1
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 1549424938f6d45d885684b5ac3ee149
folderAsset: yes
timeCreated: 1501723767
licenseType: Free
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 70b98779a4ac04ee98945fbc05edc737
folderAsset: yes
timeCreated: 1501206008
licenseType: Free
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 9bdaf1631fbbf45988be2a4ea863865f
folderAsset: yes
timeCreated: 1501723747
licenseType: Free
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 4d5645b79cc5e4251827ffe171ed4658
timeCreated: 1502314583
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="HelloARController.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCore.HelloAR
{
    using System.Collections.Generic;
    using GoogleARCore;
    using UnityEngine;
    using UnityEngine.Rendering;

#if UNITY_EDITOR
    // Set up touch input propagation while using Instant Preview in the editor.
    using Input = InstantPreviewInput;
#endif

    /// <summary>
    /// Controls the HelloAR example.
    /// </summary>
    public class HelloARController : MonoBehaviour
    {
        /// <summary>
        /// The first-person camera being used to render the passthrough camera image (i.e. AR background).
        /// </summary>
        public Camera FirstPersonCamera;

        /// <summary>
        /// A prefab for tracking and visualizing detected planes.
        /// </summary>
        public GameObject TrackedPlanePrefab;

        /// <summary>
        /// A model to place when a raycast from a user touch hits a plane.
        /// </summary>
        public GameObject AndyAndroidPrefab;

        /// <summary>
        /// A gameobject parenting UI for displaying the "searching for planes" snackbar.
        /// </summary>
        public GameObject SearchingForPlaneUI;

        /// <summary>
        /// A list to hold new planes ARCore began tracking in the current frame. This object is used across
        /// the application to avoid per-frame allocations.
        /// </summary>
        private List<TrackedPlane> m_NewPlanes = new List<TrackedPlane>();

        /// <summary>
        /// A list to hold all planes ARCore is tracking in the current frame. This object is used across
        /// the application to avoid per-frame allocations.
        /// </summary>
        private List<TrackedPlane> m_AllPlanes = new List<TrackedPlane>();

        /// <summary>
        /// True if the app is in the process of quitting due to an ARCore connection error, otherwise false.
        /// </summary>
        private bool m_IsQuitting = false;

        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            // Exit the app when the 'back' button is pressed.
            if (Input.GetKey(KeyCode.Escape))
            {
                Application.Quit();
            }

            _QuitOnConnectionErrors();

            // Check that motion tracking is tracking.
            if (Session.Status != SessionStatus.Tracking)
            {
                const int lostTrackingSleepTimeout = 15;
                Screen.sleepTimeout = lostTrackingSleepTimeout;
                if (!m_IsQuitting && Session.Status.IsValid())
                {
                    SearchingForPlaneUI.SetActive(true);
                }

                return;
            }

            Screen.sleepTimeout = SleepTimeout.NeverSleep;

            // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
            Session.GetTrackables<TrackedPlane>(m_NewPlanes, TrackableQueryFilter.New);
            for (int i = 0; i < m_NewPlanes.Count; i++)
            {
                // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
                // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
                // coordinates.
                GameObject planeObject = Instantiate(TrackedPlanePrefab, Vector3.zero, Quaternion.identity,
                    transform);
                planeObject.GetComponent<TrackedPlaneVisualizer>().Initialize(m_NewPlanes[i]);
            }

            // Hide snackbar when currently tracking at least one plane.
            Session.GetTrackables<TrackedPlane>(m_AllPlanes);
            bool showSearchingUI = true;
            for (int i = 0; i < m_AllPlanes.Count; i++)
            {
                if (m_AllPlanes[i].TrackingState == TrackingState.Tracking)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            SearchingForPlaneUI.SetActive(showSearchingUI);

            // If the player has not touched the screen, we are done with this update.
            Touch touch;
            if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
            {
                return;
            }

            // Raycast against the location the player touched to search for planes.
            TrackableHit hit;
            TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
                TrackableHitFlags.FeaturePointWithSurfaceNormal;

            if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
            {
                var andyObject = Instantiate(AndyAndroidPrefab, hit.Pose.position, hit.Pose.rotation);

                // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                // world evolves.
                var anchor = hit.Trackable.CreateAnchor(hit.Pose);

                // Andy should look at the camera but still be flush with the plane.
                if ((hit.Flags & TrackableHitFlags.PlaneWithinPolygon) != TrackableHitFlags.None)
                {
                    // Get the camera position and match the y-component with the hit position.
                    Vector3 cameraPositionSameY = FirstPersonCamera.transform.position;
                    cameraPositionSameY.y = hit.Pose.position.y;

                    // Have Andy look toward the camera respecting his "up" perspective, which may be from ceiling.
                    andyObject.transform.LookAt(cameraPositionSameY, andyObject.transform.up);
                }

                // Make Andy model a child of the anchor.
                andyObject.transform.parent = anchor.transform;
            }
        }

        /// <summary>
        /// Quit the application if there was a connection error for the ARCore session.
        /// </summary>
        private void _QuitOnConnectionErrors()
        {
            if (m_IsQuitting)
            {
                return;
            }

            // Quit if ARCore was unable to connect and give Unity some time for the toast to appear.
            if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
            {
                _ShowAndroidToastMessage("Camera permission is needed to run this application.");
                m_IsQuitting = true;
                Invoke("_DoQuit", 0.5f);
            }
            else if (Session.Status.IsError())
            {
                _ShowAndroidToastMessage("ARCore encountered a problem connecting.  Please start the app again.");
                m_IsQuitting = true;
                Invoke("_DoQuit", 0.5f);
            }
        }

        /// <summary>
        /// Actually quit the application.
        /// </summary>
        private void _DoQuit()
        {
            Application.Quit();
        }

        /// <summary>
        /// Show an Android toast message.
        /// </summary>
        /// <param name="message">Message string to show in the toast.</param>
        private void _ShowAndroidToastMessage(string message)
        {
            AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

            if (unityActivity != null)
            {
                AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
                unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
                {
                    AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,
                        message, 0);
                    toastObject.Call("show");
                }));
            }
        }
    }
}


text:
// <copyright file="PointcloudVisualizer.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCore.HelloAR
{
    using System.Collections.Generic;
    using GoogleARCore;
    using UnityEngine;
    using UnityEngine.Profiling;

    /// <summary>
    /// Visualize the point cloud.
    /// </summary>
    public class PointcloudVisualizer : MonoBehaviour
    {
        private const int k_MaxPointCount = 61440;

        private Mesh m_Mesh;

        private Vector3[] m_Points = new Vector3[k_MaxPointCount];

        /// <summary>
        /// Unity start.
        /// </summary>
        public void Start()
        {
            m_Mesh = GetComponent<MeshFilter>().mesh;
            m_Mesh.Clear();
        }

        /// <summary>
        /// Unity update.
        /// </summary>
        public void Update()
        {
            // Fill in the data to draw the point cloud.
            if (Frame.PointCloud.IsUpdatedThisFrame)
            {
                // Copy the point cloud points for mesh verticies.
                for (int i = 0; i < Frame.PointCloud.PointCount; i++)
                {
                    m_Points[i] = Frame.PointCloud.GetPoint(i);
                }

                // Update the mesh indicies array.
                int[] indices = new int[Frame.PointCloud.PointCount];
                for (int i = 0; i < Frame.PointCloud.PointCount; i++)
                {
                    indices[i] = i;
                }

                m_Mesh.Clear();
                m_Mesh.vertices = m_Points;
                m_Mesh.SetIndices(indices, MeshTopology.Points, 0);
            }
        }
    }
}


text:
fileFormatVersion: 2
guid: 23e3f20de6c2e405a93736a38f74b0fb
timeCreated: 1502338316
licenseType: Free
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 26074b15f9c13404d858bfedb8b8c00c
timeCreated: 1502419589
licenseType: Free
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//-----------------------------------------------------------------------
// <copyright file="TrackedPlaneVisualizer.cs" company="Google">
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------

namespace GoogleARCore.HelloAR
{
    using System.Collections.Generic;
    using GoogleARCore;
    using UnityEngine;

    /// <summary>
    /// Visualizes a TrackedPlane in the Unity scene.
    /// </summary>
    public class TrackedPlaneVisualizer : MonoBehaviour
    {
        private static int s_PlaneCount = 0;

        private readonly Color[] k_PlaneColors = new Color[]
        {
            new Color(1.0f, 1.0f, 1.0f),
            new Color(0.956f, 0.262f, 0.211f),
            new Color(0.913f, 0.117f, 0.388f),
            new Color(0.611f, 0.152f, 0.654f),
            new Color(0.403f, 0.227f, 0.717f),
            new Color(0.247f, 0.317f, 0.709f),
            new Color(0.129f, 0.588f, 0.952f),
            new Color(0.011f, 0.662f, 0.956f),
            new Color(0f, 0.737f, 0.831f),
            new Color(0f, 0.588f, 0.533f),
            new Color(0.298f, 0.686f, 0.313f),
            new Color(0.545f, 0.764f, 0.290f),
            new Color(0.803f, 0.862f, 0.223f),
            new Color(1.0f, 0.921f, 0.231f),
            new Color(1.0f, 0.756f, 0.027f)
        };

        private TrackedPlane m_TrackedPlane;

        // Keep previous frame's mesh polygon to avoid mesh update every frame.
        private List<Vector3> m_PreviousFrameMeshVertices = new List<Vector3>();
        private List<Vector3> m_MeshVertices = new List<Vector3>();
        private Vector3 m_PlaneCenter = new Vector3();

        private List<Color> m_MeshColors = new List<Color>();

        private List<int> m_MeshIndices = new List<int>();

        private Mesh m_Mesh;

        private MeshRenderer m_MeshRenderer;

        /// <summary>
        /// The Unity Awake() method.
        /// </summary>
        public void Awake()
        {
            m_Mesh = GetComponent<MeshFilter>().mesh;
            m_MeshRenderer = GetComponent<UnityEngine.MeshRenderer>();
        }

        /// <summary>
        /// The Unity Update() method.
        /// </summary>
        public void Update()
        {
            if (m_TrackedPlane == null)
            {
                return;
            }
            else if (m_TrackedPlane.SubsumedBy != null)
            {
                Destroy(gameObject);
                return;
            }
            else if (m_TrackedPlane.TrackingState != TrackingState.Tracking)
            {
                 m_MeshRenderer.enabled = false;
                 return;
            }

            m_MeshRenderer.enabled = true;

            _UpdateMeshIfNeeded();
        }

        /// <summary>
        /// Initializes the TrackedPlaneVisualizer with a TrackedPlane.
        /// </summary>
        /// <param name="plane">The plane to vizualize.</param>
        public void Initialize(TrackedPlane plane)
        {
            m_TrackedPlane = plane;
            m_MeshRenderer.material.SetColor("_GridColor", k_PlaneColors[s_PlaneCount++ % k_PlaneColors.Length]);
            m_MeshRenderer.material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));

            Update();
        }

        /// <summary>
        /// Update mesh with a list of Vector3 and plane's center position.
        /// </summary>
        private void _UpdateMeshIfNeeded()
        {
            m_TrackedPlane.GetBoundaryPolygon(m_MeshVertices);

            if (_AreVerticesListsEqual(m_PreviousFrameMeshVertices, m_MeshVertices))
            {
                return;
            }

            m_PreviousFrameMeshVertices.Clear();
            m_PreviousFrameMeshVertices.AddRange(m_MeshVertices);

            m_PlaneCenter = m_TrackedPlane.CenterPose.position;

            int planePolygonCount = m_MeshVertices.Count;

            // The following code converts a polygon to a mesh with two polygons, inner
            // polygon renders with 100% opacity and fade out to outter polygon with opacity 0%, as shown below.
            // The indices shown in the diagram are used in comments below.
            // _______________     0_______________1
            // |             |      |4___________5|
            // |             |      | |         | |
            // |             | =>   | |         | |
            // |             |      | |         | |
            // |             |      |7-----------6|
            // ---------------     3---------------2
            m_MeshColors.Clear();

            // Fill transparent color to vertices 0 to 3.
            for (int i = 0; i < planePolygonCount; ++i)
            {
                m_MeshColors.Add(Color.clear);
            }

            // Feather distance 0.2 meters.
            const float featherLength = 0.2f;

            // Feather scale over the distance between plane center and vertices.
            const float featherScale = 0.2f;

            // Add vertex 4 to 7.
            for (int i = 0; i < planePolygonCount; ++i)
            {
                Vector3 v = m_MeshVertices[i];

                // Vector from plane center to current point
                Vector3 d = v - m_PlaneCenter;

                float scale = 1.0f - Mathf.Min(featherLength / d.magnitude, featherScale);
                m_MeshVertices.Add((scale * d) + m_PlaneCenter);

                m_MeshColors.Add(Color.white);
            }

            m_MeshIndices.Clear();
            int firstOuterVertex = 0;
            int firstInnerVertex = planePolygonCount;

            // Generate triangle (4, 5, 6) and (4, 6, 7).
            for (int i = 0; i < planePolygonCount - 2; ++i)
            {
                m_MeshIndices.Add(firstInnerVertex);
                m_MeshIndices.Add(firstInnerVertex + i + 1);
                m_MeshIndices.Add(firstInnerVertex + i + 2);
            }

            // Generate triangle (0, 1, 4), (4, 1, 5), (5, 1, 2), (5, 2, 6), (6, 2, 3), (6, 3, 7)
            // (7, 3, 0), (7, 0, 4)
            for (int i = 0; i < planePolygonCount; ++i)
            {
                int outerVertex1 = firstOuterVertex + i;
                int outerVertex2 = firstOuterVertex + ((i + 1) % planePolygonCount);
                int innerVertex1 = firstInnerVertex + i;
                int innerVertex2 = firstInnerVertex + ((i + 1) % planePolygonCount);

                m_MeshIndices.Add(outerVertex1);
                m_MeshIndices.Add(outerVertex2);
                m_MeshIndices.Add(innerVertex1);

                m_MeshIndices.Add(innerVertex1);
                m_MeshIndices.Add(outerVertex2);
                m_MeshIndices.Add(innerVertex2);
            }

            m_Mesh.Clear();
            m_Mesh.SetVertices(m_MeshVertices);
            m_Mesh.SetIndices(m_MeshIndices.ToArray(), MeshTopology.Triangles, 0);
            m_Mesh.SetColors(m_MeshColors);
        }

        private bool _AreVerticesListsEqual(List<Vector3> firstList, List<Vector3> secondList)
        {
            if (firstList.Count != secondList.Count)
            {
                return false;
            }

            for (int i = 0; i < firstList.Count; i++)
            {
                if (firstList[i] != secondList[i])
                {
                    return false;
                }
            }

            return true;
        }
    }
}


text:
fileFormatVersion: 2
guid: 6a35c744e5010405c847fad90282d2be
timeCreated: 1502832523
licenseType: Pro
NativeFormatImporter:
  externalObjects: {}
  mainObjectFileID: 100100000
  userData:
  assetBundleName:
  assetBundleVariant:


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 1654175882956584}
  m_IsPrefabParent: 1
--- !u!1 &1654175882956584
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4055847820020234}
  - component: {fileID: 33340294062673050}
  - component: {fileID: 23646549736039258}
  - component: {fileID: 114776205485222536}
  m_Layer: 0
  m_Name: TrackedPlaneVisualizer
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &4055847820020234
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1654175882956584}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &23646549736039258
MeshRenderer:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1654175882956584}
  m_Enabled: 1
  m_CastShadows: 1
  m_ReceiveShadows: 1
  m_DynamicOccludee: 1
  m_MotionVectors: 1
  m_LightProbeUsage: 1
  m_ReflectionProbeUsage: 1
  m_Materials:
  - {fileID: 2100000, guid: 92b1ca249edc047509db2c7bc05789ef, type: 2}
  m_StaticBatchInfo:
    firstSubMesh: 0
    subMeshCount: 0
  m_StaticBatchRoot: {fileID: 0}
  m_ProbeAnchor: {fileID: 0}
  m_LightProbeVolumeOverride: {fileID: 0}
  m_ScaleInLightmap: 1
  m_PreserveUVs: 1
  m_IgnoreNormalsForChartDetection: 0
  m_ImportantGI: 0
  m_StitchLightmapSeams: 0
  m_SelectedEditorRenderState: 3
  m_MinimumChartSize: 4
  m_AutoUVMaxDistance: 0.5
  m_AutoUVMaxAngle: 89
  m_LightmapParameters: {fileID: 0}
  m_SortingLayerID: 0
  m_SortingLayer: 0
  m_SortingOrder: 0
--- !u!33 &33340294062673050
MeshFilter:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1654175882956584}
  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!114 &114776205485222536
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1654175882956584}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 23e3f20de6c2e405a93736a38f74b0fb, type: 3}
  m_Name:
  m_EditorClassIdentifier: