XR SDK
Antarmuka PreInit SDK XR

SDK Sitemap

Ekstrak subsistem Meshing meshGrafik utama primitif Unity. Mesh membuat sebagian besar dunia 3D Anda. Unity mendukung mesh poligon triangulat atau Quadrangulasi. Nurbs, Nurms, permukaan Subdiv harus dikonversi ke poligon. More info
Lihat di Glossary
data dari Penyedia eksternal dan mengubahnya menjadi Login Login. Ini juga dapat menghasilkan WordPress.org opsional tanpa mengulangi kios benang utama.

Kasus penggunaan utama untuk subsistem Meshing adalah untuk jaring yang dihasilkan permukaan, umumnya dari algoritma spatial mappingProses pemetaan permukaan dunia nyata ke dunia virtual.
Lihat di Glossary
seperti yang dihasilkan dari cameraKomponen yang menciptakan gambar sudut pandang tertentu di tempat kejadian Anda. Output ditarik ke layar atau ditangkap sebagai tekstur. More info
Lihat di Glossary
kedalaman. Tidak ada batasan pada ukuran mesh, atau frekuensi pembaruan.

Generasi mesh terjadi secara serentak pada benang latar belakang, sehingga mengekstrak data dari penyedia eksternal tidak menghalangi benang utama ke, misalnya, bake mesh colliderBentuk tak terlihat yang digunakan untuk menangani tabrakan fisik untuk objek. Seorang sari tidak perlu menjadi bentuk yang sama dengan jala objek - perkiraan kasar sering lebih efisien dan tidak dapat dibedakan dalam gameplay. More info
Lihat di Glossary
.

Aliran kontrol

Subsistem Meshing memiliki dua pertanyaan dasar:

  • Dapatkan keadaan semua jaring yang dilacak (misalnya, Baru, Berubah, Tidak berubah, Dihapus).
  • Hasilkan mesh tertentu. Mesh diidentifikasi menggunakan pengidentifikasi MeshId.

Getting MeshInfos

C# pengguna bisa mendapatkan info mesh dari metode instance XRMeshSubsystem:

public bool TryGetMeshInfos(List<MeshInfo> meshInfosOut);

Peta ini langsung ke panggilan C ke UnityXRMeshProvider::GetMeshInfos dan biasanya disebut sekali per bingkai untuk mendapatkan daftar saat ini dari jaring yang dilacak.

Implementasi C berikut dapat menggunakan objek allocator yang disediakan untuk mengalokasikan array UnityXRMeshInfo yang harus diisi kemudian:

UnitySubsystemErrorCode(UNITY_INTERFACE_API * GetMeshInfos)(
        UnitySubsystemHandle handle, void* pluginData, UnityXRMeshInfoAllocator * allocator);

Memori yang dialokasikan dimiliki oleh Unity (biasanya menggunakan aokator stack, sehingga alokasi sangat cepat):

typedef struct UnityXRMeshInfo
{
    UnityXRMeshId meshId;
    bool updated;
    int priorityHint;
} UnityXRMeshInfo;

Jika tidak ada yang berubah karena panggilan terakhir ke TryGetMeshInfos, Anda dapat mengembalikan palsu untuk menghindari mengisi array setiap bingkai.

Field Description
meshId Pengidentifikasi unik 128-bit. Penyedia menghasilkan nilai-nilai ini, yang dapat menjadi pointer untuk data mesh, tetapi Anda perlu dapat menghasilkan mesh tertentu oleh IDnya.
updated Satu-satunya kebutuhan Unity adalah apakah mesh telah diperbarui sejak waktu terakhir itu dihasilkan. Menentukan apakah mesh ditambahkan atau dihapus dilakukan secara otomatis; melaporkan keberadaan jala yang Unity tidak tahu tentang di permukaan seperti Ditambahkan, sementara tidak melaporkan jala yang sebelumnya dilaporkan menandai mesh sebagai Hapus.
priorityHint C # menafsirkan nilai ini, tetapi Anda mungkin ingin, misalnya, menyediakan komponen C # yang memprioritaskan mesh mana yang menghasilkan berdasarkannya. Unity tidak menggunakan nilai ini.

Di C#, TryGetMeshInfos menempati List<MeshInfo>, yang mencakup keadaan jala:

public enum MeshChangeState
{
    Added,
    Updated,
    Removed,
    Unchanged
}

Berdasarkan keadaan perubahan jala dan nilai petunjuk prioritas, komponen C# kemudian dapat memutuskan mesh mana (es) untuk menghasilkan berikutnya.

Generasi Mesh

Dari C #, Anda dapat menghasilkan asynchronous mesh tertentu menggunakan metode instance XRMeshSubsystem:

public extern void GenerateMeshAsync(
    MeshId meshId,
    Mesh mesh,
    MeshCollider meshCollider,
    MeshVertexAttributes attributes,
    Action<MeshGenerationResult> onMeshGenerationComplete);

Ini mempesona mesh untuk generasi. Anda dapat mempesona sebanyak yang Anda butuhkan, tetapi Anda mungkin ingin membatasi jumlah jala yang dihasilkan secara bersamaan dengan beberapa saat.

Unity selalu memanggil delegate onMeshGenerationComplete yang diberikan, bahkan jika kesalahan terjadi.

Mesh dihasilkan dalam dua fase, berikut model pengakuisisi dan rilis:

UnitySubsystemErrorCode(UNITY_INTERFACE_API * AcquireMesh)(
    UnitySubsystemHandle handle,
    void* pluginData,
    const UnityXRMeshId * meshId,
    UnityXRMeshDataAllocator * allocator);

