XGRIDSDokumentation
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • Lixel PortalCam-Serie

    • PortalCam P1

      • Produktübersicht
      • Grundlegende Bedienung
      • LCC Scan App verwenden
      • Wartung und Pflege
      • FAQ
  • Lixel K-Serie

    • Lixel K1

      • Produktübersicht
      • Grundlegende Bedienung
      • Geräteaktivierung und -verbindung
      • Scan-Workflow
      • Punktwolke mit absoluten Koordinaten erfassen
      • Kartenfusion
      • Empfehlungen zur Routenplanung für typische Szenen
      • Hinweise
      • FAQ
    • Lixel K2

      • Produktübersicht
      • Grundlegende Bedienung
      • Aktivierung und Verbindung
      • Scan-Workflow
      • Punktwolke mit absoluten Koordinaten erfassen
      • Kartenfusion
      • Empfehlungen zur Routenplanung für typische Szenen
      • Hinweise
      • FAQ
  • Lixel L-Serie

    • Lixel L2 Pro

      • Produktübersicht
      • Grundlegende Bedienung
      • Geräteaktivierung und -verbindung
      • Scan-Workflow
      • Punktwolke mit absoluten Koordinaten erfassen
      • Messpunkt
      • Anhang
      • FAQ
    • Lixel L3

      • Produktübersicht
      • Grundlegende Bedienung
      • Aktivierung und Verbindung
      • Scan-Workflow
      • Punktwolke mit absoluten Koordinaten erfassen
      • Anhang
  • Zubehör

    • Stick Light

      • Installationsanleitung
      • Grundlegende Bedienung
      • Häufige Fragen
  • Lixel Studio

    • Version und Copyright
    • Installation und Aktivierung
    • Softwareoberfläche
    • Dateioperationen
    • Projektverarbeitung
    • Werkzeuge
    • 2D-Zeichnung
    • Anwendungen
    • Einstellungen
    • Geräteverbindung
    • Häufige Fragen
  • Lixel CyberColor

    • LCC Studio

      • Erste Schritte
      • Version und Updates
      • Download und Installation
      • Oberfläche und Navigation
      • Vor der Rekonstruktion
      • Modellrekonstruktion
      • Einzelmodell-Rekonstruktion
      • Kartenfusion
      • Boden-Luft-Fusion
      • Luftbild-Rekonstruktion
      • Meine Modelle
      • Weitere Funktionen
      • Einstellungen und Konto
      • Converter
      • Videorekonstruktion
      • Häufige Fragen / FAQ
    • LCC Scene Editor

      • Version und Updates
      • Konto und Anmeldung
      • Produktübersicht und Startseite
      • Editor-Oberfläche
      • Navigationsmodi
      • Datei
      • Einstellungen
      • Bearbeiten
      • Fenster
      • Globale Symbolleiste
      • Assets und Eigenschaften
      • Linke Symbolleiste
      • Ansichtspunkte
      • Portal
      • Skybox
      • Markierungen
      • Messung
      • Flythrough
      • Szenenbericht
      • 3D-Layout
      • Minikarte
      • Vorschaumodus (Viewer)
      • Hilfe
      • Häufige Fragen (FAQ)
      • Spawn-Point
    • LCC Model Editor

      • Version und Updates
      • Benutzerhandbuch
      • Übersicht und Oberfläche
      • Dateioperationen
      • Selektoren
      • Modelle bearbeiten
      • Messung
      • Farbkorrektur
      • Asset-Verwaltung
      • Einstellungen und Hilfe
      • Häufige Fragen
    • Capture Guide

      • Überblick
      • Überblick über die Aufnahmegeräte
      • Allgemeine Aufnahmeprinzipien
      • Aufnahme von Innenszenen
      • Aufnahme von Außenszenen
      • Großflächige Aufnahme (Map Fusion)
      • Aerial-Ground Map Fusion – Aufnahme
      • Objektaufnahme
      • Personenaufnahme
      • Video-Rekonstruktionsaufnahme
      • HD Enhancement
      • Kontrollpunkte (Lixel P1)
      • FAQ und Fehlerbehebung
    • Best Practices

      • Zusammenführen mehrerer großer 3DGS-Modelle
    • Versionsgeschichte
  • Plugin & SDK

    • Unreal

      • Einführung
      • Schnellstart - Windows
      • Schnellstart - Linux
      • Schnellstart - Quest3
      • Editionen und Lizenzierung
      • Rendering
      • Tiled-Rasterisierung (experimentell)
      • Bildeinstellungen
      • Normalen und Beleuchtung
      • Szenenbearbeitung
      • Leistungsparameter
      • Leitfaden zur Leistung
      • Integration von Drittanbieter- und Engine-Plugins
      • Proxy Mesh
      • Ladeanimation
      • Kollision
      • Unterstützung des Navigation System
      • Unterstützung von Single Layer Water
      • Lokalisierung
      • FAQ
      • Fehlerbehebung
      • Logs und Diagnose
      • Kontakt
      • Bewährte Vorgehensweisen

        • 3DGS mit einem LixelStudio-Mesh neu beleuchten
      • API-Referenz

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • SOG- / SPZ- / PLY-Actors
        • ALCC2ProxyMesh
        • ALCCClippingVolume
        • ALCCSectionPlane
        • ALCCLoadVolume
        • ULCCUtilLibrary
        • Enums
        • Structs
      • Änderungsprotokoll

        • v3.4.0
        • v3.3.1
        • v3.0.0
        • v2.2.1
        • v1.0.0
        • v0.9.0
        • v0.8.0
        • v0.7.1
        • v0.6.1
        • v0.5.2
        • v0.4.1
        • v0.4.0
        • v0.3.0
        • v0.0.5
        • v0.0.4
        • v0.0.3
        • v0.0.2
        • v0.0.1
    • Unity

      • Einführung in das Unity SDK
      • Technische Funktionen
      • Anforderungen an die Entwicklungsumgebung
      • PC-Schnellstartanleitung
      • Leitfaden zur Optimierung der Projekteinstellungen
      • Pico 4 Ultra-Entwicklungsanleitung
      • Pico 4 Ultra-PC-Streaming-Anleitung
      • Quest 3-Entwicklungsanleitung
      • Quest 3-PC-Streaming-Anleitung
      • OpenXR-Entwicklungsanleitung
      • Pico 4 Ultra-Business-Streaming-Anleitung
      • Glossar
      • FAQ
      • Kontakt
      • Funktionsentwicklungsleitfaden

        • Entwicklungsanleitung für gemischtes Multi-Szenen-Rendering
        • Entwicklungsanleitung für Schattenempfang
        • Entwicklungsanleitung für Echtzeitbeleuchtung
        • Entwicklungsanleitung für Multi-Kamera-Rendering
        • Entwicklungsanleitung für hochauflösendes Bild-Rendering
        • Entwicklungsanleitung zur Kompatibilität der Datenformate LCC und LCC2
        • Entwicklungsanleitung für Ladeeffekte
        • Entwicklungsanleitung für das Umschalten des Mip-Rendering-Modus
        • Entwicklungsanleitung für Kanten- und Eckensnapping
        • Entwicklungsanleitung für projizierte Decals
        • Entwicklungsanleitung für projizierte Video-Decals
        • Entwicklungsanleitung für Hervorhebung
        • Entwicklungsanleitung für Echtzeit-Clipping
        • Entwicklungsanleitung für Farbanpassung
        • Entwicklungsanleitung für das Abrufen von Szenen-Mesh-Daten
        • Entwicklungsanleitung für den Editor-Modus
        • Konfigurationsanleitung für Render-Leistungsparameter
        • Entwicklungsanleitung zum gemeinsamen Paketieren von Anwendung und Daten
        • Entwicklungsanleitung für das Kollisionssystem
        • Anleitung zu macOS-Berechtigungsproblemen in der Entwicklung
        • Entwicklungsanleitung für Kompilierung und Paketierung auf iOS-Geräten
      • API-Referenz

        • LCCManager
        • Renderer
        • Datentypen
      • Changelog

        • v2.3.0
        • v2.2.10
        • v2.2.0
        • v2.1.19
        • v2.0.14
    • Web

      • Einführung
      • Leitfaden zur Rendering-Leistungsoptimierung
      • Grafikkonfiguration
      • Häufige Fragen
      • API-Referenz

        • LCCRender::clearIndexDB
        • LCCRender::dispose
        • LCCRender::load
        • LCCRender::setCamera
        • LCCRender::unload
        • LCCRender::update
        • LCCObject::checkRenderNextFrame
        • LCCObject::clearRenderNextFrame
        • LCCObject::ecef2Prj
        • LCCObject::getBounds
        • LCCObject::getEnvInstancedMesh
        • LCCObject::getInstancedMesh
        • LCCObject::getLodInfos
        • LCCObject::getOriginPosition
        • LCCObject::getProjectionCoordinateSystemInfos
        • LCCObject::hasCollision
        • LCCObject::hasEnvironment
        • LCCObject::hasShcoef
        • LCCObject::intersectsCapsule
        • LCCObject::intersectsRayExt
        • LCCObject::intersectsRayFromOriginExt
        • LCCObject::intersectsSphere
        • LCCObject::lowerToBottom
        • LCCObject::prj2Ecef
        • LCCObject::raiseToTop
        • LCCObject::raycast
        • LCCObject::raycastFromOrigin
        • LCCObject::setAlpha
        • LCCObject::setClipBox
        • LCCObject::setClipPlane
        • LCCObject::setEndLod
        • LCCObject::setLodAutoLevelUp
        • LCCObject::setMaxDistance
        • LCCObject::setMaxNodeSplats
        • LCCObject::setMaxSplats
        • LCCObject::setOriginPosition
        • LCCObject::setPointsColor
        • LCCObject::setRenderState
        • LCCObject::setRotation
        • LCCObject::setScale
        • LCCObject::setSemantic
        • LCCObject::setSemanticColor
        • LCCObject::setSmooth
        • LCCObject::setStartLod
        • LCCObject::setTranslation
        • LCCObject::setVisible
        • LCCObject::togglePointsDisplayMode
        • LCCObject::useEnvironment
        • LCCObject::useShcoef
      • Änderungsprotokoll

        • v0.6.3
        • v0.6.2
        • v0.6.1
        • v0.6.0
        • v0.5.5
        • v0.5.4
        • v0.5.3
        • v0.5.2
        • v0.5.1
        • v0.5.0
        • v0.4.1
        • v0.4.0
        • v0.3.1
        • v0.3.0
        • v0.2.0

