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.
Subsistem Meshing memiliki dua pertanyaan dasar:
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.
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
.
AcquireMesh
menawarkan dua cara menyediakan data mesh ke Unity: Unity-managed dan dikelola penyedia.
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
.
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);
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.
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);
}