AcquireMesh disebut pada benang latar belakang, sehingga Anda dapat melakukan banyak pemrosesan dalam metode ini seperti yang Anda suka, termasuk pekerjaan intensif perhitungan seperti menghasilkan mesh itu sendiri. Fungsi ini dapat kembali segera atau rentang beberapa bingkai.

Jika Anda menyediakan struktur percepatan MeshCollider, Unity juga menghitung struktur percepatan MeshCollider (“Bake Fisika” dalam diagram di atas). Ini dapat memakan waktu untuk jala besar, sehingga juga terjadi pada benang pekerja.GenerateMeshAsync, Unity also computes the MeshCollider’s acceleration structure (“Bake Physics” in the above diagram). This can be time-consuming for large meshes, so it also occurs on the worker thread.

Akhirnya, ketika data siap, Unity menulisnya ke UnityEngine.Mesh dan / atau UnityEngine.MeshCollider pada benang utama. Setelah itu, panggilan Unity ReleaseMesh, juga pada benang utama:

UnitySubsystemErrorCode(UNITY_INTERFACE_API * ReleaseMesh)(
    UnitySubsystemHandle handle,
    void* pluginData,
    const UnityXRMeshId * meshId,
    const UnityXRMeshDescriptor * mesh,
    void* userData);

KarenaReleaseMesh disebut pada benang utama, harus kembali dengan cepat. Biasanya, ini digunakan untuk sumber daya gratis yang dialokasikan selama AcquireMesh.

Manajemen memori

AcquireMesh menawarkan dua cara menyediakan data mesh ke Unity: Unity-managed dan dikelola penyedia.

Memori yang dikelola oleh Unity

Untuk membiarkan Unity mengelola memori, gunakan:

UnityXRMeshDescriptor* (UNITY_INTERFACE_API * MeshDataAllocator_AllocateMesh)(
    UnityXRMeshDataAllocator * allocator,
    size_t vertexCount,
    size_t indexCount,
    UnityXRIndexFormat indexFormat,
    UnityXRMeshVertexAttributeFlags attributes,
    UnityXRMeshTopology topology);

Ini mengembalikan struct dengan pointer untuk penyangga berdasarkan persimpangan attributes ini dan atribut vertex yang diminta dari C#. Penyedia kemudian harus menyalin data yang sesuai untuk penyangga.

Ketika Anda menggunakan paradigm ini, Anda tidak harus membebaskan memori, karena Unity akan mendaur ulang memori setelah panggilan ke ReleaseMesh.

Memori yang dikelola oleh penyedia

Alih-alih membiarkan Unity mengelola memori, Anda dapat menunjukkannya pada data Anda sendiri. Data harus tetap berlaku sampai ReleaseMesh disebut.

Gunakan MeshDataAllocator_SetMesh untuk memberikan UnityXRMeshDescriptor Anda sendiri yang titik pointer non-null untuk data yang valid:

void(UNITY_INTERFACE_API * MeshDataAllocator_SetMesh)(
    UnityXRMeshDataAllocator * allocator, const UnityXRMeshDescriptor * meshDescriptor);

User data

Implementasi AcquireMesh Anda dapat memanggil:

void(UNITY_INTERFACE_API * MeshDataAllocator_SetUserData)(
    UnityXRMeshDataAllocator * allocator, void* userData);

Unity melewati pointer userData kembali ke implementasi ReleaseMesh Anda. Ini sangat berguna ketika Anda menggunakan memori yang dikelola oleh penyedia.

Contoh komponen C#

void Update()
{
    if (s_MeshSubsystem.TryGetMeshInfos(s_MeshInfos))
    {
        foreach (var meshInfo in s_MeshInfos)
        {
            switch (meshInfo.ChangeState)
            {
                case MeshChangeState.Added:
                case MeshChangeState.Updated:
                    AddToQueueIfNecessary(meshInfo);
                    break;

                case MeshChangeState.Removed:
                    RaiseMeshRemoved(meshInfo.MeshId);

                    // Remove from processing queue
                    m_MeshesNeedingGeneration.Remove(meshInfo.MeshId);

                    // Destroy the GameObject
                    GameObject meshGameObject;
                    if (meshIdToGameObjectMap.TryGetValue(meshInfo.MeshId, out meshGameObject))
                    {
                        Destroy(meshGameObject);
                        meshIdToGameObjectMap.Remove(meshInfo.MeshId);
                    }

                    break;

                default:
                    break;
            }
        }
    }

    // ...

    while (m_MeshesBeingGenerated.Count < meshQueueSize && m_MeshesNeedingGeneration.Count > 0)
    {
        // Get the next mesh to generate. Could be based on the mesh's
        // priorityHint, whether it is new vs updated, etc.
        var meshId = GetNextMeshToGenerate();

        // Gather the necessary Unity objects for the generation request
        var meshGameObject = GetOrCreateGameObjectForMesh(meshId);
        var meshCollider = meshGameObject.GetComponent<MeshCollider>();
        var mesh = meshGameObject.GetComponent<MeshFilter>().mesh;
        var meshAttributes = shouldComputeNormals ? MeshVertexAttributes.Normals : MeshVertexAttributes.None;

        // Request generation
        s_MeshSubsystem.GenerateMeshAsync(meshId, mesh, meshCollider, meshAttributes, OnMeshGenerated);

        // Update internal state
        m_MeshesBeingGenerated.Add(meshId, m_MeshesNeedingGeneration[meshId]);
        m_MeshesNeedingGeneration.Remove(meshId);
    }
}

void OnMeshGenerated(MeshGenerationResult result)
{
    if (result.Status != MeshGenerationStatus.Success)
    {
        // Handle error, regenerate, etc.
    }

    m_MeshesBeingGenerated.Remove(result.MeshId);
}
XR SDK
Antarmuka PreInit SDK XR