Entwicklungsanleitung für das Abrufen von Szenen-Mesh-Daten

Bei der Rekonstruktion von LCC-Daten erzeugt das LCC Unity SDK auch Mesh-Daten, die für Kollisionen verwendet werden. Neben der Kollisionserkennung bietet das SDK die Möglichkeit, diese Mesh-Daten zu extrahieren, in Unity-Mesh-Objekte zu konvertieren und zu visualisieren, was für Szenarien wie das Exportieren und Backen von NavMesh praktisch ist.

Im Folgenden wird anhand eines vollständigen Beispiels beschrieben, wie alle Mesh-Daten synchron abgerufen und wie Mesh-Daten eines festgelegten Bereichs nach Bedarf abgerufen werden.

Umgebungseinrichtung

Erstellen Sie in Unity eine brandneue Szene. Unity erstellt standardmäßig die Hauptkamera und das Richtungslicht.

Hauptkamera einrichten

Wählen Sie die Hauptkamera im Fenster Hierarchie aus und legen Sie deren Eigenschaften im Fenster Inspektor wie unten dargestellt fest.

Die Eigenschaften der Hauptkamera festlegen

Die Eigenschaften der Hauptkamera festlegen

LCCManager erstellen

Klicken Sie mit der rechten Maustaste in einen leeren Bereich des Fensters Hierarchie, wählen Sie im Popup-Menü Leeres GameObject erstellen, um ein leeres GameObject zu erstellen, benennen Sie es LCCManager, normalisieren Sie dessen Transform und fügen Sie über Komponente hinzufügen das Skript LCCManager hinzu.

