Sử dụng neo không gian địa lý để định vị nội dung trong thế giới thực trên Unity

Neo không gian địa lý là một loại neo cho phép bạn đặt nội dung 3D trong thế giới thực.

Các loại neo không gian địa lý

Có ba loại neo không gian địa lý, mỗi loại xử lý độ cao theo cách khác nhau:

  1. Cố định WGS84:
    Neo WGS84 cho phép bạn đặt nội dung 3D tại bất kỳ vĩ độ nào, kinh độ và độ cao.

  2. Neo địa hình:
    Neo địa hình cho phép bạn đặt nội dung chỉ sử dụng vĩ độ và kinh độ có độ cao so với địa hình tại vị trí đó. Độ cao được xác định tương ứng với mặt đất hoặc tầng như đã biết của VPS.

  3. Neo trên mái:
    Neo trên mái nhà cho phép bạn chỉ đặt nội dung dựa trên vĩ độ và kinh độ có độ cao so với mái nhà của một toà nhà tại vị trí đó. Cao độ được xác định tương ứng với đỉnh của một toà nhà đã biết của Streetscape Geometry. Thuộc tính này sẽ mặc định theo độ cao địa hình khi không được đặt trên một toà nhà.

WGS84 Địa hình Gắn trên sân thượng
Vị trí ngang Vĩ độ, Kinh độ Vĩ độ, Kinh độ Vĩ độ, Kinh độ
Vị trí theo chiều dọc So với độ cao WGS84 Tương ứng với mức địa hình do Google Maps xác định So với tầng mái do Google Maps xác định
Cần được giải quyết bằng máy chủ? Không

Điều kiện tiên quyết

Hãy nhớ bật API không gian địa lý trước khi tiếp tục.

Đặt neo không gian địa lý

Mỗi loại văn bản liên kết đều có các API chuyên biệt để tạo; hãy xem Các loại neo không gian địa lý để biết thêm thông tin.

Tạo liên kết từ kiểm thử nhấn

Bạn cũng có thể tạo quảng cáo cố định không gian địa lý từ một kết quả kiểm tra lượt truy cập. Sử dụng Tư thế từ kiểm thử lượt truy cập và chuyển đổi hình ảnh đó thành GeospatialPose. Hãy sử dụng thanh này để đặt bất kỳ loại neo nào trong 3 loại liên kết được mô tả.

Lấy tư thế không gian địa lý từ tư thế thực tế tăng cường

AREarthManager.Convert(Pose) cung cấp thêm một cách thức để xác định vĩ độ và kinh độ bằng cách chuyển đổi Tư thế thực tế tăng cường thành Tư thế không gian địa lý.

Tạo tư thế thực tế tăng cường từ một tư thế không gian địa lý

AREarthManager.Convert(GeospatialPose) chuyển đổi vị trí ngang, độ cao và phép quay quaternion do Trái đất chỉ định đối với khung toạ độ đông – lên – nam thành Tư thế AR tương ứng với toạ độ thế giới GL.

Chọn phương thức phù hợp với trường hợp sử dụng của bạn

Mỗi phương pháp tạo quảng cáo cố định có một số đánh đổi liên quan cần lưu ý:

  • Khi sử dụng Hình học cảnh quan đường phố, sử dụng kiểm thử nhấn để đính kèm nội dung vào toà nhà.
  • Ưu tiên neo Địa hình hoặc Gắn trên mái hơn là neo WGS84 vì chúng sử dụng giá trị độ cao do Google Maps xác định.

Xác định vĩ độ và kinh độ của một vị trí

Có ba cách để tính vĩ độ và kinh độ của một vị trí:

  • Sử dụng Nhà sáng tạo không gian địa lý để xem và tăng cường thế giới bằng nội dung 3D mà không cần phải đến một địa điểm cụ thể. Điều này cho phép bạn đặt nội dung sống động 3D một cách trực quan bằng cách sử dụng Google Maps trong Trình chỉnh sửa Unity. Vĩ độ, kinh độ, độ xoay và độ cao của nội dung sẽ được tính toán tự động cho bạn.
  • Sử dụng Google Maps
  • Sử dụng Google Earth. Lưu ý rằng việc lấy những toạ độ này bằng Google Earth, chứ không phải Google Maps, sẽ cho bạn biên độ sai số lên đến vài mét.
  • Đến vị trí thực tế

Sử dụng Google Maps

