Technische Referenz
Vollständige Locus Package v2 erstellen
Auf dieser Seite
- Mit einem funktionsfähigen vollständigen Paket beginnen
- Archivstruktur
- locusplace.json
- Feldreferenz des Paketrahmens
- Package-v2-Metadaten im ZIP
- Ansicht: destination.json
- Raum: space.json
- Experience: experience.json
- Optionale Funktionen und übersetzte Bezeichnungen
- Erforderliche Herkunftsangaben
- Sicherheit und Ressourcenlimits
- Dateien und URLs als Importquelle
- Paketprüfung und Beispiele
Status: kanonischer Vertrag für Veröffentlichung, Speicherung, Kombination und vollständigen Import. Ab Locus 1.2.1 lässt sich dieses Archiv über Dateien oder eine öffentliche HTTPS-URL als Ansicht oder Raum importieren. Das ältere flache Format in der
locus-asset-format.md bleibt eine Kompatibilitätseingabe.
Ein .zip oder .locusplace ist ein gewöhnliches ZIP-Archiv mit einer oder mehreren Package-v2-Destinations (Produktname: Ansichten), Spaces (Räume) und Experiences. Es bildet den sicheren Veröffentlichungs- und Integritätsrahmen, den Locus selbst sowie vollständige portable Pakete verwenden. Direkt in der ZIP-Wurzel liegen locusplace.json und
catalog/ direkt in der ZIP-Wurzel. Legen Sie beide nicht in einen zusätzlichen übergeordneten Ordner.
Die Prüfung basiert auf Archivbytes und Manifesten, niemals auf der Dateiendung. Ein vollständiges Paket bewahrt packageID, die Inhalts-IDs,
contentVersion -Updatestrom und unterstützte Experiences. Ein erneuter Import desselben Inhalts-Hashes ist eine idempotente Operation ohne Änderung. Der gepflegte Packer und Validator erstellen und prüfen genau dieses Format.
Dieser Paketrahmen enthält reine Daten, keine ausführbaren Erweiterungen. Innerhalb derselben Locus-Version hat jede von der Laufzeit verarbeitete Package-v2-Funktion dieselbe Bedeutung, unabhängig davon, ob das Archiv integriert ist, aus der Bibliothek stammt oder über Dateien/URL importiert wurde. Die Herkunft darf Berechtigungen, Importkontingente, Updatebefugnis, Speicherung, Entfernen und Anzeigebezeichnungen beeinflussen, schaltet aber niemals ein anderes Raum-/Ansichtsschema oder andere Rendererfunktionen frei. Skripte, Plugins, dynamische Bibliotheken und ausführbare Dateien gehören nicht zum Format. Für jede Herkunft gelten dieselben Prüfungen auf sichere Pfade, Integrität, Ressourcenbudgets, strukturelle Dekodierung, vollständige Referenzauflösung und Mindestversion.
Diese Anleitung beschreibt den vollständigen Paketrahmen und die Basismanifeste. Die Feldreferenz erläutert die optionalen Funktionen von Ansichten und Räumen einschließlich Dateien, Grenzen, Standardwerten und Mindestversionen. Das Schema des Paketrahmens und Herkunftsschema beschreiben die JSON-Struktur. Packer und Validator prüfen zusätzlich Dateibytes und feldübergreifende Regeln. Ein JSON Schema allein kann kein Archiv prüfen und nicht nachweisen, dass die Darstellung auf Apple Vision Pro angenehm ist.
Mit einem funktionsfähigen vollständigen Paket beginnen
Klonen oder laden Sie das öffentliche Werkzeug-Repository. Führen Sie diese Befehle im Hauptverzeichnis des Repositorys unter macOS aus. Erforderlich sind Python 3.9 oder neuer und eine Xcode-Installation mit
xcrun usdchecker und xcrun usdcat. Die grundlegende Prüfung verwendet die Python-Standardbibliothek,
/usr/bin/sips für die vollständige Bilddekodierung sowie Xcodes usdchecker und usdcat
für Modelle. Erweiterte Prüfungen für Wolken, Wasserreflexionen/-kontakte und sonnenfreie Himmel benötigen zusätzlich NumPy und Pillow: python3 -m pip install numpy pillow.
python3 examples/locusplace/build_examples.py /absolute/path/to/locusplace-examples
python3 tools/validate_locusplace.py --current-app-version 1.4.4 /absolute/path/to/locusplace-examples/view-only.locusplace
python3 tools/validate_locusplace.py --current-app-version 1.4.4 /absolute/path/to/locusplace-examples/room-only.locusplace
python3 tools/validate_locusplace.py --current-app-version 1.4.4 /absolute/path/to/locusplace-examples/combined.locusplace
Der Zielordner darf noch nicht existieren oder muss leer sein. Diese winzigen synthetischen Beispiele prüfen das Format. Farbverlauf und Würfel sind keine fertige Landschaft oder ein fertiger Raum in Produktionsqualität. Ihr Quellcode und die erzeugten Inhalte stehen unter Apache-2.0. Siehe die Beispielanweisungen.
--current-app-version gibt an, auf welche Locus-Version sich die Prüfung bezieht; dadurch wird weder die installierte App aktualisiert noch eine Funktion freigeschaltet. Die Werkzeuge verwenden vorsichtshalber den Standardwert 1.0.0; geben Sie die Zielversion ausdrücklich an. Vollständige Importe erfordern mindestens Locus 1.2.1; neuere Felder haben jeweils eigene Mindestversionen. Die Boden- und Mittelgrundeinstellungen für Räume benötigen einen unterstützenden Build ab 1.4.4. Diese Anleitung behauptet nicht, dass ein solcher Build bereits im App Store erhältlich ist.
Entpacken Sie für ein eigenes Paket ein Beispiel in einen bearbeitbaren Ordner oder erstellen Sie die unten gezeigte Struktur. Ersetzen Sie Dateien und Herkunftsangaben, verwenden Sie eigene stabile IDs und schreiben Sie die Ausgabe außerhalb dieses Ordners:
python3 tools/pack_locusplace.py --current-app-version 1.4.4 MyEditablePlace MyPlace.zip
python3 tools/validate_locusplace.py --current-app-version 1.4.4 --json MyPlace.zip
Der Packer berechnet die Felder neu: files und contentHash, prüft das Archiv und erstellt erst danach die Ausgabedatei. Vorhandene Ausgabedateien werden nicht überschrieben. Der bearbeitbare Quellordner bleibt unverändert. Importieren Sie das Ergebnis über Orte → Importieren → Ansicht importieren oder Raum importieren → Dateien. Wählen Sie einen Importweg für einen im Paket enthaltenen Inhaltstyp. Ein kombiniertes Paket installiert seine Inhalte gemeinsam. Auch eine direkte öffentliche HTTPS-URL zur ZIP-Datei ist möglich. Prüfen Sie jeden erstellten Sitz, Effekt, jede Lichtquelle und jeden Ton auf Apple Vision Pro, bevor Sie einen fertigen Ort weitergeben.
Archivstruktur
example.locusplace
├── locusplace.json
└── catalog/
├── destinations/<destination-id>/
│ ├── destination.json
│ ├── provenance.json
│ └── ...
├── spaces/<space-id>/
│ ├── space.json
│ ├── provenance.json
│ └── ...
└── experiences/<experience-id>/
└── experience.json
Jeder reguläre Archiveintrag außer der Datei locusplace.json muss aufgeführt sein in files. Jede deklarierte Datei muss vorhanden sein. Erlaubt sind nur die drei bekannten Katalogsammlungen. Jede Datei muss zu einer Paket-ID gehören, die in folgendem Feld deklariert ist: contents. Package-v2-Manifeste bleiben gegenüber unbekannten Feldern vorwärtskompatibel. Unbekannte Felder im Paketrahmen, nicht unterstützte Formatversionen, Sammlungen und Inhaltsmodi werden jedoch sicher abgewiesen. Für Herkunftsangaben gilt das veröffentlichte Schema.
Ein reines Ansichts- oder Raumarchiv installiert wiederverwendbare Kataloginhalte. Nach der Katalogauflösung erzeugt Locus die Standardkombinationen: jede Ansicht mit „Ihr Raum“ sowie jede Ansicht mit jedem Raum, der eine Ansichtsöffnung besitzt. Eine explizite Experience ersetzt nur ihre benannte Kombination und kann auf Inhalte desselben Archivs oder auf eine stabile ID im integrierten bzw. importierten Katalog verweisen.
locusplace.json
{
"formatVersion": 1,
"packageID": "place.example-combined",
"contentVersion": "1.0.0",
"minimumAppVersion": "1.0.0",
"contents": {
"destinationIDs": ["destination.example-view"],
"spaceIDs": ["space.example-room"],
"experienceIDs": ["experience.example-combined"]
},
"files": [
{
"path": "catalog/destinations/destination.example-view/destination.json",
"byteCount": 214,
"sha256": "<64 lowercase hex characters>"
}
],
"contentHash": "<64 lowercase hex characters>"
}
packageID und alle Inhalts-IDs sind stabile ASCII-Kennungen mit höchstens 128 Bytes. Sie beginnen mit einem Buchstaben oder einer Ziffer. Danach sind nur Buchstaben, Ziffern sowie
., _und -. Versionsnummern bestehen aus genau drei numerischen Bestandteilen. Ändern sich die Bytes, muss ein Update dieselben deklarierten Inhalts-IDs behalten und die folgende Version erhöhen: contentVersion. Der erneute Import desselben contentHash ist eine idempotente Operation ohne Änderung.
contentHash ist der SHA-256 aller nach Unicode-Pfad sortierten Dateieinträge. Jeder Eintrag liefert diese UTF-8-Bytes:
path NUL decimal-byteCount NUL lowercase-sha256 NUL
Dieser Hash ist unabhängig von JSON-Leerraum und der Reihenfolge der ZIP-Mitglieder. Der Validator liest außerdem jede deklarierte Datei als Datenstrom und prüft ihre tatsächliche Byteanzahl, ZIP-CRC und SHA-256.
Feldreferenz des Paketrahmens
| Feld | Erforderlich | Bedeutung |
|---|---|---|
formatVersion |
ja | Ganzzahl 1; unbekannte Versionen des Paketrahmens werden sicher abgewiesen. |
packageID |
ja | Stabile Identität dieses Installations-/Updatestroms; kein Dateiname. |
contentVersion |
ja | Drei numerische Bestandteile, beispielsweise 1.2.0; erhöhen Sie die Version, wenn sich die Bytes bei gleichen IDs ändern. |
minimumAppVersion |
ja | Älteste Locus-Version, die das Archiv importieren darf, ebenfalls mit drei numerischen Bestandteilen. |
contents.destinationIDs |
ja | Eindeutige Ansichts-IDs im Besitz dieses ZIPs; verwenden Sie [] wenn keine vorhanden sind. |
contents.spaceIDs |
ja | Eindeutige Raum-IDs im Besitz dieses ZIPs; verwenden Sie [] wenn keine vorhanden sind. |
contents.experienceIDs |
ja | Eindeutige Experience-IDs im Besitz dieses ZIPs; verwenden Sie [] wenn keine vorhanden sind. |
files |
ja | Vollständiges erzeugtes Inventar jeder Nutzdatei außer locusplace.json. |
files[].path |
ja | Kanonischer archivrelativer catalog/... -Pfad. |
files[].byteCount |
ja | Exakte unkomprimierte Byteanzahl. |
files[].sha256 |
ja | SHA-256 der entpackten Bytes, 64 kleingeschriebene Hexadezimalzeichen. |
contentHash |
ja | SHA-256-Identität des oben beschriebenen kanonischen Dateiinventars. |
Package-v2-Metadaten im ZIP
Der vollständige Paketrahmen verwendet formatVersion: 1; jedes destination.json,
space.json und experience.json verwendet formatVersion: 2. Die Room-Versionsnummern v1–v10 in der Referenz des flachen Kompatibilitätsformats
gehören zur separaten flachen space.json -Eingabe. Ändern Sie niemals ein vollständiges
space.json auf Version 10, um gebackene Lichtschichten zu nutzen. In vollständigen Paketen aktivieren typisierte Felder die optionalen Funktionen; abgesichert werden sie durch
minimumAppVersion.
Alle Dateipfade eines Pakets sind relativ zum Ordner ihres Manifests, nicht zur ZIP-Wurzel. Jede Referenz muss auf eine reguläre Datei innerhalb dieses Pakets zeigen. Die Basismanifeste von Package v2 erlauben vorwärtskompatible Metadaten; einzelne Funktionsprofile können jedoch geschlossene Feldmengen vorgeben. Verlassen Sie sich nicht darauf, dass ein unbekanntes Feld dargestellt wird. Der äußere Paketrahmen weist unbekannte Felder zurück; Herkunftsangaben müssen dem veröffentlichten Schema entsprechen.
Das Koordinatensystem ist rechtshändig, verwendet Meter, +Y nach oben und −Z nach vorn. Quaternionen stehen in der Reihenfolge
[x, y, z, w]. Eine Transformation kann folgende Felder enthalten: translationMeters (drei endliche Zahlen), orientationXYZW (vier endliche Zahlen mit einer von null verschiedenen Länge) und
scale (drei endliche positive Zahlen).
Ansicht: destination.json
{
"formatVersion": 2,
"id": "destination.example-view",
"title": "Example View",
"panorama": {
"path": "panorama.jpg",
"projection": "equirectangular",
"width": 8192,
"height": 4096,
"initialYawDegrees": 0
},
"provenance": "provenance.json"
}
| Feld | Erforderlich | Bedeutung und Prüfung |
|---|---|---|
formatVersion |
ja | Ganzzahl 2. |
id |
ja | Stabile Ansichts-ID; muss mit Verzeichnisname und ID im Paketrahmen übereinstimmen. |
title |
ja | Nicht leerer sichtbarer Ansichtsname. |
panorama.path |
ja | Paketrelatives endgültiges JPEG oder PNG; der Dateityp wird anhand der dekodierten Bytes bestimmt, nicht allein anhand der Endung. |
panorama.projection |
ja | Genau equirectangular. |
panorama.width, height |
ja | Positive dekodierte Abmessungen, die exakt den deklarierten Werten entsprechen, mit width == 2 * height. |
panorama.initialYawDegrees |
nein | Endliche Drehung im kanonischen Panoramakoordinatensystem; Standard: 0. |
sourceImage |
nein | Optionales paketrelatives JPEG/PNG-Prüfbild. Es wird nicht dargestellt, kann aber als typisierte, dekodierte und budgetierte Datei im vollständigen Paket erhalten bleiben. Bearbeitbare DCC-Quelldateien gehören nicht ins Laufzeit-ZIP. |
thumbnail |
nein | Paketrelatives JPEG/PNG-Katalogbild. |
caption |
nein | Für Menschen lesbare Beschreibung. |
generation.generator |
nein | Wahrheitsgemäßer Name des Generators oder Werkzeugs. |
generation.model |
nein | Optionale Modell-/Workflow-Version. |
generation.generatedAt |
nein | Optionaler Zeitstempel; empfohlen wird RFC 3339 UTC. |
depthLayers[] |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Reservierte geordnete Tiefendaten. Der öffentliche Import weist dieses Feld zurück, bis eine Produktlaufzeit und eine Prüfung auf Byteebene das Format unterstützen. |
midground.path |
nein | Mittelgrund-USDZ für die Laufzeit, das in beiden Erlebnismodi dargestellt wird. Für integrierte, Bibliotheks- und importierte Pakete gelten dieselben Regeln zu Mitgliedern, Struktur und Ressourcen. Siehe Mittelgrundreferenz. |
midground.transform |
nein | Optionale endliche Transformation für midground.path. |
midground.terrainEntities |
nein | Eindeutige, nicht leere Namen der Geländeeinheiten in midground.path; die Laufzeit verwendet sie, um Gelände unter der Grundfläche des Raums abzusenken. |
midground.water |
nein | Von der App dargestellte Wasserdefinition mit geprüfter Maske/Normalenkarte und optionalen Uferdaten aus der Feldreferenz. |
sky |
nein | Von der App erzeugter Nachthimmel (Sterne, Milchstraße, optionale Polarlichter), sichtbar durch eine geprüfte 2:1-Graustufenmaske sky.mask; erfordert minimumAppVersion >= 1.2.4. Siehe Himmelsreferenz. |
gpuTexture, gpuTextures |
nein | Geprüfte ASTC-KTX1-Begleitdateien, die für Nutzer-ZIPs und Bibliothekspakete gleichermaßen verfügbar sind. Die v1-Begleitdatei des Panoramas erfordert 1.2.3; das v2-Array der Quellbilder erfordert 1.3.0. Quell-Hashes, Abmessungen und Mipmap-Stufen müssen übereinstimmen. |
water, clouds, fireflies |
nein | Wasserdefinitionen einschließlich Leuchten, Bewegung gemalter Wolken und Glühwürmchen zur Laufzeit; erfordern minimumAppVersion >= 1.3.0. Für referenzierte Dateien und Ressourcenlimits gilt der gemeinsame Package-v2-Vertrag. |
environment.sunPath |
nein | Erstellter sonnenfreier Himmel mit optionaler maskierter Sonnenscheibe; erfordert 1.3.0 und die zugehörige Bestätigung des Autors. |
celestial |
nein | Animierter Himmelskörper mit referenzierten Texturen; erfordert 1.2.4oder die höhere Mindestversion, die die optionalen Funktionen verlangen (Bewegung und Entwicklung der Wolkenhülle benötigen 1.3.0). |
nearOrbit |
nein | Profile für den nahen Orbit, Texturdateien und ein an den Inhalt gebundener Nachweis des Ersatzpanoramas. v1 und v2 erfordern 1.3.0; v2 umfasst das Kachelmanifest, die Kachelbilder und ihre GPU-Begleitdateien. |
splat.variants, splat.ply |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Reservierte zukünftige Dateireferenzen. Der Splat-Renderer wurde entfernt; der öffentliche Import weist daher das gesamte Feld zurück. |
splat.metricScaleFactor |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Endlicher positiver Maßstab im reservierten Vertrag. |
splat.groundPlaneOffset |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Endlicher erstellter Bodenversatz im reservierten Vertrag. |
splat.placement |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Optionale gemeinsame Transformation im reservierten Vertrag. |
environment |
nein | Helligkeit der sichtbaren Ansicht, optionales kleines SDR-Bild für die Raumbeleuchtung und direkte Sonnenlichtvorgaben, siehe unten. |
audio.path |
nein in Package v2; in öffentlichen ZIP-Importen nicht unterstützt | Reservierte Laufzeit-Audiodatei. Der öffentliche Import weist dieses Feld zurück, bis vollständige Audiodatenprüfung und Wiedergabe unterstützt werden. |
audio.loops |
mit Package-v2-Audio; in öffentlichen ZIP-Importen nicht unterstützt | Boolescher Wert für die Wiederholung im reservierten Vertrag. |
provenance |
ja, für Importe | Paketrelative JSON-Datei mit Herkunftsangaben. |
Vollständige ZIPs akzeptieren die von diesem Programm tatsächlich verarbeiteten Felder sowie ausdrücklich beibehaltene Metadaten wie sourceImage, sofern sich deren Inhalt als typisierte Daten innerhalb der Ressourcenlimits prüfen lässt. midground gehört zum gemeinsamen Laufzeitvertrag und erfordert minimumAppVersion >= 1.2.1.
depthLayers, splatund der ältere Block audio bleiben reserviert oder veraltet und haben keinen aktuellen Laufzeitverbraucher. Deshalb weist diese App-Version sie unabhängig von ihrer Herkunft zurück, statt ungeprüfte Dateipfade zu akzeptieren. Sobald eine spätere Version eine dieser Funktionen implementiert, muss sie Dateireferenzen, Typ- und Budgetprüfungen, Laufzeitverbraucher und Mindestversion in den gemeinsamen Vertrag aufnehmen. Es darf kein separater Schalter für öffentliche Importe hinzukommen.
12.288×6.144 (12K) wird empfohlen, ist aber keine Pflicht. Niedrigere Auflösungen wie 8.192×4.096, 6.144×3.072 oder 4.096×2.048 sind gültig, sofern sie exakt 2:1 sind und mit ihren tatsächlichen dekodierten Abmessungen angegeben werden. Skalieren Sie ein kleineres Bild nicht nur hoch, um 12K anzugeben: Es entstehen keine neuen Details, nur höherer Speicherbedarf.
Die Panoramakoordinaten sind festgelegt: u = 0.5 ist Winkel 0 und die anfängliche Vorwärtsrichtung/Welt −Z; u nimmt nach Osten in Richtung +X zu; die Naht liegt bei u = 0/1bei einem Winkel von ±180°; die oberste Bildzeile zeigt den Zenit. initialYawDegrees dreht das Bild innerhalb dieses Koordinatensystems, definiert es aber nicht neu.
Optionale Beleuchtung einer Ansicht:
{
"environment": {
"imageBasedLight": "thumbnail.jpg",
"skyGainEV": 0,
"exposureEV": 0,
"horizonPitchDegrees": 0,
"colorGrade": {"contrast": 1.15, "saturation": 1.2},
"directSun": {"enabled": false, "illuminanceLux": 5000}
}
}
| Feld | Bedeutung |
|---|---|
imageBasedLight |
Separates 2:1-JPEG/PNG nur für Beleuchtung und Reflexionen der Raumgeometrie. Es darf nicht denselben Pfad verwenden wie panorama.path; empfohlen sind 1024×512. Ohne Bild wird ein neutraler Beleuchtungsersatz verwendet. |
skyGainEV |
Endlicher EV-Wert ausschließlich für das sichtbare Panorama. |
exposureEV |
Endlicher EV-Wert ausschließlich für IBL. |
horizonPitchDegrees |
Endliche erstellte Horizontkorrektur. |
colorGrade.contrast |
Optionaler Kontrast des sichtbaren SDR-Panoramas im Bereich 0.5 bis 2.0; 1.0 ist neutral. |
colorGrade.saturation |
Optionale Sättigung des sichtbaren SDR-Panoramas im Bereich 0.0 bis 2.0; 1.0 ist neutral. |
directSun.enabled |
Ob eine separate gerichtete Lichtquelle definiert ist. |
directSun.azimuthDegrees, elevationDegrees |
Endliche Richtungswinkel; bei aktivierter Sonne sind beide erforderlich. |
directSun.illuminanceLux |
Endliche, nicht negative Beleuchtungsstärke. |
Die Farbanpassung betrifft nur das angezeigte SDR-Panorama. Sie verwendet dieselbe Textur erneut und macht aus der Ansicht weder HDR noch stellt sie im Ausgangsbild fehlende Lichterdetails wieder her. Auch eine deaktivierte Sonne kann einen Wert von 5000 Lux tragen, damit Sonnenlicht hinzufügen mit der App-Standardstärke startet, ohne den im Paket festgelegten Aus-Zustand zu ändern.
visibleSkyHDR und hdrManifest sind veraltet und werden abgewiesen. Eine EXR-Datei außerhalb des USDZ darf weder die sichtbare Ansicht noch das Raumbeleuchtungsbild liefern. OpenEXR bleibt für Raumtexturen innerhalb des USDZ erlaubt und wird dort geprüft.
Raum: space.json
{
"formatVersion": 2,
"id": "space.example-room",
"title": "Example Room",
"scene": "scene.usdz",
"thumbnail": "thumbnail.jpg",
"caption": "A quiet house arranged around a sunlit courtyard.",
"previewCamera": {
"yawDegrees": -28,
"pitchDegrees": -10,
"zoom": 1.0
},
"seatedOrigin": {
"translationMeters": [0, 0, 0],
"orientationXYZW": [0, 0, 0, 1]
},
"safeHeadVolume": {
"centerMeters": [0, 1.2, 0],
"sizeMeters": [1.2, 0.6, 1.2]
},
"destinationOpenings": [
{
"id": "front",
"transform": {
"translationMeters": [0, 1.2, -2],
"orientationXYZW": [0, 0, 0, 1]
},
"widthMeters": 4,
"heightMeters": 2.5
}
],
"collision": {"mode": "embedded"},
"teleportCatalog": {"path": "teleport-points.json", "houseID": "example-room"},
"quality": {
"status": "unverified",
"triangleCount": 0,
"materialCount": 0,
"entityCount": 0,
"maxTextureDimension": 0
},
"provenance": "provenance.json"
}
| Feld | Erforderlich | Bedeutung und Prüfung |
|---|---|---|
formatVersion |
ja | Ganzzahl 2. |
id |
ja | Stabile Raum-ID; muss mit Verzeichnisname und ID im Paketrahmen übereinstimmen. |
title |
ja | Nicht leerer sichtbarer Raumname. |
scene |
ja | Paketrelative eigenständige USDZ-Datei. .blend und andere Erstellungsdateien sind kein Ersatz und dürfen auch nicht an anderer Stelle im Paket liegen. |
thumbnail |
nein | Dekodiertes JPEG oder PNG für die Raumkarte, mit paketrelativem Pfad. Eine deklarierte Datei muss existieren, vollständig dekodierbar sein und zählt zum Bildbudget des Archivs. Ohne Angabe wird das Ersatzsymbol verwendet. |
caption |
nein | Nicht leerer Anzeigetext für Über diesen Raum; höchstens 2.000 UTF-8-Bytes. |
previewCamera.yawDegrees, pitchDegrees |
nein | Endliche Anfangswinkel für die begrenzte 3D-Vorschau. Sie beeinflussen die immersive Platzierung nicht. |
previewCamera.zoom |
mit Kamera | Endlicher positiver Anfangsmaßstab für die begrenzte 3D-Vorschau. Zurücksetzen stellt diese erstellte Ansicht wieder her; der Viewer begrenzt die Interaktion auf seinen unterstützten Bereich. |
seatedOrigin.translationMeters |
ja | Drei endliche Meterwerte für die erstellte Bodenreferenz des Sitzes. |
seatedOrigin.orientationXYZW |
ja | Vier endliche Komponenten eines normierten Quaternions; das Sitzkoordinatensystem muss aufrecht bleiben, ohne Neigung oder Rollen. |
safeHeadVolume.centerMeters |
ja | Drei endliche Meterwerte in Raumkoordinaten. |
safeHeadVolume.sizeMeters |
ja | Drei endliche, strikt positive Abmessungen. |
destinationOpenings |
ja | Array rechteckiger Öffnungen. Ein eigenständiger Raumimport braucht genau eine. Keine oder mehrere Öffnungen erfordern eine erstellte virtual-space Experience im selben Archiv. |
destinationOpenings[].id |
pro Eintrag | Eindeutige Paketkennung für die Experience-Kombination. |
destinationOpenings[].transform |
pro Eintrag | Erforderliche Positions-/Quaternion-Pose. |
destinationOpenings[].widthMeters, heightMeters |
pro Eintrag | Endliche, strikt positive Abmessungen. |
collision.mode |
ja | embedded oder separate. |
collision.path |
bedingt | Nicht zulässig für embedded; für separateist dagegen eine paketrelative, eigenständige USDZ-Datei erforderlich. Für sie gelten dieselben Regeln zu Archivmitgliedern, Texturen und Geometrie wie für scene. Seine Geometrie teilt sich mit der Szenengeometrie das Ressourcenbudget des Raums. Umbenannte Quelldateien aus einem Erstellungsprogramm sind nicht zulässig. |
quality.status |
ja | unverified oder verified. |
quality.triangleCount, materialCount, entityCount, maxTextureDimension |
ja | Nicht negative Messwerte des Autors. Null bedeutet nicht vermessen; die tatsächlichen USD-Daten werden unabhängig geprüft. |
teleportCatalog.path |
ja | Paketrelative Teleport-JSON-Datei. Das gewählte Haus muss mindestens einen Sitzpunkt enthalten, sonst kann der Raum nicht als virtueller Raum betreten werden. Die Grenze von 1 MiB gilt aufgrund der Feldrolle auch dann, wenn der Dateiname nicht endet auf .json; Groß-/Kleinschreibung oder Unicode-Aliase im Dateisystem umgehen dieses Limit nicht. |
teleportCatalog.houseID |
ja | ID, die ein nicht leeres Array auswählt: houses in dieser JSON-Datei. |
spatialAdaptation.wallEntities |
nein | Eindeutige, nicht leere USD-Entitätsnamen für Wände. Diese Metadaten blenden sie nicht aus. |
spatialAdaptation.roofEntities |
nein | Eindeutige, nicht leere Namen ohne Überschneidung mit den Wänden. |
spatialAdaptation.deskEntitiesByTeleportID |
nein | Zuordnung einer deklarierten Teleport-ID zu einem nicht leeren Namen der erstellten Tischflächenentität. |
provenance |
ja | Paketrelative JSON-Datei mit Herkunftsangaben. |
Das USDZ verwendet Meter, ein rechtshändiges Koordinatensystem und +Y nach oben. Es enthält nur unterstützte USD-, Textur- und Audiodaten für die Laufzeit. USDZ-Mitglieder müssen unkomprimiert gespeichert sein. Der Validator lädt die tatsächliche USD-Szene, löst ihre Ebenen auf und zählt Geometrie; kleine oder auf null gesetzte quality -Qualitätswerte können ein zu großes Modell nicht verbergen.
Erforderliche Teleport-JSON-Datei (das gewählte Haus muss mindestens einen Punkt enthalten):
{
"houses": {
"example-room": [
{
"id": "work-desk",
"title": "Work desk",
"anchorXZ": [0.5, 0.5],
"sourceFloorOffset": 0,
"eyeHeight": 1.15,
"yawRadians": 0
}
]
}
}
anchorXZ besteht aus zwei endlichen normierten Werten im Bereich 0...1; sourceFloorOffset ist endlich und nicht negativ in den Maßeinheiten des erstellten Modells; eyeHeight ist positiv, endlich und in Metern angegeben; yawRadians ist eine endliche Modelldrehung um +Y im Weltkoordinatensystem. Punkt-IDs sind eindeutig und Titel nicht leer.
Experience: experience.json
{
"formatVersion": 2,
"id": "experience.example-combined",
"title": "Example Room · Example View",
"destinationID": "destination.example-view",
"spaceID": "space.example-room",
"supportedModes": ["virtual-space"],
"composition": {
"destinationOpeningID": "front",
"destinationYawDegrees": 0,
"destinationPitchDegrees": 0,
"destinationExposureOffsetEV": 0
},
"compatibility": {
"minimumViewerVersion": "1.0.0",
"requiredCapabilities": ["world-tracking"]
}
}
| Feld | Erforderlich | Bedeutung und Prüfung |
|---|---|---|
formatVersion |
ja | Ganzzahl 2. |
id |
ja | Stabile Experience-ID. |
title |
ja | Nicht leerer sichtbarer Kachelname. |
destinationID |
ja | Stabile Ansichts-ID in diesem ZIP oder in bereits installierten Inhalten. |
spaceID |
bedingt | Stabile Raum-ID; erforderlich für virtual-space; für den folgenden Modus normalerweise weggelassen: room-portal. |
supportedModes |
ja | Nicht leeres Array ohne Duplikate, das ausschließlich Folgendes enthält: virtual-space oder room-portal. |
composition.destinationOpeningID |
bedingt | Erforderlich für virtual-space; bezeichnet eine Öffnung im referenzierten Raum. |
composition.destinationYawDegrees |
nein | Endlicher Ausrichtungsversatz des Himmels für diese Kombination. |
composition.destinationPitchDegrees |
nein | Endlicher Neigungsversatz des Himmels für diese Kombination. |
composition.destinationExposureOffsetEV |
nein | Endlicher relativer Belichtungsversatz für diese Kombination. |
compatibility.minimumViewerVersion |
nein | Deklarative Zeichenfolge für die Mindestversion des Viewers. |
compatibility.requiredCapabilities |
nein | Deklarative Funktionskennungen. |
ZIPs mit nur einer Ansicht oder nur einem Raum installieren wiederverwendbare Inhalte und nehmen an den Standardkombinationen teil. Eine explizite Experience ist nur nötig, um für eine Kombination Öffnung, Ausrichtung, Belichtung, Titel, Modus oder Kompatibilität zu überschreiben. Referenzen können auf dasselbe Archiv oder auf integrierte bzw. bereits installierte stabile IDs zeigen. Nicht auflösbare Referenzen führen zur Ablehnung des gesamten Imports.
Optionale Funktionen und übersetzte Bezeichnungen
Ergänzen Sie optionale Felder im Manifest der zugehörigen Ansicht oder des Raums und legen Sie jede referenzierte Datei neben diesem Manifest ab. Die Feldreferenz
beschreibt Medien und Masken, Ton und Raummusik, Mittelgrund und Wind, Wasser, Himmel, Wolken, Sonnenbahn, Himmelskörper, nahen Orbit, schwarze Löcher, Punktlichter, GPU-Begleittexturen, Sitze und Gruppen, Licht, Animationen, Videoflächen, Partikel und gebackene Lichtschichten. Sie definiert außerdem localizations,
provenanceDetailsowie die folgenden Einstellungen des Raums: viewGroundFloorOffsetMeters,
viewGroundKeepOutund viewMidgroundVisibility Einstellungen.
Diese optionalen Felder gehören beispielsweise in ein ansonsten vollständiges Raummanifest und erfordern im Paketrahmen minimumAppVersion: "1.4.4" oder neuer:
{
"viewGroundFloorOffsetMeters": 0.2,
"viewGroundKeepOut": false,
"viewMidgroundVisibility": "terrainOnly"
}
Ihre Bedeutung bleibt für importierte, integrierte und Bibliotheksinhalte gleich. Funktionskennungen der Bibliothek in der Feldreferenz gehören zu Bibliotheksangeboten. Fügen Sie kein erfundenes Feld requiredCapabilities in locusplace.json. Der Import vollständiger Pakete prüft die Mindestversion der App und den typisierten Inhalt selbst.
Erforderliche Herkunftsangaben
Jede importierte Destination und jeder Space verweist auf ein JSON-Dokument mit Herkunftsangaben. Es nennt Autor oder Agentur, entweder eine Lizenz oder einen Vorbehalt aller Rechte, gewünschte Urheberangaben, Änderungen, die Nutzung von KI und gegebenenfalls den KI-Anbieter. URLs zur Quelle oder Originaldatei sind optional, müssen aber HTTPS verwenden und dürfen weder Zugangsdaten noch Fragment enthalten. Fehlende, zu große oder ungültige Herkunftsangaben führen zur Ablehnung des gesamten Imports. Siehe Herkunftsreferenz.
{
"formatVersion": 1,
"creatorOrAgency": "Your name or studio",
"sourcePageURL": "https://example.com/project",
"originalAssetURL": "https://example.com/original",
"license": {
"identifier": "YOUR-LICENSE-ID",
"name": "Your license name",
"url": "https://example.com/license"
},
"requestedCredit": "Credit line requested by the creator",
"modificationNotes": "Converted and packaged for Locus.",
"aiGenerated": false
}
| Feld | Erforderlich | Bedeutung und Grenzen |
|---|---|---|
formatVersion |
ja | Ganzzahl 1. |
creatorOrAgency |
ja | Nicht leerer Name des Autors/Studios, höchstens 200 Zeichen. |
sourcePageURL |
nein | Öffentliche HTTPS-Projektseite ohne Zugangsdaten oder Fragment. |
originalAssetURL |
nein | Öffentliche HTTPS-Quellseite; dokumentiert die Herkunft, ohne die Originaldatei einzubetten. |
license.identifier |
bedingt | Nicht leere Kennung, höchstens 100 Zeichen; erforderlich mit license. Locus wählt die Lizenz des Inhalts nicht für Sie aus. |
license.name |
bedingt | Nicht leerer Name, höchstens 200 Zeichen; erforderlich mit license. |
license.url |
bedingt | Öffentliche HTTPS-URL der Lizenz; erforderlich mit license. |
rights.statement |
bedingt | Nicht leerer Rechtevorbehalt, höchstens 1.000 Zeichen; verwenden mit rights.url anstelle von license. |
rights.url |
bedingt | Öffentliche HTTPS-URL des Rechtevorbehalts; genau eines der folgenden Felder ist erforderlich: license oder rights ist erforderlich. |
requestedCredit |
ja | Nicht leere gewünschte Urheberangabe, höchstens 1.000 Zeichen. |
modificationNotes |
ja | Nicht leere Angaben zur Bearbeitung, höchstens 2.000 Zeichen. |
aiGenerated |
ja | Boolescher Wert. |
aiProvider |
bedingt | Erforderlich und nicht leer, wenn aiGenerated ist true; bei false nicht erlaubt; höchstens 200 Zeichen. |
importSource |
nein | Reserviert für eine Ansicht, die Locus direkt aus einem Bild erstellt: photos, filesoder url. Pakete externer Autoren sollten dieses Feld weglassen. |
Das Dokument darf höchstens 64 KiB groß sein. Übernehmen Sie nach einem Austausch der Dateien nicht die Herkunftsangaben einer Vorlage. Die Repository-Lizenz und die Lizenz Ihrer Inhalte sind getrennte Angaben.
Das ZIP dient zur Laufzeitauslieferung, nicht als Sicherung der Erstellungsdateien. Jede Nutzdatei muss über ein bekanntes Package-v2-Dateifeld erreichbar sein. Nicht referenzierte Dateien werden selbst dann zurückgewiesen, wenn sie in locusplace.json.files. .blend, .blend1,
.blend2, .fbx, .obj, .mtl, .gltfund .glb werden auch dann abgewiesen, wenn sie deklariert sind. Bewahren Sie solche Quelldateien außerhalb des ZIPs auf. Ein Raum liefert das endgültige USDZ; eine paketierte Ansicht das endgültige 2:1-Panorama und optional ein kleines 2:1-JPEG/PNG für die Raumbeleuchtung.
Sicherheit und Ressourcenlimits
Die Prüfung untersucht Bytes, nicht Dateiendungen. Abgewiesen werden Pfadtraversierung, absolute oder nicht kanonische Pfade, Rückwärtsschrägstriche, Steuerzeichen, Kollisionen durch Groß-/Kleinschreibung oder Unicode, Symlinks, doppelte Einträge, verschlüsselte Daten, nicht deklarierte Dateien, falsche Hashes, nicht unterstützte Manifeste, fehlerhafte Bilder, ungültige EXR-Texturen in USDZ, fehlerhafte USDZ-Strukturen, komprimierte USDZ-Mitglieder und nicht unterstützte USDZ-Dateitypen. Raumlimits werden anhand der vom System tatsächlich geladenen USD-Szene geprüft; die selbst angegebenen Qualitätsmesswerte sind nur Erstellungsmetadaten und können diese Zählwerte nicht reduzieren.
Die Liste zulässiger Bildformate auf Byteebene ist verbindlich: importierte Panoramen und Rasterfelder sourceImage,
thumbnailund imageBasedLight müssen JPEG oder PNG sein. USDZ-Texturen dürfen JPEG, PNG oder OpenEXR sein. Andere von ImageIO dekodierbare Formate werden nicht stillschweigend akzeptiert, sondern abgewiesen. Auch 3D-Erstellungsformate außerhalb des USDZ sind verboten. Ein USDZ darf ausschließlich USD/USDA/USDC, JPEG, PNG, OpenEXR, M4A, WAV und MP3 enthalten.
| Ressourcenbudget | v1-Limit |
|---|---|
| Download oder lokales Archiv | 1 GiB |
| ZIP-Mitglieder | 4,096 |
| Wurzelmanifest | 1 MiB |
| Jede Nutzdatei | 768 MiB |
| Gesamte entpackte Nutzdaten | 2 GiB |
| Kompressionsverhältnis | 200:1 |
| Jede importierte JSON-Datei | 1 MiB |
| JSON-Herkunftsangaben | 64 KiB |
| Bildabmessung | 32.768 px |
| Ein Bild | 150 Millionen Pixel |
| Alle Ansichtsbilder | 500 Millionen Pixel |
| USDZ-Mitglieder | 4,096 |
| USDZ-Dateigröße / entpackte Größe | 768 MiB / 1,5 GiB |
| USDZ-Texturabmessung / Gesamtpixelzahl | 16.384 px / 500 Millionen |
| Geladene Raumgeometrie | 5 Millionen Dreiecke, 1.024 Materialien, 100.000 Entitäten |
Dateien und URLs als Importquelle
Für Ansichten akzeptiert die Importseite ein JPG-, PNG- oder HEIC-Bild aus Fotos, Dateien oder einer direkten öffentlichen HTTPS-URL. Locus wandelt das Bild in ein Package-v2-Paket mit genau einer Destination um und prüft und installiert es über denselben Validator und die atomare Installation. Dateien und URLs akzeptieren auch vollständige Package-v2-ZIPs für Ansichten und Räume, einschließlich kombinierter Pakete mit dem vom Besucher gewählten Inhaltstyp. Bestehende flache ZIPs bleiben Kompatibilitätseingaben. Ein fehlerhaftes Archiv mit locusplace.json wird als ungültiges vollständiges Paket abgewiesen. Es gibt keinen Rückfall auf den flachen Parser. URL-Importe weisen Zugangsdaten, Fragmente, localhost, .localund DNS-Antworten mit nicht öffentlichen Adressen ab. Ein Hostname wird pro Anfrage einmal aufgelöst. Jede zurückgegebene Adresse muss öffentlich sein. Die TLS-Verbindung wird zu genau dieser numerischen IP-Adresse aufgebaut, während der ursprüngliche Hostname authentifiziert wird. Jede Weiterleitung wiederholt diese Auflösung und Adressbindung vor einer neuen Verbindung. Höchstens fünf Weiterleitungen sind erlaubt; deklarierte und tatsächlich heruntergeladene Datenmengen sind begrenzt.
Prüfung und Katalogauflösung erfolgen in einem nicht öffentlichen Zwischenverzeichnis auf demselben Volume. Eine bibliotheksweite beratende Sperre serialisiert Inventarprüfung, Kontingentprüfung und Übernahme. Erstinstallationen verwenden eine exklusive atomare Umbenennung; Updates einen atomaren Verzeichnistausch. Bei jedem Fehler wird das Zwischenverzeichnis entfernt und das installierte Paket bleibt unverändert.
Paketprüfung und Beispiele
Die folgenden Befehle verwalten den vollständigen Package-v2-Paketrahmen für Veröffentlichungen und vollständige Importe. Die älteren flachen Werkzeuge bleiben dokumentiert in der
locus-asset-format.md.
Prüfen Sie beide Dateiendungen ohne Installation:
python3 tools/validate_locusplace.py --current-app-version 1.4.4 MyPlace.locusplace
python3 tools/validate_locusplace.py --current-app-version 1.4.4 MyPlace.zip
python3 tools/validate_locusplace.py --current-app-version 1.4.4 --json MyPlace.locusplace
Der Python-Code verwendet die Standardbibliothek sowie macOS ImageIO über /usr/bin/sipsund die USD-Werkzeuge usdchecker und usdcat (mit Xcode bzw. dessen Befehlszeilenwerkzeugen installiert). Nach der strukturellen JPEG- oder PNG-Prüfung dekodiert ImageIO alle Bildpixel. Die EXR-Prüfung betrifft ausschließlich Texturen innerhalb von USDZ-Dateien. Die USD-Werkzeuge laden die tatsächliche USD-Szene des Raums, lösen ihre Ebenen auf und vermessen sie. Bei einem Fehler endet das Programm mit einem Fehlercode. Es prüft Archiv, Integrität, Package v2, Herkunftsangaben, Bilder/EXR und USDZ. Für die Installation und die Auflösung von Referenzen zwischen Katalogen bleibt der visionOS-Importer maßgeblich.
Packen Sie einen bearbeitbaren Ordner in eine gewöhnliche ZIP-Datei. Dabei werden alle Integritätsdaten neu berechnet; die Datei wird nur erstellt, wenn der Validator sie akzeptiert:
python3 tools/pack_locusplace.py --current-app-version 1.4.4 MyEditablePlace MyPlace.zip
Erzeugen Sie echte Beispielarchive mit nur einer Ansicht, nur einem Raum sowie kombinierten Inhalten in einem temporären oder ignorierten Ordner und prüfen Sie sie:
python3 examples/locusplace/build_examples.py /tmp/locusplace-examples
for package in /tmp/locusplace-examples/*.locusplace; do
python3 tools/validate_locusplace.py --current-app-version 1.4.4 "$package"
done
Die Beispiele werden aus Quellcode erzeugt, ohne private Dateien herunterzuladen oder kostenpflichtige Dienste aufzurufen. Generator und erwartete Struktur stehen in der Beispiel-README.