Das GameObject LCCManager erstellen und das Skript LCCManager hinzufügen

Das GameObject LCCManager erstellen und das Skript LCCManager hinzufügen

LCCRenderer erstellen

Klicken Sie mit der rechten Maustaste in einen leeren Bereich des Fensters Hierarchie, wählen Sie Leeres GameObject erstellen, um ein leeres GameObject zu erstellen, benennen Sie es LCCRenderer und setzen Sie dessen Transform auf Rotation.x = -90 und Scale.x = -1.

LCCRenderer erstellen und dessen Transform festlegen

LCCRenderer erstellen und dessen Transform festlegen (Rotation.x = -90, Scale.x = -1)

Hinweis:

Die Transform-Einstellungen des GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) richten es am LCC-Daten-Koordinatensystem aus. Details zur Ausrichtung am Koordinatensystem finden Sie unter „LCC-Daten-Koordinatensystem“ in Einführung in das Unity SDK.

Datenvoraussetzungen

Die Voraussetzung dafür, dass das Abrufen von Mesh-Daten wirksam wird, ist, dass die Szene die entsprechenden Kollisions-Mesh-Daten trägt (erzeugt, wenn LCC Studio sie rekonstruiert). Darüber hinaus gelten für diese Fähigkeit die folgenden Einschränkungen:

  • Nur PC / Mac und nur lokale Datenquellen werden unterstützt (HTTP-Datenquellen werden nicht unterstützt).
  • Kann nur im Hauptthread aufgerufen werden.
  • Daten im nativen Format (PLY / SOG / SPZ / splat / ksplat) tragen keine Kollisions-Mesh-Daten; der Aufruf der zugehörigen Methoden gibt null zurück.

