AR Foundation - Align ar-object pararell to floor

i’m working with the new ar-foundation-samples and facing a problem with the ar-object rotation when i place it on a vertical plane. If i build the exactly same scene (SampleUXScene) to both platforms (iOS & Android)…so on iOS it’s working like expected (see picture “what i want”) and on Android something went wrong like on the picture “what i get”. The up-vector is facing the Camera but it rotates also around the up-vector-axis!
The same happens also placing an object on a horizontal plane!
So what’s the difference between iOS and Android? Is Android or ArCore interpreting something wrong? Because on iOS it’s working correctly! Any ideas how to fix this problem?

What i want:

What i get:

This is the code to place an object on a plane…

void Update()
    {
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);

            if (touch.phase == TouchPhase.Began)
            {
                if (m_RaycastManager.Raycast(touch.position, s_Hits, TrackableType.PlaneWithinPolygon))
                {
                    Pose hitPose = s_Hits[0].pose;
               
                    spawnedObject = Instantiate(m_PlacedPrefab, hitPose.position, hitPose.rotation);
               

                    if (onPlacedObject != null)
                    {
                        onPlacedObject();
                    }
                }
            }
        }
    }

@tdmowrer @mdurand

Try this:

spawnedObject = Instantiate(m_PlacedPrefab, hitPose.position, Quaternion.LookRotation( hitPose.rotation * Vector3.forward, Vector3.up );

Here’s we are constructing a new rotation value for spawned object orienting it by pose forward and world up vectors.

2 Likes

I’ve recently had to face the same problem and here is my solution.

I found that it actually takes 2 steps to get the picture onto the wall.

  • You need to put the picture onto the plane found by AR Foundation.

  • Then, rotate the picture so that it is parallel to the floor.

My GetWallPlacement() method finds those two rotations.

Here is my code. For the first part, replace what you have on your inner if statement (where you do the raycast) with my suggested if statement and that will call the method GetWallPlacement(…)

One difference between your example and mine, is that my prefab has positive Z at the top of the picture and it looks like you had Z+ pointing down. I think you could probably adapt that for your needs by replacing Vector3.down in my method to Vector3.up.

        if (arRaycastManager.Raycast(touchPosition, hits, TrackableType.PlaneWithinPolygon))
        {
            Pose hitPose = hits[0].pose;
            Quaternion orientation = Quaternion.identity;
            Quaternion zUp = Quaternion.identity;

            GetWallPlacement(hits[0], out orientation, out zUp);

            GameObject wallObj = Instantiate(WallObject, hitPose.position, orientation);
            wallObj.transform.rotation = zUp;
        }

    private void GetWallPlacement(ARRaycastHit _planeHit, out Quaternion orientation, out Quaternion zUp)
    {
        TrackableId planeHit_ID = _planeHit.trackableId;
        ARPlane planeHit = arPlaneManager.GetPlane(planeHit_ID);
        Vector3 planeNormal = planeHit.normal;
        orientation = Quaternion.FromToRotation(Vector3.up, planeNormal);
        Vector3 forward = _planeHit.pose.position - (_planeHit.pose.position + Vector3.down);
        zUp = Quaternion.LookRotation(forward, planeNormal);
    }
5 Likes

The solution @Markus_T provided worked for me.

1 Like