Để biết vĩ độ và kinh độ của một vị trí bằng Google Maps:

  1. Truy cập vào Google Maps trên máy tính.

  2. Điều hướng đến Lớp > Xem thêm.

  3. Thay đổi Loại bản đồ thành Vệ tinh và xóa hộp kiểm Chế độ xem hình ảnh địa cầu ở góc dưới cùng bên trái của màn hình.

    Thao tác này sẽ buộc sử dụng phối cảnh 2D và loại bỏ các lỗi có thể xảy ra từ chế độ xem 3D ở góc.

  4. Trên bản đồ, hãy nhấp chuột phải vào vị trí rồi chọn kinh độ/vĩ độ để sao chép vào bảng nhớ tạm.

Sử dụng Google Earth

Bạn có thể tính toán vĩ độ và kinh độ của vị trí từ Google Earth bằng cách nhấp vào một vị trí trong giao diện người dùng và đọc dữ liệu từ chi tiết dấu vị trí.

Để xem vĩ độ và kinh độ của một vị trí bằng Google Earth:

  1. Chuyển đến Google Earth trên máy tính.

  2. Chuyển đến trình đơn ba đường kẻ và chọn Kiểu bản đồ.

  3. Tắt nút chuyển Toà nhà 3D.

  4. Sau khi tắt nút chuyển Toà nhà 3D, hãy nhấp vào biểu tượng ghim để thêm dấu vị trí tại vị trí đã chọn.

  5. Chỉ định một dự án có chứa dấu vị trí rồi nhấp vào Lưu.

  6. Trong trường Tiêu đề của dấu vị trí, hãy nhập tên cho dấu vị trí.

  7. Nhấp vào mũi tên quay lại trong ngăn dự án, rồi chọn trình đơn More Actions (Thao tác khác).

  8. Chọn Xuất dưới dạng tệp KML trên trình đơn.

Tệp KLM báo cáo vĩ độ, kinh độ và độ cao của một dấu vị trí trong thẻ <coordinates> được phân tách bằng dấu phẩy như sau:

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

Không sử dụng vĩ độ và kinh độ trong các thẻ <LookAt> chỉ định vị trí camera chứ không phải vị trí.

Đến vị trí thực tế

Bạn có thể tính độ cao của một vị trí bằng cách đi đến đó trong thực tế và quan sát tại địa phương.

Lấy tứ phân vị xoay

GeospatialPose.EunRotation trích xuất hướng từ Tư thế không gian địa lý và xuất ra một quaternion đại diện cho ma trận xoay biến đổi vectơ từ mục tiêu thành hệ toạ độ đông-lên-bắc (EUN). X+ điểm về phía Đông, Y+ hướng lên khỏi trọng lực và Z+ điểm về phía bắc.

Neo WGS84

Neo WGS84 là một loại neo cho phép bạn đặt nội dung 3D tại bất kỳ vĩ độ, kinh độ và độ cao nào. Quảng cáo này phụ thuộc vào tư thế và hướng để đặt trong thế giới thực. Vị trí bao gồm vĩ độ, kinh độ và độ cao được chỉ định trong hệ thống toạ độ WGS84. Hướng bao gồm phép xoay quaternion.

Độ cao được báo cáo theo mét phía trên ellipsoid WGS84 tham chiếu sao cho cao độ mặt đất không phải bằng 0. Ứng dụng của bạn chịu trách nhiệm cung cấp các toạ độ này cho mỗi điểm neo được tạo.

Đặt một neo WGS84 trong thế giới thực

Xác định cao độ của một vị trí

Có một vài cách xác định cao độ của một vị trí để đặt neo:

  • Nếu vị trí của điểm neo nằm gần người dùng thì bạn có thể sử dụng cao độ tương tự với cao độ thiết bị của người dùng.
  • Sau khi bạn có vĩ độ và kinh độ, hãy sử dụng API Độ cao để nhận độ cao dựa trên thông số kỹ thuật EGM96. Bạn phải chuyển đổi độ cao EGM96 của API Maps thành WGS84 để so sánh với độ cao GeospatialPose. Hãy xem GeoidEval có cả dòng lệnh và giao diện HTML. API Maps báo cáo vĩ độ và kinh độ theo thông số kỹ thuật WGS84 ngay từ đầu.
  • Bạn có thể biết được vĩ độ, kinh độ và độ cao của một vị trí từ Google Earth. Thao tác này sẽ khiến biên độ sai số lên đến vài mét. Sử dụng vĩ độ, kinh độ và độ cao từ các thẻ <coordinates>, không phải thẻ <LookAt>, trong tệp KML.
  • Nếu một điểm neo hiện có đang ở gần nếu bạn không ở trên một đoạn dốc, bạn có thể sử dụng độ cao từ GeospatialPose của máy ảnh mà không cần sử dụng nguồn khác, chẳng hạn như API Maps.

Tạo quảng cáo cố định