In früheren Versionen rekonstruierte Daten enthalten möglicherweise keine Kollisionsdaten; in diesem Fall gibt der Aufruf von GetMeshes() null zurück.

Alle Mesh-Daten synchron abrufen

Das synchrone Abrufen aller Mesh-Daten bedeutet, die Geometriedaten aller Kollisions-Mesh-Blöcke in der Szene auf einmal zu lesen, implementiert über die Methode Renderer.GetMeshes().

Erstellen Sie ein neues C#-Skript namens Meshes.cs mit folgendem Code:

using System.Collections.Generic;
using LCCCore;
using UnityEngine;
using UnityEngine.Rendering;

public class Meshes : MonoBehaviour
{
    public LCCManager m_manager;
    public string m_FilePath;
    private LCCCore.Renderer m_renderer;
    private bool m_isLoaded = false;
    private Camera m_camera;

    private const string kContainerName = "LCCVisualizedMeshes";

    void Start()
    {
        m_camera = Camera.main;
        m_isLoaded = false;
        m_manager.SetPlatformType(PlatformType.PC);

        m_renderer = m_manager.GetRender(this.transform);
        m_renderer.Load(m_FilePath,
            p => Debug.Log($"[Meshes] Ladefortschritt: {p:P1}"),
            () =>
            {
                Debug.Log($"[Meshes] Datei geladen: {m_FilePath}");
                m_isLoaded = true;
                m_manager.SetAutoFov(false);
            },
            e => Debug.LogError($"[Meshes] Datei-Ladefehler: {e}")
        );
    }

    public void onGetAllMeshes()
    {
        if (!m_isLoaded || m_renderer == null)
        {
            Debug.LogWarning("[Meshes] Die Daten sind noch nicht fertig geladen; Meshes können nicht abgerufen werden.");
            return;
        }

        var meshes = m_renderer.GetMeshes();
        if (meshes == null || meshes.Count == 0)
        {
            Debug.LogWarning("[Meshes] Keine Meshes erhalten (die Daten enthalten möglicherweise keine Collider).");
            return;
        }

        VisualizeMeshes(meshes);
    }

