Search Unity

3D Space difference between Android & IOS / Proper position and rotation of Gameobjects in 3D Space

Discussion in 'Scripting' started by GKotlidas, Oct 19, 2018.

  1. GKotlidas

    GKotlidas

    Joined:
    Jul 28, 2012
    Posts:
    5
    Greetings to the Community :)

    Usually i prefer to keep going until i found a solution to a coding / programming problem of mine, BUT as this problem already took me almost 3 months and i am on dead-end, i would like to ask help from the Community.

    First of all what is this about:

    I am making a AR Application that is uses the Vuforia SDK (only for the Camera Input) and i am placing Markers (Pins) in the Unity3D's World Space that they are fetched from a database through an API.

    Each marker it has GPS Based, Latitude, Longitude, and also Altitude as this a Application that is made for Placing AR Markers in top of Mountains.

    To be able to put the Markers in the 3D Space i am calculating their position by getting the Difference (Distance) from the Marker's GPS to the User's current location GPS and calculating the distance between them for each Axis Seperate.

    As an a example: Marker #1 its 100 meters in front of User's current location and 50 meters left of the user and 30 meters higher than the the user.

    So i do this for each marker and i am putting the Markers in the 3D Space and up to this point everything seems to be working inside Unity3D's Editor.

    The problems:

    1) There is a Difference in the Scene's 3D Space based on Application Launch between IOS and Android.

    The 3D Space inside the Scene in Android is always constant if you launch the app it doesn't matter where you are facing, if you are facing North or South or West or East.

    In Android always, Unity 3D Space's North is the Same like the Real North, they have a difference, but its always constant and it doesn't depend of how you launched the application.

    In IOS the Unity 3D Space's North it depends of how you launch the Application, if you launch the application while you are holding your phone west east north or south this is the point that the Scene it will have as North..

    Can someone explain to me why is this happening, is it normal?
    And if it is normal how i can make the IOS version to have the same reaction like in the Android version so the Scene's North to be always True North ?

    -----------------------------------------------------------------------------------------------------

    2) I tried to fix the first problem so i can make the IOS version to point like the Android version but because i couldn't do it, instead i dropped and i went ahead to thoroughly test the Android version in Real Devices, Phones & Tablets in Real Places.

    What i noticed is that in the Android version that is always constant, the Scene when its loaded always has the same 3D Space and North is always at that same place, it still is a little bit off from the Real North of GPS.

    To try to fix that what i did is:

    To put all the Markers under a parent called MarkersHolder and then Rotate the Parent in Y axis by using the Compass True Heading and some Camera Offset but still the Markers are not in their correct place they are either more left or right than they supposed to be, and if ONE of them it fits exactly for any reason the others still they don't fit.

    After many tests in Real Places with Real Devices as it didn't worked at all, i went ahead and made a new Version of the Application that has some UI Buttons and Manually i am rotating the Parent of the Markers called MarkersHolder.

    I tried to put all the markers to be in their correct places just by rotating the parent and while ONE of them is in perfect place the others still are not.

    So i am thinking that the creation of the Markers and their Positioning in the 3D Space logically it is totally wrong or i am missing something that my mind can't actually grasp.

    Can someone explain me why this is happening ?

    From the moment that Unity's 3D space is working in a grid that is in meters and is 1x1 meter(s) why when i am putting the Markers in it, and i am rotating the parent not all the markers are not in the correct place but only one?

    Shouldn't be lining up all of them correctly when i am aligning one of them by myself?

    And because this is a programming problem i am also putting the code.

    Creating the Markers:


    Code (CSharp):
    1. public void CreateOrRefreshMarker(Item _item)
    2.     {
    3.         bool markerWasJustCreated = false;
    4.  
    5.         GameObject markerGO = null;
    6.  
    7.         markerGO = GetMarkerGOByID(_item.id);
    8.  
    9.         if (markerGO == null)
    10.         {
    11.             markerGO = GameObject.Instantiate(markerPrefab, Vector3.zero, Quaternion.identity, markersHolder.transform);
    12.             markerWasJustCreated = true;
    13.         }
    14.  
    15.         Category _category = GetCategoryByID(_item.category_id);
    16.         Marker _marker = markerGO.GetComponent<Marker>();
    17.         _marker.SetID(_item.id);
    18.         _marker.SetColor(ColorUtils.HexToColor(_category.color));
    19.         _marker.symbolText.text = _category.description.Substring(0, 1);
    20.         _marker.titleText.text = _item.name;
    21.  
    22.         float _distance = dist(latitude, longitude, _item.lat, _item.lng);
    23.         string _distanceText = string.Empty;
    24.  
    25.         if (_distance >= 1000)
    26.         {
    27.             _distanceText = (_distance / 1000).ToString("F2") + " Km";
    28.         }
    29.         else
    30.         {
    31.             _distanceText = _distance.ToString("F0") + "M";
    32.         }
    33.  
    34.         switch (Application.systemLanguage)
    35.         {
    36.             case SystemLanguage.English:
    37.                 _marker.detailsText.text =
    38.                     "Lat: " + _item.lat.ToString("F5") +
    39.                     " Long: " + _item.lng.ToString("F5") +
    40.                     " Alt: " + _item.height.ToString() +
    41.                     " Distance: " + _distanceText;
    42.                 if (!string.IsNullOrEmpty(_item.text_en))
    43.                 {
    44.                     _marker.shortText.text = _item.text_en;
    45.                 }
    46.                 else
    47.                 {
    48.                     _marker.ToggleShortText(false);
    49.                 }
    50.                 break;
    51.             case SystemLanguage.Spanish:
    52.                 _marker.detailsText.text =
    53.                     "Lat: " + _item.lat.ToString("F5") +
    54.                     " Long: " + _item.lng.ToString("F5") +
    55.                     " Alt: " + _item.height.ToString() +
    56.                     " Distancia: " + _distanceText;
    57.                 if (!string.IsNullOrEmpty(_item.text_es))
    58.                 {
    59.                     _marker.shortText.text = _item.text_es;
    60.                 }
    61.                 else
    62.                 {
    63.                     _marker.ToggleShortText(false);
    64.                 }
    65.                 break;
    66.             case SystemLanguage.Portuguese:
    67.                 _marker.detailsText.text =
    68.                     "Lat: " + _item.lat.ToString("F5") +
    69.                     " Long: " + _item.lng.ToString("F5") +
    70.                     " Alt: " + _item.height.ToString() +
    71.                     " Distancia: " + _distanceText;
    72.                 if (!string.IsNullOrEmpty(_item.text_pt))
    73.                 {
    74.                     _marker.shortText.text = _item.text_pt;
    75.                 }
    76.                 else
    77.                 {
    78.                     _marker.ToggleShortText(false);
    79.                 }
    80.                 break;
    81.         }
    82.  
    83.         float markerX = dist(0, _item.lng, 0, longitude);
    84.         float markerZ = dist(_item.lat, 0, latitude, 0);
    85.  
    86.         if (_item.lng < longitude)
    87.         {
    88.             // Debug.Log("_item.lng < lng for marker with id:" + _item.id.ToString());
    89.             markerX = -markerX;
    90.         }
    91.  
    92.         if (_item.lat < latitude)
    93.         {
    94.             // Debug.Log("_item.lat < lat for marker with id:" + _item.id.ToString());
    95.             markerZ = -markerZ;
    96.         }
    97.  
    98.         float markerY = _item.height - altitude;
    99.  
    100.         Vector3 markerPosition = new Vector3(markerX, markerY, markerZ); //the position of the target if unityNorth and actual geoNorth were the same
    101.  
    102.         markerGO.transform.position = markerPosition;
    103.         Vector3 relativePos = markerPosition - Vector3.zero; // target.position - transform.position;
    104.         Quaternion markerRotation = Quaternion.LookRotation(relativePos);
    105.  
    106.         markerGO.transform.rotation = markerRotation;
    107.  
    108.         float distanceClamped = Mathf.Max(Mathf.Min(_distance, markerDistanceFar), markerDistanceClose);
    109.  
    110.         float distance = Vector3.Distance(markerGO.transform.position, Vector3.zero);
    111.         float distanceAfterMoving = -1f;
    112.      
    113.         float markerScale = scaleForDistance / distance;
    114.  
    115.         if (_distance >= markerDistanceFar)
    116.         {
    117.             markerGO.transform.position = Vector3.MoveTowards(markerGO.transform.position, Vector3.zero, distance - markerDistanceFar );
    118.             distanceAfterMoving = Vector3.Distance(markerGO.transform.position, Vector3.zero);          
    119.  
    120.             // markerScale = scaleForDistanceFar / distance;
    121.         }
    122.  
    123.         if (_distance <= markerDistanceClose)
    124.         {
    125.             markerGO.transform.position = Vector3.MoveTowards(markerGO.transform.position, Vector3.zero, -(markerDistanceClose - distance));
    126.             distanceAfterMoving = Vector3.Distance(markerGO.transform.position, Vector3.zero);
    127.          
    128.             // markerScale = scaleForDistanceClose / distance;
    129.         }
    130.  
    131.         // markerGO.GetComponent<RectTransform>().localScale = new Vector3(markerScale, markerScale, markerScale);
    132.  
    133.         if (markerWasJustCreated)
    134.         {
    135.             markers.Add(markerGO);
    136.         }
    137.  
    138.         if (debugMarkers)
    139.         {
    140.             Debug.Log(
    141.                 "marked ID: " + _item.id.ToString() +
    142.                 " X: " + markerX.ToString() +
    143.                 " Y: " + markerY.ToString() +
    144.                 " Z: " + markerZ.ToString() +
    145.                 " mP: " + markerPosition.ToString() +
    146.                 " _distance: " + _distance.ToString() +
    147.                 " distance: " + distance.ToString() +
    148.                 " distanceAM: " + distanceAfterMoving.ToString() +
    149.                 " dClam: " + distanceClamped.ToString() +
    150.             ""
    151.             );
    152.         }
    153.     }
    Calculating the Distance:

    Code (CSharp):
    1.     float dist(float lat1, float lon1, float lat2, float lon2)
    2.     {  // generally used geo measurement function
    3.         var R = 6378.137; // Radius of earth in KM
    4.         var dLat = (lat2 - lat1) * Mathf.PI / 180;
    5.         var dLon = (lon2 - lon1) * Mathf.PI / 180;
    6.         var a = Mathf.Sin(dLat / 2) * Mathf.Sin(dLat / 2) +
    7.             Mathf.Cos(lat1 * Mathf.PI / 180) * Mathf.Cos(lat2 * Mathf.PI / 180) *
    8.             Mathf.Sin(dLon / 2) * Mathf.Sin(dLon / 2);
    9.         var c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1 - a));
    10.         var d = R * c;
    11.         return (float)(d * 1000); // meters
    12.     }

    Calculating Initial Compass Heading and Camera Offset:

    Code (CSharp):
    1. void OnGotDirection(float headingAccuracy, float magneticHeading, Vector3 rawVector, double timestamp, float trueHeading)
    2.     {
    3.         if (!compassInitialized)
    4.         {
    5.             if (debugEnabled)
    6.             {
    7.                 Debug.Log("Compass initializing...");
    8.             }
    9.  
    10.             float eulerAnglesY = Camera.main.transform.eulerAngles.y;
    11.  
    12.             if (compassOffset == 0 && eulerAnglesY!=0)
    13.             {
    14.                 initialEulerAnglesY = eulerAnglesY;
    15.                 Vector3 fwd = new Vector3(0, 0, 1);
    16.                 Vector3 north = Quaternion.Euler(0, trueHeading, 0) * fwd;
    17.                 compassOffset = Vector3.SignedAngle(fwd, north, Vector3.up) + (360 - eulerAnglesY);
    18.                 compassOffsetNoEuler = Vector3.SignedAngle(fwd, north, Vector3.up);
    19.             }
    20.  
    21.             initialCompassTrueHeading = trueHeading;
    22.             compassInitialized = true;
    23.         }
    24.     }
    And Rotating the parent:

    Code (CSharp):
    1. switch (markersCreationSystem)
    2.         {
    3.             case 0:              
    4.                 break;
    5.             case 1:
    6.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -initialCompassTrueHeading, 0);
    7.                 break;
    8.             case 2:
    9.                 markersHolder.transform.localRotation = Quaternion.Euler(0, initialCompassTrueHeading, 0);
    10.                 break;
    11.             case 3:
    12.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -compassOffset, 0);
    13.                 break;
    14.             case 4:
    15.                 markersHolder.transform.localRotation = Quaternion.Euler(0, compassOffset, 0);
    16.                 break;
    17.             case 5:
    18.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -compassOffsetNoEuler, 0);
    19.                 break;
    20.             case 6:
    21.                 markersHolder.transform.localRotation = Quaternion.Euler(0, compassOffsetNoEuler, 0);
    22.                 break;
    23.             case 7:
    24.                 markersHolder.transform.localRotation = Quaternion.Euler(0, - initialCompassTrueHeading - compassOffset, 0);
    25.                 break;
    26.             case 8:
    27.                 markersHolder.transform.localRotation = Quaternion.Euler(0, - (initialCompassTrueHeading - compassOffset), 0);
    28.                 break;
    29.             case 9:
    30.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading + compassOffset), 0);
    31.                 break;
    32.             case 10:
    33.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -initialCompassTrueHeading - compassOffsetNoEuler, 0);
    34.                 break;
    35.             case 11:
    36.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler), 0);
    37.                 break;
    38.             case 12:
    39.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading + compassOffsetNoEuler), 0);
    40.                 break;
    41.             case 13:
    42.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
    43.                 break;
    44.             case 14:
    45.                 markersHolder.transform.localRotation = Quaternion.Euler(0, Input.compass.trueHeading, 0);
    46.                 break;
    47.             case 15:
    48.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset - 22.5f), 0);
    49.                 break;
    50.             case 16:
    51.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset - 45.0f), 0);
    52.                 break;
    53.             case 17:
    54.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset - 90.0f), 0);
    55.                 break;
    56.             case 18:
    57.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset + 22.5f), 0);
    58.                 break;
    59.             case 19:
    60.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset + 45.0f), 0);
    61.                 break;
    62.             case 20:
    63.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffset + 90.0f), 0);
    64.                 break;
    65.             case 21:
    66.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler - 22.5f), 0);
    67.                 break;
    68.             case 22:
    69.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler - 45.0f), 0);
    70.                 break;
    71.             case 23:
    72.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler - 90.0f), 0);
    73.                 break;
    74.             case 24:
    75.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler + 22.5f), 0);
    76.                 break;
    77.             case 25:
    78.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler + 45.0f), 0);
    79.                 break;
    80.             case 26:
    81.                 markersHolder.transform.localRotation = Quaternion.Euler(0, -(initialCompassTrueHeading - compassOffsetNoEuler + 90.0f), 0);
    82.                 break;
    83.         }      

    Thank you,
    Georgios
     
  2. GKotlidas

    GKotlidas

    Joined:
    Jul 28, 2012
    Posts:
    5
    Bump !!!!
     
    Last edited: Oct 22, 2018
  3. GKotlidas

    GKotlidas

    Joined:
    Jul 28, 2012
    Posts:
    5
    Bump Again !!
     
  4. NatiMella

    NatiMella

    Joined:
    Oct 23, 2018
    Posts:
    1