Sau khi bạn có vĩ độ, kinh độ, độ cao và tứ phân vị xoay, hãy sử dụng ARAnchorManagerExtensions.AddAnchor() để neo nội dung vào các toạ độ địa lý mà bạn chỉ định.

if (earthTrackingState == TrackingState.Tracking)
{
  var anchor =
      AnchorManager.AddAnchor(
          latitude,
          longitude,
          altitude,
          quaternion);
  var anchoredAsset = Instantiate(GeospatialAssetPrefab, anchor.transform);
}

Neo địa hình

Neo địa hình là một loại neo cho phép bạn đặt các đối tượng thực tế tăng cường chỉ dựa trên vĩ độ và kinh độ, tận dụng thông tin từ VPS để tìm cao độ chính xác so với mặt đất.

Thay vì nhập cao độ mong muốn, bạn cung cấp cao độ bên trên địa hình. Khi giá trị này bằng 0, neo sẽ được cân bằng với địa hình.

Đặt chế độ tìm máy bay

Việc tìm mặt phẳng là không bắt buộc và không bắt buộc phải sử dụng neo. Lưu ý rằng chỉ sử dụng mặt phẳng ngang. Các mặt phẳng nằm ngang sẽ giúp căn chỉnh động các neo địa hình trên mặt đất.

Lưu ý rằng các neo địa hình chịu ảnh hưởng của HorizontalHorizontal | Vertical

Sử dụng trình đơn thả xuống Chế độ phát hiện để đặt chế độ phát hiện:

Tạo điểm neo Địa hình bằng API không đồng bộ mới

Để tạo và đặt điểm neo Địa hình, hãy gọi ARAnchorManagerExtensions.resolveAnchorOnTerrainAsync().

Quảng cáo cố định cuối màn hình chưa sẵn sàng ngay và cần được phân giải. Sau khi giải quyết xong, vấn đề này sẽ có trong ResolveAnchorOnTerrainPromise.

public GameObject TerrainAnchorPrefab;

public void Update()
{
    ResolveAnchorOnTerrainPromise terrainPromise =
        AnchorManager.ResolveAnchorOnTerrainAsync(
            latitude, longitude, altitudeAboveTerrain, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckTerrainPromise(terrainPromise));
}

private IEnumerator CheckTerrainPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.TerrainAnchorState == TerrainAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(TerrainAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

Kiểm tra trạng thái cam kết

Lời hứa sẽ có một PromiseState được liên kết.

Tiểu bang Mô tả
Pending Thao tác vẫn đang chờ xử lý.
Done Hoạt động đã hoàn tất và kết quả sẽ có sẵn.
Cancelled Thao tác đã bị huỷ.

Kiểm tra trạng thái neo Địa hình của kết quả Promise

TerrainAnchorState thuộc về hoạt động không đồng bộ và là một phần của kết quả Promise cuối cùng.

switch (result.TerrainAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case TerrainAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case TerrainAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case TerrainAnchorState.ErrorInternal:
        // The Terrain anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

Neo trên nóc

Hình ảnh chính về neo nóc

Neo trên nóc là một loại neo và rất giống với neo địa hình nêu trên. Sự khác biệt là bạn sẽ cung cấp cao độ phía trên mái nhà chứ không phải cao độ phía trên địa hình.

Tạo điểm neo trên Sân thượng bằng API không đồng bộ (Async API) mới

Quảng cáo cố định cuối màn hình chưa sẵn sàng ngay và cần được phân giải.

Để tạo và đặt quảng cáo cố định cuối màn hình trên sân thượng, hãy gọi ARAnchorManagerExtensions.resolveAnchorOnRooftopAsync(). Tương tự như neo Địa hình, bạn cũng sẽ truy cập vào PromiseState của Promise. Sau đó, bạn có thể kiểm tra kết quả Promise để truy cập vào RooftopAnchorState.

public GameObject RooftopAnchorPrefab;

public void Update()
{
    ResolveAnchorOnRooftopPromise rooftopPromise =
        AnchorManager.ResolveAnchorOnRooftopAsync(
            latitude, longitude, altitudeAboveRooftop, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckRooftopPromise(rooftopPromise));
}

private IEnumerator CheckRooftopPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.RooftopAnchorState == RooftopAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(RooftopAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

Kiểm tra trạng thái cam kết

Lời hứa sẽ có một PromiseState được liên kết, hãy xem bảng ở trên.

Kiểm tra trạng thái neo trên sân thượng của kết quả Promise

RooftopAnchorState thuộc về hoạt động không đồng bộ và là một phần của kết quả Promise cuối cùng.

switch (result.RooftopAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case RooftopAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case RooftopAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case RooftopAnchorState.ErrorInternal:
        // The Rooftop anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

Các bước tiếp theo