    private void VisualizeMeshes(List<LCCMeshBlock> meshes)
    {
        // Das vorherige Visualisierungsergebnis bereinigen, um Anhäufung zu vermeiden
        Transform root = m_renderer.Transform;
        Transform old = root.Find(kContainerName);
        if (old != null) Destroy(old.gameObject);

        var container = new GameObject(kContainerName).transform;
        container.SetParent(root, false);

        Material material = CreateVisualMaterial();

        for (int i = 0; i < meshes.Count; i++)
        {
            LCCMeshBlock block = meshes[i];
            if (block.vertices == null || block.vertices.Length == 0) continue;
            if (block.triangles == null || block.triangles.Length < 3) continue;

            var go = new GameObject(string.IsNullOrEmpty(block.id) ? $"MeshBlock_{i}" : block.id);
            go.transform.SetParent(container, false);

            var mesh = new Mesh { name = go.name };
            // Die Vertexanzahl eines einzelnen Blocks kann 65535 überschreiten, daher müssen 32-Bit-Indizes verwendet werden, andernfalls wird die Geometrie beschädigt
            mesh.indexFormat = IndexFormat.UInt32;
            mesh.vertices = block.vertices;
            mesh.triangles = block.triangles;
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            var mf = go.AddComponent<MeshFilter>();
            mf.sharedMesh = mesh;

            var mr = go.AddComponent<MeshRenderer>();
            mr.sharedMaterial = material;
        }

        Debug.Log($"[Meshes] GameObjects erstellt und {meshes.Count} Mesh-Blöcke visualisiert.");
    }

    private Material CreateVisualMaterial()
    {
        Shader shader = Shader.Find("Universal Render Pipeline/Lit")
            ?? Shader.Find("Standard")
            ?? Shader.Find("Diffuse");
        if (shader == null) return null;

        var mat = new Material(shader) { color = new Color(0.7f, 0.7f, 0.7f, 1f) };
        // Die Wicklungsreihenfolge der Kollisions-Mesh-Dreiecke ist nicht garantiert konsistent; Rückseiten-Culling für vollständige Anzeige deaktivieren
        mat.SetFloat("_Cull", (float)CullMode.Off);
        return mat;
    }
}

Hinweis:

  • GetMeshes() ist eine synchrone schwere Operation: Sie liest synchron von der Festplatte, analysiert und weist Speicher zu. In großen Szenen, z. B. bei einem Datensatz mit 262 Blöcken, muss möglicherweise eine große Menge an Festplattendaten gelesen und mehrere GB bis mehrere zehn GB verwalteter Speicher zugewiesen werden. Rufen Sie die Methode einmal auf und cachen Sie das Ergebnis selbst; rufen Sie sie niemals in jedem Frame auf.
  • vertices / boundsLocal liegen im lokalen Koordinatensystem des Objekts, daher richtet das Anhängen des Visualisierungs-GameObject unter Renderer.Transform es automatisch aus.
  • Die Vertexanzahl eines einzelnen Blocks kann 65535 überschreiten (gemessenes Maximum 390.656); vor dem Aufbau des eigenen Mesh müssen Sie mesh.indexFormat = IndexFormat.UInt32 setzen, andernfalls wird die Geometrie beschädigt.
  • Die Wicklungsreihenfolge der Kollisions-Mesh-Dreiecke ist nicht garantiert konsistent; das Beispiel deaktiviert das Rückseiten-Culling (_Cull = Off) für die vollständige Anzeige.

Hängen Sie das Skript an das GameObject LCCRenderer, und ziehen Sie im Inspektor das GameObject LCCManager auf die Eigenschaft Manager und tragen Sie den File Path ein.

Erstellen Sie anschließend einen Button und verknüpfen Sie die Methode onGetAllMeshes() mit dessen onClick-Ereignis.

