Search Unity

ARFoundation not working with Unity ECS and Graphics.DrawMesh

Discussion in 'AR' started by Srokaaa, Nov 25, 2018.

  1. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    I recently tried to use ARFoundation with new unity ECS and it doesn't render anything. Internally in ECS all the rendering is currently done in MeshInstanceRendererSystem (sources available after downloading com.unity.entities package) which is using Graphics.DrawMesh and Graphics.DrawMeshInstanced methods. I tried using those methods directly and nothing shows on the screen. As soon as I disable ARFoundation camera and switch to a regular one everything start working fine
     
    Last edited: Nov 26, 2018
  2. tdmowrer

    tdmowrer

    Joined:
    Apr 21, 2017
    Posts:
    605
    ARFoundation is designed to be used with "traditional" Unity constructs, like MonoBehaviours. However, the XR Subsystems that it talks to (e.g., XRPlaneSubsystem for plane detection) deal in plain old data for the most part. ARFoundation's ARPlaneMeshVisualizer component uses the static method ARPlaneMeshGenerators.GenerateMesh to generate a mesh from the plane's boundary points. You can pass the generated mesh to Graphics.DrawMesh if using ECS.
     
  3. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    @tdmowrer Thanks for a quick answer but my problem is something opposite. I don't mind ARFoundation using MonoBehaviours, ECS provides a nice "Hybrid" way of dealing with it and I am easily able to access ARFoundation components from within systems. The problem is Graphics.DrawMesh not rendering at all, even if I use it without ECS. My guess is that whatever I draw using Graphics.DrawMesh is beign drawn over by ARFoundation.
     
  4. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    Uh, I actually got it working on ARFoundation Samples and I am able to draw a mesh using Graphics.DrawMesh there. I'll try to dig deeper to see what can be the cause in my project
     
  5. tdmowrer

    tdmowrer

    Joined:
    Apr 21, 2017
    Posts:
    605
    Okay, let me know if you are able to get to the bottom of it. Would be good to know.
     
  6. Srokaaa

    Srokaaa

    Joined:
    Sep 18, 2018
    Posts:
    169
    Sorry for late answer. I got it working finally and the cause was not in ARFoundation but IL2CPP stripping ECS classes. Here is the link to a discussion about that: https://forum.unity.com/threads/meshinstancerenderer-not-rendering-on-ios.591703/#post-3952090

    Otherwise I find them working really well with each other. I just have some "Input" systems where I get all the data I need from ARFoundation and write it to any entities that need it:


    Code (CSharp):
    1.     public class ArInputSystem : JobComponentSystem
    2.     {
    3.         private ComponentGroup _arOriginComponentGroup;
    4.         private ComponentGroup _editorCamera;
    5.         private ComponentGroup _arInputComponentGroup;
    6.  
    7.         private List<ARRaycastHit> cachedRaycastHits = new List<ARRaycastHit>();
    8.         private List<ARRaycastHit> newRaycastHits    = new List<ARRaycastHit>();
    9.  
    10.         protected override void OnCreateManager()
    11.         {
    12.             _arOriginComponentGroup = GetComponentGroup(typeof(ARSessionOrigin));
    13.             _editorCamera = GetComponentGroup(typeof(UnityEngine.Camera),
    14.                 ComponentType.Subtractive<ARCameraBackground>());
    15.             _arInputComponentGroup = GetComponentGroup(typeof(ArInputComponent));
    16.         }
    17.  
    18.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    19.         {
    20.             //This duplicates write job but is necessary if we don't want to raycast needlessly.
    21.             if (_arInputComponentGroup.GetComponentDataArray<ArInputComponent>().Length <= 0) return inputDeps;
    22.  
    23.             var arSessionOrigins = _arOriginComponentGroup.GetComponentArray<ARSessionOrigin>();
    24.             var editorCameraArray = _editorCamera.GetComponentArray<UnityEngine.Camera>();
    25.  
    26.             if (arSessionOrigins.Length > 0)
    27.             {
    28.                 var arSessionOrigin = arSessionOrigins[0];
    29.                 if (arSessionOrigin.Raycast(new Vector3(Screen.width * 0.5f, Screen.height * 0.5f),
    30.                     newRaycastHits,
    31.                     TrackableType.Planes))
    32.  
    33.                 {
    34.                     var firstHit = newRaycastHits[0];
    35.                     cachedRaycastHits.Clear();
    36.                     cachedRaycastHits.AddRange(newRaycastHits);
    37.  
    38.                     return new WriteArInputJob
    39.                     {
    40.                         ArPlaneNormal   = firstHit.pose.forward,
    41.                         ArPlaneHitPoint = firstHit.pose.position,
    42.                         Hit             = true
    43.                     }.Schedule(this, inputDeps);
    44.                 }
    45.  
    46.                 if (cachedRaycastHits.Count > 0)
    47.                 {
    48.                     var firstHit = newRaycastHits[0];
    49.                     return new WriteArInputJob
    50.                     {
    51.                         ArPlaneNormal   = firstHit.pose.forward,
    52.                         ArPlaneHitPoint = firstHit.pose.position,
    53.                         Hit             = false
    54.                     }.Schedule(this, inputDeps);
    55.                 }
    56.             }
    57.  
    58.             if (editorCameraArray.Length > 0)
    59.             {
    60.                 var ray = editorCameraArray[0].ScreenPointToRay(Input.mousePosition);
    61.                 var direction = ray.direction;
    62.                 var origin = ray.origin;
    63.                 var intersectionPoint =
    64.                     GeometryUtils.IntersectPoint(direction,
    65.                         origin,
    66.                         up(),
    67.                         new float3(0.0f, 0.0f, 0.0f));
    68.  
    69.                 return new WriteArInputJob
    70.                 {
    71.                     ArPlaneNormal   = up(),
    72.                     ArPlaneHitPoint = intersectionPoint,
    73.                     Hit             = true
    74.                 }.Schedule(this, inputDeps);
    75.             }
    76.  
    77.             return new WriteArInputJob
    78.             {
    79.                 ArPlaneNormal   = up(),
    80.                 ArPlaneHitPoint = zero,
    81.                 Hit             = false
    82.             }.Schedule(this, inputDeps);
    83.         }
    84.  
    85.         private struct WriteArInputJob : IJobProcessComponentData<ArInputComponent>
    86.         {
    87.             [ReadOnly] public float3 ArPlaneNormal;
    88.             [ReadOnly] public float3 ArPlaneHitPoint;
    89.             [ReadOnly] public bool   Hit;
    90.  
    91.             public void Execute([WriteOnly] ref ArInputComponent data)
    92.             {
    93.                 data.ArPlaneNormal   = ArPlaneNormal;
    94.                 data.ArPlaneHitPoint = ArPlaneHitPoint;
    95.                 data.Hit             = Hit;
    96.             }
    97.         }
    98.     }
    99.  
    It would be nice to have ARFoundation version of https://docs.unity3d.com/ScriptReference/RaycastCommand.html so we can schedule everything on the Jobs and not wait for it to finish on a Main Thread.
     
    Last edited: Dec 4, 2018