google-ar / arcore-unity-sdk

ARCore SDK for Unity
https://developers.google.com/ar
Other
1.4k stars 402 forks source link

Hit test API did not take into account hit flag PlaneWithinInfinity #334

Open wangvnn opened 6 years ago

wangvnn commented 6 years ago

I am using Frame.RaycastAll to find all the planes that are intersected with the ray from the center all the screen. I use TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinInfinity; The problem is internally this: ExternApi.ArFrame_hitTest(m_NativeSession.SessionHandle, frameHandle, x, y, hitResultListHandle); sometimes does not return all the valid planes. For example: plan1 is closer and plane 2 is further. Sometimes the API only return plane1, instead of returning both (both are valid result) It looks like internally the API did not use the flag PlaneWithinInfinity, because If plane2 is big enough to cover the area underneath plane1, then the API returns the correct result (2 planes) otherwise it will return 1 plane only.

pablisho commented 6 years ago

Hi, thanks for the report. I cannot reproduce your issue. Using PlaneWithinInfinity does not guarantee that all planes will be hit. Only planes that would intersect if they were infinitely big will be hit. In a 3D environment this is not always true. Let me know if this helps or if you still experience this issue with planes that should be clearly be hit.

wangvnn commented 6 years ago

I added image for clarification: https://ibb.co/mwsXAe

As you can see it works on the top image, it does not work well on the bottom image. I have 4 planes (1,2,3,4), I cast a ray from camera (6) and detect all the hits and display the reticle (5) on the lowest plane. In the top image, it returns 4 hit planes (1,2,3,4), and in the bottom image it returns 1 hit planes only (3).

NOTE: plane 3 is a book on my table, 2 is my table, 1,4 is the floor planes that have not been merged yet.

I use this code: List hits = new List(); TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinInfinity; if (Frame.RaycastAll(Screen.width / 2, Screen.height / 2, raycastFilter, hits)) { ....... }

I trace the code until: HitTestApi.cs

    public static bool RaycastAll(float x, float y, TrackableHitFlags filter, List<TrackableHit> hitResults)
    {
        hitResults.Clear();
        var nativeSession = LifecycleManager.Instance.NativeSession;
        if (nativeSession == null)
        {
            return false;
        }

        return nativeSession.HitTestApi.Raycast(nativeSession.FrameHandle, x, Screen.height - y, filter, hitResults, true);
    }

And

public bool Raycast(IntPtr frameHandle, float x, float y, TrackableHitFlags filter, List outHitList, bool isOnlyQueryingNearestHit) { outHitList.Clear();

        IntPtr hitResultListHandle = IntPtr.Zero;
        ExternApi.ArHitResultList_create(m_NativeSession.SessionHandle, ref hitResultListHandle);
        ExternApi.ArFrame_hitTest(m_NativeSession.SessionHandle, frameHandle, x, y, hitResultListHandle);

        int hitListSize = 0;
        ExternApi.ArHitResultList_getSize(m_NativeSession.SessionHandle, hitResultListHandle, ref hitListSize);

        for (int i = 0; i < hitListSize; i++)
        {
            TrackableHit trackableHit;
            if (HitResultListGetItemAt(hitResultListHandle, i, out trackableHit))
            {
                if ((filter & trackableHit.Flags) != TrackableHitFlags.None)
                {
                    outHitList.Add(trackableHit);
                }
            }
        }

        ExternApi.ArHitResultList_destroy(hitResultListHandle);
        return outHitList.Count != 0;
    }

And it looks like the result returned from hit test API is wrong. I also notice at this line: ExternApi.ArFrame_hitTest(m_NativeSession.SessionHandle, frameHandle, x, y, hitResultListHandle);

The code does not pass in any hit flag param, so I assume internally the API would do ray cast with all infinite planes. But it does not seem to work that way.

pablisho commented 6 years ago

Hi, thanks for reporting this. Looking further into it, we are only hitting against planes of 2x the current size instead of infinite planes. I added it to our internal tracker to fix it for next releases.

wangvnn commented 6 years ago

Great. Btw, do you have information about the next release (date, fixes, improvements...) ?

pablisho commented 6 years ago

Unfortunately I cannot share any timelines. But we do add the "fixed in upcoming release" tag to issues when a bug is fixed for the next release.

Nishanth14 commented 5 years ago

@pablisho Any update on when we can expect the fix for 'PlaneWithinInfinity' or do you suggest any workaround for this.

Thanks!

ziemlich3DPeter commented 5 years ago

@pablisho Found this issue by searching with Google. So I'm not 100% sure if this is the right place: I'm also facing this problem within my current project using ARCore XR Plugin 1.0.0 preview 24 from the Unity Package Manager. Did your team already fix this in ARCore, or is Unity's package not up to date?