Nach dem Ausführen klicken Sie auf den Button, um alle Kollisions-Meshes in der Szene zu sehen.

Alle Mesh-Daten synchron abrufen und visualisieren

Alle Kollisions-Mesh-Daten nach dem Klicken auf den Button visualisieren

Mesh-Daten nach Bedarf abrufen

Das Abrufen nach Bedarf bedeutet, nur den angegebenen Teil der Mesh-Daten zu lesen, statt alle Mesh-Daten auf einmal zu lesen, um großen I/O- und Speicheraufwand zu vermeiden. Im Folgenden wird das Lesen der Mesh-Blöcke innerhalb eines bestimmten Bereichs um die Kamera als Beispiel verwendet.

Verwenden Sie zunächst GetMeshBlockInfos(), um die Metadaten aller Blöcke (einschließlich der Weltraum-Bounding-Boxen) zu erhalten, berechnen Sie die Distanz vom Rendering-Kamera-Zentrum zur Block-BBOX-Oberfläche in Weltkoordinaten, filtern Sie die Block-IDs mit einer Distanz unter 100 m heraus und verwenden Sie dann das parametrisierte GetMeshes(ids), um nur diese Blöcke zu lesen.

Fügen Sie die folgenden Methoden zu Meshes.cs hinzu:

public void onRequireMeshes()
{
    if (!m_isLoaded || m_renderer == null)
    {
        Debug.LogWarning("[Meshes] Die Daten sind noch nicht fertig geladen; Meshes können nicht abgerufen werden.");
        return;
    }

    // 1. Zero-I/O-Lesen aller Block-Metadaten, Filtern der Blöcke innerhalb von 100 m anhand der Distanz von der Kamera zur BBOX-Oberfläche
    var infos = m_renderer.GetMeshBlockInfos();
    if (infos == null || infos.Count == 0)
    {
        Debug.LogWarning("[Meshes] Keine Mesh-Informationen erhalten (die Daten enthalten möglicherweise keine Collider).");
        return;
    }

    Vector3 camPos = m_camera.transform.position;
    var ids = new List<string>();
    foreach (var info in infos)
    {
        // Wenn sich die Kamera innerhalb der BBOX befindet, gibt ClosestPoint die Kamera selbst zurück und die Distanz ist 0, daher wird der Block ebenfalls ausgewählt
        if (calculateMinDistanceToAABB(info.boundsWorld, camPos) < 100f)
            ids.Add(info.id);
    }

    if (ids.Count == 0)
    {
        Debug.LogWarning("[Meshes] Keine Mesh-Blöcke innerhalb von 100 m um die Kamera.");
        return;
    }

    // 2. Nur die gefilterten Blöcke per ID lesen und visualisieren
    var meshes = m_renderer.GetMeshes(ids);
    if (meshes == null || meshes.Count == 0)
    {
        Debug.LogWarning("[Meshes] Meshes konnten nicht per ID abgerufen werden.");
        return;
    }

    VisualizeMeshes(meshes);
    Debug.Log($"[Meshes] {ids.Count} Blöcke innerhalb von 100 m um die Kamera ausgewählt, {meshes.Count} visualisiert.");
}

// Die nächste Distanz von einem Punkt zur AABB-Oberfläche berechnen (gibt 0 zurück, wenn der Punkt innerhalb der AABB liegt)
private static float calculateMinDistanceToAABB(Bounds _aabb, Vector3 _point)
{
    Vector3 p = _aabb.ClosestPoint(_point);
    return Vector3.Distance(p, _point);
}

Hinweis:

  • GetMeshBlockInfos() ist eine Zero-I/O-, Zero-Analyse-Operation, die nur die bereits im Speicher befindlichen Metadaten liest; Sie können sie frei aufrufen.
  • Der Distanzfilter verwendet boundsWorld (Weltraum-Bounding-Box), und das Kamera-Zentrum verwendet Camera.transform.position.
  • Verwenden Sie Bounds.ClosestPoint, um die nächste Distanz von einem Punkt zur AABB-Oberfläche zu berechnen: Wenn sich die Kamera innerhalb der BBOX befindet, gibt ClosestPoint die Kamera selbst zurück und die Distanz ist 0, daher wird dieser Block ebenfalls ausgewählt.
  • Der Filterradius 100f (Einheit: Meter) im Beispiel kann nach Bedarf angepasst werden.

Erstellen Sie einen Button und verknüpfen Sie onRequireMeshes() mit dessen onClick-Ereignis.

Nach dem Ausführen klicken Sie auf den Button, um die Mesh-Blöcke innerhalb von 100 m um die Kamera zu sehen.

Mesh-Daten innerhalb von 100 m um die Kamera nach Bedarf abrufen und visualisieren

Mesh-Daten innerhalb von 100 m um die Kamera nach Bedarf abrufen

Schlüsselschritte

Die Schlüsselschritte zum Abrufen und Visualisieren von Szenen-Mesh-Daten:

  1. Die Vorkonfiguration wie SetPlatformType abschließen und die LCC-Szene über GetRender + Load laden.
  2. Bestätigen, dass die Daten Kollisions-Mesh-Daten tragen (native Formate oder in früheren Versionen rekonstruierte Daten möglicherweise nicht).
  3. Vollständiges Abrufen: GetMeshes() aufrufen, um alle Blöcke auf einmal zu lesen und das Ergebnis selbst zu cachen, um wiederholte Aufrufe zu vermeiden.
  4. Abrufen nach Bedarf: Zuerst GetMeshBlockInfos() verwenden, um die Welt-Bounding-Boxen der Blöcke zu erhalten, die IDs nach Kameradistanz filtern und dann GetMeshes(ids) verwenden, um nur die Zielblöcke zu lesen.
  5. Beim Visualisieren das GameObject unter Renderer.Transform anhängen, um es an den lokalen Koordinaten auszurichten, und das Mesh mit IndexFormat.UInt32 aufbauen.

APIs zum Abrufen von Mesh-Daten

Die folgenden Methoden befinden sich alle auf Renderer; sie müssen nach Abschluss des Szenenladens aufgerufen werden, und die Daten müssen Kollisions-Mesh-Daten tragen.

GetMeshBlockInfos

// Rückgabewert: List<LCCMeshBlockInfo> → Metadaten der Kollisions-Mesh-Blöcke; null, wenn kein Mesh vorhanden oder nicht verfügbar
public List<LCCMeshBlockInfo> GetMeshBlockInfos()

Gibt die Metadaten aller Kollisions-Mesh-Blöcke zurück (id, Welt-/Lokal-Bounding-Box, Vertexanzahl, Flächenanzahl). Zero-I/O und Zero-Analyse; liest nur die bereits im Speicher befindlichen Metadaten.

Verwendungsbeispiel:

var infos = renderer.GetMeshBlockInfos();
foreach (var info in infos)
{
    Debug.Log($"{info.id}: verts={info.vertexCount}, faces={info.faceCount}, bbox={info.boundsWorld.size}");
}

Hinweise:

  • Nur PC / Mac + lokale Datenquelle; nur im Hauptthread.
  • Typische Verwendung: Zuerst damit die Welt-BBox jedes Blocks abrufen, die benötigten IDs heraussuchen und dann GetMeshes(ids) aufrufen, um nur diese Blöcke zu lesen.
  • Native Formate (PLY / SOG / SPZ / splat / ksplat) haben kein Mesh und geben null zurück (was normal ist und nicht protokolliert wird).

GetMeshes

// Rückgabewert: List<LCCMeshBlock> → Geometriedaten aller Kollisions-Mesh-Blöcke; null, wenn nicht verfügbar
public List<LCCMeshBlock> GetMeshes()

Gibt synchron die Geometriedaten aller Kollisions-Mesh-Blöcke zurück (Vertices + Dreiecksindizes, im lokalen Koordinatensystem). Dies ist eine schwere Operation (synchrones Festplattenlesen + Analyse + Zuweisung); rufen Sie sie einmal auf und cachen Sie sie selbst, niemals in jedem Frame.

Verwendungsbeispiel:

var meshes = renderer.GetMeshes();
foreach (var block in meshes)
{
    // block.vertices / block.triangles liegen im lokalen Koordinatensystem des Objekts vor
}

Hinweise:

  • Nur PC / Mac + lokale Datenquelle; nur im Hauptthread.
  • Verwenden Sie für große Szenen stattdessen GetMeshBlockInfos() zum Auswählen der IDs + GetMeshes(ids), um eine einmalige Zuweisung großer Mengen verwalteten Speichers zu vermeiden.
  • Die Vertexanzahl eines einzelnen Blocks kann 65535 überschreiten; vor dem Aufbau des eigenen Mesh müssen Sie mesh.indexFormat = IndexFormat.UInt32 setzen.

GetMeshes (nach ID)

// Rückgabewert: List<LCCMeshBlock> → Kollisions-Mesh-Geometriedaten für die angegebenen IDs; null, wenn keine Treffer
public List<LCCMeshBlock> GetMeshes(IEnumerable<string> _ids)

Gibt synchron die Geometriedaten der Kollisions-Mesh-Blöcke mit den angegebenen IDs zurück (lokales Koordinatensystem). Die IDs werden von GetMeshBlockInfos() bereitgestellt.

ParameterTypBeschreibung
_idsIEnumerable<string>Die Sammlung der Zielblock-IDs (bereitgestellt von GetMeshBlockInfos())

Verwendungsbeispiel:

var ids = new List<string> { "block-0", "block-3" };
var meshes = renderer.GetMeshes(ids);

Hinweise:

  • Unbekannte IDs werden mit einer Warnung übersprungen; doppelte IDs werden dedupliziert (nicht wiederholt von der Festplatte gelesen); die Rückgabereihenfolge ist die Traversierungsreihenfolge der IDs (nach Deduplizierung).
  • Die Übergabe von null, einer leeren Eingabe oder keiner Treffer gibt null mit einer Warnung zurück.
  • Weitere Einschränkungen sind dieselben wie bei GetMeshes().

Datenstruktur LCCMeshBlockInfo

public struct LCCMeshBlockInfo {
    public string id;           // Knoten-ID, entspricht LCCMeshBlock.id
    public Bounds boundsWorld;  // Weltraum-AABB, zum Auswählen der IDs
    public Bounds boundsLocal;  // Lokalraum-AABB
    public int vertexCount;     // Vertexanzahl
    public int faceCount;       // Flächenanzahl
}
FeldTypBeschreibung
idstringKnoten-ID, entspricht LCCMeshBlock.id
boundsWorldBoundsWeltraum-AABB, zum Auswählen der IDs
boundsLocalBoundsLokalraum-AABB
vertexCountintVertexanzahl
faceCountintFlächenanzahl

Datenstruktur LCCMeshBlock

public struct LCCMeshBlock {
    public string id;           // Knoten-ID
    public Vector3[] vertices;  // Vertices, in lokalen Koordinaten
    public int[] triangles;     // Dreiecksindizes, drei pro Gruppe
    public Bounds boundsLocal;  // Bounding Box im selben Raum wie die Vertices
}
FeldTypBeschreibung
idstringKnoten-ID
verticesVector3[]Vertex-Array, im lokalen Koordinatensystem des Objekts
trianglesint[]Dreiecksindizes, drei pro Gruppe
boundsLocalBoundsBounding Box im selben Raum wie die Vertices

Hinweis:

vertices / boundsLocal liegen beide im lokalen Koordinatensystem des Objekts. Um sie in Unity zu visualisieren, hängen Sie das GameObject, das das Mesh trägt, unter Renderer.Transform an, um es automatisch auszurichten. Die Vertexanzahl eines einzelnen Blocks kann 65535 überschreiten; vor dem Aufbau des eigenen Mesh müssen Sie mesh.indexFormat = IndexFormat.UInt32 setzen.