技術リファレンス

完全な Locus Package v2 の制作ガイド

このページの内容
  1. 動作する完全なパッケージから始める
  2. アーカイブ構成
  3. locusplace.json
  4. ラッパーのフィールドリファレンス
  5. ZIP 内の Package v2 メタデータ
  6. View:destination.json
  7. Room:space.json
  8. Experience:experience.json
  9. 省略可能な機能とラベルの翻訳
  10. 必須の来歴情報
  11. セキュリティとリソース上限
  12. ファイルと URL からの取得
  13. パッケージの検証とサンプル

位置づけ:公開、保存、組み合わせ、全機能に対応したインポートについての正式な契約です。Locus 1.2.1 以降では、ファイルまたは公開 HTTPS URL から、このアーカイブを View と Room の両方のインポートに使用できます。旧来のフラット形式は locus-asset-format.md で、互換入力として引き続き利用できます。

1 つの .zip または .locusplace ファイルは、1 つ以上の Package v2 Destination(製品名:View)、Space(Room)、Experience を含む通常の ZIP アーカイブです。Locus 本体と、全機能に対応した可搬パッケージで使用する、安全な公開と整合性検証のためのラッパーです。ZIP ルートには locusplace.json および catalog/ を直接配置します。両方を別の親ディレクトリにまとめて入れないでください。

検証は常にアーカイブのバイト列とマニフェストに基づき、ファイル名の拡張子には依存しません。完全なパッケージは、 packageID、コンテンツ ID、 contentVersion による更新系列、サポートする Experience を維持します。同じコンテンツハッシュのインポートは冪等な処理で、何も変更しません。維持管理されているパッキングツールとバリデーターは、この形式そのものを生成・検査します。

このラッパーに格納できるのは純粋なデータであり、実行可能な拡張機能ではありません。同じ Locus バイナリでは、実行時に使用するすべての Package v2 機能は、アーカイブがアプリ同梱、Library からのダウンロード、ファイル/URL からのインポートのいずれであっても、同じコンテンツの意味を持ちます。入手元によって、利用権限、カスタムインポートの許容量、更新権限、保存、削除、UI のラベルは変わることがありますが、別の Room/View スキーマや描画機能が有効になることはありません。スクリプト、プラグイン、動的ライブラリ、実行可能なメンバーは、この形式の対象外です。すべての入手元で、同じパス封じ込め、整合性、リソース上限、構造を確認したデコード、参照先の完結性、最低バージョンの検証を維持します。

完全なラッパーと基本マニフェストについては、このガイドを使用してください。 フィールドリファレンス では、省略可能な View と Room の機能、アセット、範囲、最低アプリバージョンを説明しています。 ラッパーのスキーマ および 来歴情報のスキーマ は JSON の構造を定義しています。パッキングツールとバリデーターは、ファイルのバイト列とフィールド間の規則も検証します。JSON Schema だけではアーカイブを検証できず、Apple Vision Pro で快適に使えることも証明できません。

動作する完全なパッケージから始める

取得先: 公開ツールリポジトリをクローンまたはダウンロードしてください。macOS 上で、リポジトリのルートから以下のコマンドを実行します。Python 3.9 以降と、 xcrun usdchecker および xcrun usdcatを提供する Xcode が必要です。基本的な検証では、Python 標準ライブラリと、 /usr/bin/sips (画像の完全デコード用)、および Xcode の usdchecker および usdcat (モデルの検証用)を使用します。高度な雲、水の反射/接触、太陽を含まない空の検証には、NumPy と 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

出力先ディレクトリは、存在しないか空である必要があります。これらの小さな合成サンプルは形式を試すためのものです。グラデーションや立方体は、製品品質の風景や完成した Room ではありません。ソースと生成コンテンツのライセンスは Apache-2.0 です。詳細: サンプルの説明.

--current-app-version は、検証 対象の Locus バージョンを指定します。インストール済みアプリを更新したり、機能を使えるようにしたりするものではありません。ツールのデフォルト値は、安全側に設定した 1.0.0です。意図するバージョンを明示的に指定してください。完全なパッケージのインポートには Locus 1.2.1 以降が必要で、新しいフィールドにはそれぞれ固有の最低バージョンがあります。Room の地面と中景の制御項目には、対応する 1.4.4 以降のビルドが必要です。このガイドは、そのようなビルドが現在 App Store で提供されていると主張するものではありません。

独自のパッケージを制作するには、サンプルを編集可能なフォルダに展開するか、下記の構成を作成します。アセットと来歴情報を置き換え、独自の固定 ID を使用し、出力先をそのフォルダの 外 にしてください。

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

パッキングツールは files および contentHashを再計算し、アーカイブを検証してから出力します。既存の出力は上書きしません。編集可能なソースも変更しません。生成したパッケージは、 Places → インポート → View をインポート または Room をインポート → ファイルから、含まれているコンテンツの種類に合う入口を選んでインポートしてください。複合パッケージでは、内容がまとめてインストールされます。公開 HTTPS の ZIP 直接 URL も利用できます。完成した場所を共有する前に、制作した各座席、エフェクト、照明、サウンドを Apple Vision Pro で確認してください。

アーカイブ構成

example.locusplace
├── locusplace.json
└── catalog/
    ├── destinations/<destination-id>/
    │   ├── destination.json
    │   ├── provenance.json
    │   └── ...
    ├── spaces/<space-id>/
    │   ├── space.json
    │   ├── provenance.json
    │   └── ...
    └── experiences/<experience-id>/
        └── experience.json

ルートの locusplace.json 以外の通常ファイルのメンバーは、すべて filesに宣言する必要があります。宣言したファイルはすべて存在しなければなりません。アーカイブに含められるカタログコレクションは既知の 3 種類だけで、すべてのファイルは、 contentsで宣言されたパッケージ ID の配下になければなりません。Package v2 マニフェストは未知のフィールドに対する前方互換性を維持しますが、外側のラッパーの未知のフィールド、未対応の形式バージョン、コレクション、コンテンツモードは、安全のため拒否されます。来歴情報は公開スキーマに従う必要があります。

View のみ、または Room のみのアーカイブは、再利用可能なカタログコンテンツとしてインストールされます。カタログの参照解決が済むと、Locus がデフォルトの組み合わせを作ります。各 View と Your Room、および各 View と Destination 開口部を備えるすべての Room が対象です。明示的な Experience は、指定された組み合わせだけを置き換えます。同じアーカイブ内のコンテンツや、組み込み/インポート済みカタログに存在する固定 ID を参照できます。

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 とすべてのコンテンツ ID は、最大 128 バイトの固定 ASCII 識別子です。先頭は英字または数字で、以降に使えるのは英字、数字、 ., _、および -のみです。バージョンは必ず 3 つの数値で構成します。内容のバイト列が変わる更新では、宣言済みのコンテンツ ID を維持し、 contentVersionを以前より大きくします。同じ contentHash のインポートは冪等な処理で、何も変更しません。

contentHash は、すべてのファイルレコードを Unicode パス順にソートして算出した SHA-256 です。各レコードは、次の UTF-8 バイト列としてハッシュに加えられます。

path NUL decimal-byteCount NUL lowercase-sha256 NUL

このハッシュは、JSON の空白や ZIP 内のメンバーの順序には依存しません。バリデーターは、宣言された各ファイルをストリームで読みながら、実際のバイト数、ZIP CRC、SHA-256 も検証します。

ラッパーのフィールドリファレンス

フィールド 必須 意味
formatVersion はい 整数 1です。未知のラッパーバージョンは安全のため拒否されます。
packageID はい このインストール/更新系列の固定の識別情報。ファイル名ではありません。
contentVersion はい 3 つの数値で構成するバージョン。例: 1.2.0。同じ ID でバイト列が変わる場合はバージョンを上げます。
minimumAppVersion はい アーカイブをインポートできる最も古い Locus バージョン。これも 3 つの数値で構成します。
contents.destinationIDs はい この ZIP が所有する一意な View ID。 [] は、該当するものがない場合に使用します。
contents.spaceIDs はい この ZIP が所有する一意な Room ID。 [] は、該当するものがない場合に使用します。
contents.experienceIDs はい この ZIP が所有する一意な Experience ID。 [] は、該当するものがない場合に使用します。
files はい 全ペイロードファイルを網羅して生成した一覧。ただし、次のファイルを除きます: locusplace.json.
files[].path はい アーカイブを基準とする正規化された相対パス。 catalog/... です。
files[].byteCount はい 展開後の正確なバイト数。
files[].sha256 はい 展開後のバイト列の SHA-256。小文字の 16 進数 64 文字です。
contentHash はい 上記の正規化されたペイロード一覧を識別する SHA-256。

ZIP 内の Package v2 メタデータ

完全なラッパーは formatVersion: 1です。各 destination.json, space.json および experience.json で使用する形式は formatVersion: 2です。 フラット互換形式のリファレンス に記載された Room v1〜v10 の数字は、別系統のフラット形式の space.json 入力に属します。ベイク済みライトレイヤーを使用するために、完全な space.json のバージョンを 10 に変えないでください。完全なパッケージでは、省略可能な機能は型付きのフィールドで有効になります。最低アプリバージョンの制約を指定するのは minimumAppVersion.

パッケージ内のすべてのアセットパスは、ZIP ルートではなく、マニフェストのあるディレクトリを基準とする相対パスです。参照先は必ず、そのパッケージ内の通常ファイルでなければなりません。Package v2 の基本マニフェストはメタデータの前方互換性を認めますが、個々の機能プロファイルではフィールドを限定する場合があります。未知のフィールドが描画されることを前提にしないでください。外側のラッパーは未知のフィールドを拒否し、来歴情報は公開スキーマに従う必要があります。

座標系は右手系で、単位はメートル、上方向は +Y、前方は −Z です。クォータニオンは [x, y, z, w]です。変換には、 translationMeters (有限の数値 3 つ)、 orientationXYZW (長さがゼロでない、有限の数値 4 つ)、および scale (有限の正の数値 3 つ)を指定できます。

View: 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"
}
フィールド 必須 意味と検証
formatVersion はい 整数 2.
id はい View の固定 ID。ディレクトリ名およびラッパー内の ID と一致します。
title はい 空ではない、ユーザーに表示する View 名。
panorama.path はい パッケージを基準とする相対パスの最終版 JPEG または PNG。種類は拡張子だけでなく、デコードしたバイト列から判定します。
panorama.projection はい 値は equirectangular.
panorama.width, height はい デコード後の正の寸法を正確に宣言します。条件は width == 2 * height.
panorama.initialYawDegrees 任意 規定のパノラマ座標系内での、有限の回転角。デフォルトは 0.
sourceImage 任意 パッケージを基準とする相対パスの JPEG/PNG 監査画像(省略可能)。描画には使用しませんが、完全なパッケージでは、型、デコード結果、リソース上限を検証したデータとして保持できます。編集可能なソースや DCC ソースは実行時 ZIP に含めません。
thumbnail 任意 パッケージを基準とする相対パスの JPEG/PNG カタログ画像。
caption 任意 人が読むための説明。
generation.generator 任意 実際に使用した生成ツールなどの名称。
generation.model 任意 モデル/ワークフローのバージョン(省略可能)。
generation.generatedAt 任意 タイムスタンプ(省略可能)。RFC 3339 の UTC 形式を推奨します。
depthLayers[] Package v2 では不可。公開 ZIP インポートでは未対応 予約済みの、順序付き深度アセット。そのエンコーディングを製品の実行時処理とバイトレベルのバリデーターが使用するようになるまで、公開インポートではこのフィールドを拒否します。
midground.path 任意 両方の Experience Mode で実行時に描画する中景 USDZ。同梱、Library、インポートのいずれのパッケージでも、同じメンバー許可リスト、構造、リソース上限に従います。詳しくは 中景のリファレンス.
midground.transform 任意 有限値による変換(省略可能)。対象は midground.path.
midground.terrainEntities 任意 空ではない一意な地面ユニット名。対象のファイルは midground.pathに含まれます。実行時には、Room の設置領域の下にある地形の高さ調整に使用します。
midground.water 任意 アプリが描画する水の定義。検証済みのマスク/法線マップと、省略可能な岸辺のデータが含まれます。詳細は フィールドリファレンス.
sky 任意 アプリが描画するプロシージャルな夜空(星、天の川、省略可能なオーロラ)。検証済みの 2:1 グレースケール sky.maskを通して表示します。必要条件は minimumAppVersion >= 1.2.4を満たす必要があります。詳細: 空のリファレンス.
gpuTexture, gpuTextures 任意 検証済みの ASTC KTX1 サイドカー。ユーザーの ZIP と Library パッケージで同様に使用できます。v1 パノラマサイドカーに必要なバージョンは 1.2.3が必要です。v2 のソース画像配列には 1.3.0が必要です。ソースのハッシュ、寸法、ミップレベルが一致する必要があります。
water, clouds, fireflies 任意 実行時の水(発光を含む)、描き込まれた雲の動き、ホタルの定義。必要な条件: minimumAppVersion >= 1.3.0が必要です。参照先のアセットとリソース上限には、共通の Package v2 契約が適用されます。
environment.sunPath 任意 太陽を含まない制作済みの空と、省略可能なマスク付き太陽円盤。必要なバージョン: 1.3.0 と、制作時の証明が必要です。
celestial 任意 アニメーションする天体と参照テクスチャ。必要なバージョン: 1.2.4、または省略可能な機能で定められた、より新しい最低バージョンが必要です(雲のシェルの移動・変化には 1.3.0).
nearOrbit 任意 近軌道プロファイル、テクスチャアセット、コンテンツに紐づくフォールバックの証明。v1 と v2 の必要なバージョン: 1.3.0が必要です。v2 にはタイルマニフェスト、タイル画像、それらの GPU サイドカーが含まれます。
splat.variants, splat.ply Package v2 では不可。公開 ZIP インポートでは未対応 将来用に予約されたアセット参照。splat バックエンドは削除済みのため、公開インポートではフィールド全体を拒否します。
splat.metricScaleFactor Package v2 では不可。公開 ZIP インポートでは未対応 予約済み仕様における、有限の正のスケール。
splat.groundPlaneOffset Package v2 では不可。公開 ZIP インポートでは未対応 予約済み仕様における、制作時に指定した有限の地面オフセット。
splat.placement Package v2 では不可。公開 ZIP インポートでは未対応 予約済み仕様における、省略可能な共通の変換。
environment 任意 表示する View の明るさ、省略可能な小さな SDR Room 照明画像、および以下の直射日光のデフォルト設定。
audio.path Package v2 では不可。公開 ZIP インポートでは未対応 予約済みの実行時オーディオファイル。完全なオーディオのバイト検証と再生を製品がサポートするまで、公開インポートではこのフィールドを拒否します。
audio.loops Package v2 オーディオ使用時。公開 ZIP インポートでは未対応 予約済み仕様における繰り返しを制御する真偽値。
provenance インポート時は必須 パッケージを基準とする相対パスの来歴情報 JSON。

完全な ZIP は、このバイナリが実際に使用するフィールドに加え、 sourceImageなど、型とリソース上限を確認できるデータとして検証可能なペイロードも受け入れます。 midground は共通の実行時契約の一部です。必要な条件: minimumAppVersion >= 1.2.1. depthLayers, splat、および旧来の audio ブロックは、予約済みまたは廃止済みで、現在の実行時処理では使用しません。そのため、このバイナリは型を検証しないパスとして受け入れず、入手元にかかわらず拒否します。将来のバイナリがいずれかの機能を実装する場合は、そのフィールドのアセット参照、型とリソース上限の検証、実行時処理、最低アプリバージョンを共通契約に追加する必要があります。公開インポート専用のスイッチを追加してはいけません。

12,288×6,144(12K)は推奨解像度で、必須ではありません。 8,192×4,096、6,144×3,072、4,096×2,048 などの低い解像度も、厳密な 2:1 で、実際のデコード後の寸法を宣言していれば有効です。12K を名乗るためだけに、小さいソースを拡大しないでください。細部は増えず、メモリを浪費するだけです。

パノラマの座標は固定されています。 u = 0.5 は yaw 0、初期の前方、ワールドの −Z 方向です。 u は東の +X 方向に向かって増加します。継ぎ目は u = 0/1、yaw ±180° です。画像の最上行が天頂です。 initialYawDegrees は、この座標系の中で画像を回転させるもので、座標系自体を再定義するものではありません。

View の照明設定(省略可能):

{
  "environment": {
    "imageBasedLight": "thumbnail.jpg",
    "skyGainEV": 0,
    "exposureEV": 0,
    "horizonPitchDegrees": 0,
    "colorGrade": {"contrast": 1.15, "saturation": 1.2},
    "directSun": {"enabled": false, "illuminanceLux": 5000}
  }
}
フィールド 意味
imageBasedLight Room のジオメトリへの照明と反射だけに使う、別の 2:1 JPEG/PNG。 panorama.pathを流用してはいけません。1024×512 を推奨します。省略時は、レンダラーの中立的な代替照明を使用します。
skyGainEV 表示されるパノラマだけに適用する、有限の EV ゲイン。
exposureEV IBL だけに適用する、有限の EV ゲイン。
horizonPitchDegrees 制作時に指定する有限の水平線補正。
colorGrade.contrast 表示する SDR パノラマのコントラスト(省略可能)。範囲は 0.5 〜 2.0; 1.0 が中立値です。
colorGrade.saturation 表示する SDR パノラマの彩度(省略可能)。範囲は 0.0 〜 2.0; 1.0 が中立値です。
directSun.enabled 独立した平行光源を制作時に設定するかどうか。
directSun.azimuthDegrees, elevationDegrees 有限の方向角。有効な場合は両方必須です。
directSun.illuminanceLux 有限の非負の照度。

カラーグレーディングが影響するのは、表示される SDR パノラマだけです。同じテクスチャを再利用するため、View が HDR になったり、ソースにないハイライトの細部が追加されたりすることはありません。無効になっている太陽にも、 5000 lux を設定できます。このため、 太陽光を追加 は、パッケージで制作時に設定したオフの状態を変更せず、アプリのデフォルト値から始まります。

visibleSkyHDR および hdrManifest は廃止済みで、拒否されます。USDZ の外側にあるパッケージ内の EXR は、表示する View や Room 照明用のマップとしては使用できません。OpenEXR は Room アセットの USDZ テクスチャ形式として引き続き許可されており、モデル内で検証されます。

Room: 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"
}
フィールド 必須 意味と検証
formatVersion はい 整数 2.
id はい Room の固定 ID。ディレクトリ名およびラッパー内の ID と一致します。
title はい 空ではない、ユーザーに表示する Room 名。
scene はい パッケージを基準とする相対パスの自己完結型 USDZ。 .blend や、その他の制作ファイルで代用したり、それらを別の場所に同梱したりすることはできません。
thumbnail 任意 Room カードに表示する、パッケージを基準とする相対パスの JPEG または PNG。指定する場合はファイルが存在し、完全にデコードできる必要があり、アーカイブの画像リソース上限を共有します。省略すると代替のアイコンを使用します。
caption 任意 空ではない訪問者向けテキスト。表示先: この Room について。上限は UTF-8 で 2,000 バイトです。
previewCamera.yawDegrees, pitchDegrees 任意 範囲が限定された 3D プレビューの、有限の初期角度。没入体験での配置には影響しません。
previewCamera.zoom カメラ使用時 範囲が限定された 3D プレビューの、有限の正の初期スケール。リセットすると、制作時に指定したこの姿勢に戻ります。ビューアーは、操作可能な範囲に値を制限します。
seatedOrigin.translationMeters はい 制作時に定めた着座床基準の位置を表す、有限の 3 成分。単位はメートルです。
seatedOrigin.orientationXYZW はい 有限で正規化されたクォータニオンの 4 成分。着座座標系は直立を保つ必要があります(ピッチとロールは禁止)。
safeHeadVolume.centerMeters はい Room 座標系での、有限の 3 成分。単位はメートルです。
safeHeadVolume.sizeMeters はい 有限で、厳密に正の 3 つの寸法。
destinationOpenings はい 長方形の開口部の配列。単独の Room のみをインポートする場合は、必ず 1 つ必要です。ゼロまたは複数の場合は、 virtual-space の Experience を同じアーカイブ内に制作する必要があります。
destinationOpenings[].id 各エントリ Experience の組み合わせで使用する、パッケージ内で一意な ID。
destinationOpenings[].transform 各エントリ 必須の位置/クォータニオンによる姿勢。
destinationOpenings[].widthMeters, heightMeters 各エントリ 有限で、厳密に正の寸法。
collision.mode はい embedded または separate.
collision.path 条件付き 禁止となるモード: embedded。一方、 separateの場合は、パッケージを基準とする相対パスの自己完結型 USDZ が必須です。検証では、 sceneと同じメンバー、テクスチャ、ジオメトリの規則を適用します。このジオメトリとシーンのジオメトリは Room のリソース上限を共有します。制作ソースの名前を変えただけのファイルは無効です。
quality.status はい unverified または verified.
quality.triangleCount, materialCount, entityCount, maxTextureDimension はい 制作者が計測した非負の値。ゼロは未計測を意味します。実際の USD は別途検証します。
teleportCatalog.path はい パッケージを基準とする相対パスのテレポート JSON。選択した家には少なくとも 1 つのポイントが必要です。なければ、その Room は Virtual Space に入れません。JSON の上限は 1 MiB で、ファイル名が .jsonで終わらない場合も、フィールドの役割に基づいてこの上限を適用します。大文字と小文字の違いや Unicode によるファイルシステム上の別名で、この制限を回避することはできません。
teleportCatalog.houseID はい この JSON 内の、空ではない houses 配列を選択する ID。
spatialAdaptation.wallEntities 任意 壁を表す、空ではない一意な USD エンティティ名。このメタデータによって壁が非表示になることはありません。
spatialAdaptation.roofEntities 任意 空ではない一意な名前。壁の名前と重複してはいけません。
spatialAdaptation.deskEntitiesByTeleportID 任意 宣言済みのテレポート ID から、制作時に指定した空ではない机エンティティ名へのマッピング。
provenance はい パッケージを基準とする相対パスの来歴情報 JSON。

USDZ はメートル単位の右手系で、上方向は +Y です。サポート対象の実行時 USD、テクスチャ、オーディオメンバーだけを含めます。USDZ 内のメンバーは無圧縮で格納する必要があります。バリデーターは実際のステージを読み込んでフラット化し、ジオメトリを数えます。 quality の値が小さい場合やゼロの場合でも、大きすぎるモデルを隠すことはできません。

必須のテレポート JSON(選択した家に少なくとも 1 つのポイントが必要):

{
  "houses": {
    "example-room": [
      {
        "id": "work-desk",
        "title": "Work desk",
        "anchorXZ": [0.5, 0.5],
        "sourceFloorOffset": 0,
        "eyeHeight": 1.15,
        "yawRadians": 0
      }
    ]
  }
}

anchorXZ は、有限で正規化された 2 つの値で、範囲は 0...1; sourceFloorOffset は、制作モデルの単位で有限かつ非負です。 eyeHeight は、有限の正の値で、単位はメートルです。 yawRadians は、ワールド座標系の +Y 軸まわりの、有限のモデル回転角です。ポイント ID は一意で、タイトルは空であってはいけません。

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"]
  }
}
フィールド 必須 意味と検証
formatVersion はい 整数 2.
id はい Experience の固定 ID。
title はい 空ではない、ユーザーに表示するタイル名。
destinationID はい この ZIP 内、またはインストール済みの View の固定 ID。
spaceID 条件付き Room の固定 ID。必須となるモード: virtual-spaceで必須です。通常、次のモードでは省略します: room-portal.
supportedModes はい 空ではない、重複のない配列。指定できる値は virtual-space または room-portal.
composition.destinationOpeningID 条件付き 必須となるモード: virtual-space。参照先 Room の開口部を指定します。
composition.destinationYawDegrees 任意 この組み合わせの、有限の空の方向合わせオフセット。
composition.destinationPitchDegrees 任意 この組み合わせの、有限の空のピッチオフセット。
composition.destinationExposureOffsetEV 任意 この組み合わせの、有限の相対露出オフセット。
compatibility.minimumViewerVersion 任意 宣言的な最低ビューアーバージョン文字列。
compatibility.requiredCapabilities 任意 宣言的な機能文字列。

View のみ、Room のみの ZIP は、再利用可能なコンテンツとしてインストールされ、デフォルトの組み合わせに加わります。明示的な Experience が必要なのは、ある組み合わせの開口部、向き、露出、タイトル、モード、互換性を上書きする場合だけです。参照先は同じアーカイブ内、または組み込み/インストール済みの固定 ID から解決できます。解決できない参照があれば、インポート全体が失敗します。

省略可能な機能とラベルの翻訳

省略可能なフィールドは、それを所有する View または Room のマニフェストに追加し、参照するアセットをすべてそのマニフェストと同じ場所に配置します。 フィールドリファレンス では、メディアとマスク、サウンドと Room の音楽、中景と風、水、空、雲、太陽の軌道、天体、近軌道、ブラックホール、ポイントライト、GPU テクスチャサイドカー、座席とグループ、照明、アニメーション、ビデオサーフェス、パーティクル、ベイク済みライトレイヤーを扱います。また、 localizations, provenanceDetail、および Room の viewGroundFloorOffsetMeters, viewGroundKeepOut、および viewMidgroundVisibility の制御項目も定義しています。

たとえば、これらの省略可能なフィールドは、それ以外の必須項目がそろった Room マニフェストに含めます。外側のラッパーに必要なバージョン指定は minimumAppVersion: "1.4.4" 以降です。

{
  "viewGroundFloorOffsetMeters": 0.2,
  "viewGroundKeepOut": false,
  "viewMidgroundVisibility": "terrainOnly"
}

これらの意味は、インポート、同梱、Library のいずれのコンテンツでも変わりません。フィールドリファレンスの Library 機能名は Library オファーに属するものです。独自の requiredCapabilities フィールドを locusplace.jsonに追加しないでください。完全なパッケージのインポート処理では、最低アプリバージョンと、型に基づくコンテンツ自体の検証を行います。

必須の来歴情報

インポートするすべての Destination と Space は、来歴情報の JSON ドキュメントを参照します。そこには制作者/エージェンシー、ライセンスまたは全著作権を留保する旨の声明のいずれか一方、希望するクレジット表記、変更内容、AI 使用の有無、該当する場合は AI プロバイダーを記録します。ソース/元アセットの URL は省略可能ですが、認証情報やフラグメントを含まない HTTPS URL でなければなりません。来歴情報が欠落している、大きすぎる、または不正な場合は、インポート全体が失敗します。詳細: 来歴情報のリファレンス.

{
  "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
}
フィールド 必須 意味と制約
formatVersion はい 整数 1.
creatorOrAgency はい 空ではない制作者/スタジオ名。上限は 200 文字です。
sourcePageURL 任意 公開 HTTPS のプロジェクトページ。認証情報やフラグメントは禁止です。
originalAssetURL 任意 公開 HTTPS のソースページ。元ファイルを埋め込まずに出所を記録します。
license.identifier 条件付き 空ではない識別子。上限は 100 文字です。 licenseがある場合は必須です。アセットのライセンスを選ぶのは Locus ではありません。
license.name 条件付き 空ではない名前。上限は 200 文字です。次のオブジェクトがある場合は必須: license.
license.url 条件付き 公開 HTTPS のライセンス URL。次のオブジェクトがある場合は必須: license.
rights.statement 条件付き 空ではない権利声明。上限は 1,000 文字です。組み合わせる URL: rights.url 。この組み合わせを使う場合、代わりに省略するのは license.
rights.url 条件付き 公開 HTTPS の権利声明 URL。 license または rights のいずれか一方が必須です。
requestedCredit はい 空ではないクレジット表記。上限は 1,000 文字です。
modificationNotes はい 空ではない準備・加工内容の記録。上限は 2,000 文字です。
aiGenerated はい 真偽値。
aiProvider 条件付き 次の場合は空ではない値が必須: aiGenerated は trueの場合は必須です。false の場合は禁止です。上限は 200 文字です。
importSource 任意 Locus が画像から直接作成する View 用に予約されています。 photos, files、または urlです。サードパーティ製パッケージでは省略してください。

ドキュメントの上限は 64 KiB です。アセットを置き換えた後に、ひな形の来歴情報をそのまま流用しないでください。リポジトリのライセンスとユーザーのアセットのライセンスは、別々の宣言です。

ZIP は実行時の配布物であり、制作データのバックアップではありません。すべてのペイロードファイルは、認識される Package v2 のアセットフィールドから参照される必要があります。参照されていないファイルは、次の一覧に記載されていても拒否されます: locusplace.json.files. .blend, .blend1, .blend2, .fbx, .obj, .mtl, .gltf、および .glb ファイルは、宣言されていても拒否されます。これらのソースファイルは ZIP の外に保持してください。Room には最終版の USDZ を、View のパッケージには最終版の 2:1 パノラマと、省略可能な小さな 2:1 JPEG/PNG Room 照明用画像 1 枚を格納します。

セキュリティとリソース上限

検証対象は拡張子ではなくバイト列です。パストラバーサル、絶対パスや非正規パス、バックスラッシュ、制御文字、大文字と小文字/Unicode の衝突、シンボリックリンク、重複エントリ、暗号化コンテンツ、未宣言ファイル、ハッシュ不一致、未対応マニフェスト、不正な画像、USDZ 内の無効な EXR テクスチャ、不正な USDZ 構造、圧縮された USDZ メンバー、未対応の USDZ アセット型を拒否します。Room のリソース上限は、システムのローダーが実際に解析する USD ステージを対象に検証します。自己申告の品質ブロックは制作メタデータであり、実際のカウントを減らすことはできません。

バイトレベルの画像許可リストは厳密です。インポートするパノラマ、 sourceImage, thumbnail、および imageBasedLight のラスター画像フィールドは JPEG または PNG に限られます。USDZ テクスチャは JPEG、PNG、OpenEXR を使用できます。ImageIO でデコードできても、それ以外の形式は暗黙に受け入れず、拒否します。パッケージ外側の 3D 制作形式も拒否されます。USDZ に含められるメンバーは、USD/USDA/USDC、JPEG、PNG、OpenEXR、M4A、WAV、MP3 だけです。

リソース v1 の上限
ダウンロードまたはローカルアーカイブ 1 GiB
ZIP エントリ数 4,096
ルートマニフェスト 1 MiB
各ペイロードファイル 768 MiB
展開後のペイロード合計 2 GiB
圧縮率 200:1
インポートされる各 JSON ファイル 1 MiB
来歴情報 JSON 64 KiB
画像の寸法 32,768 px
画像 1 枚 1 億 5,000 万ピクセル
View の全画像 5 億ピクセル
USDZ エントリ数 4,096
USDZ ファイル/展開後のバイト数 768 MiB/1.5 GiB
USDZ テクスチャの寸法/総ピクセル数 16,384 px/5 億ピクセル
読み込んだ Room のジオメトリ 三角形 500 万個、マテリアル 1,024 個、エンティティ 100,000 個

ファイルと URL からの取得

View の場合、インポートページでは、写真、ファイル、または公開 HTTPS の直接 URL から JPG、PNG、HEIC の画像を 1 枚取り込めます。Locus は画像を Destination のみの Package v2 ペイロードに正規化し、一時的なパッケージを同じバリデーターとアトミックなインストーラーで処理します。ファイルと URL からは、View および Room の完全な Package v2 ZIP も取り込めます。複合パッケージも、訪問者が選んだ種類のコンテンツを含んでいれば取り込めます。既存のフラット形式の View/Room ZIP も、互換入力として引き続き利用できます。不正なアーカイブに locusplace.json が含まれている場合は、無効な完全パッケージとして拒否されます。フラット形式のパーサーにフォールバックすることはありません。URL インポートでは、認証情報、フラグメント、localhost、 .local、非公開の DNS 解決結果は拒否されます。ホスト名はリクエストごとに一度解決し、すべての応答が公開アドレスである必要があります。TLS ソケットは元のホスト名を認証しつつ、解決で得たその IP アドレスに接続します。リダイレクトのたびに、新しい接続の前にこの名前解決と接続先固定を繰り返します。リダイレクトは最大 5 回までで、申告されたダウンロードサイズと実際の受信サイズの両方に上限を設けています。

検証とカタログの参照解決は、同じボリューム上の非公開ステージングディレクトリで完了します。ライブラリ全体のアドバイザリーロックにより、一覧作成、容量制限の検査、確定処理を直列化します。初回インストールには排他的なアトミックリネームを、更新にはアトミックなディレクトリ交換を使用します。失敗するとステージングを削除し、インストール済みパッケージは変更しません。

パッケージの検証とサンプル

以下のコマンドは、公開と全機能に対応したインポートで使用する、完全な Package v2 ラッパーを作成・検証します。旧来のフラット形式ツールについては、引き続き次の文書で説明しています: locus-asset-format.md.

どちらの拡張子でも、インストールせずに検証できます。

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

Python コードでは、標準ライブラリ、macOS の ImageIO を利用する /usr/bin/sips、および USD ツールの usdchecker および usdcat (Xcode/Command Line Tools とともにインストールされます)を使用します。ImageIO は JPEG または PNG の構造を検証した後、すべてのピクセルをデコードします。EXR の検証対象は USDZ 内のテクスチャに限られます。USD ツールは実際の Room ステージを読み込み、フラット化し、計測します。失敗時はゼロ以外の終了コードを返し、アーカイブ、整合性、Package v2、来歴情報、画像/EXR、USDZ を検証します。インストールとカタログ間の参照解決については、visionOS のインポーターによる判定が最終的なものとなります。

編集可能なディレクトリを通常の ZIP にパッキングします。整合性レコードをすべて再計算し、このバリデーターが結果を受理した場合に限って出力します。

python3 tools/pack_locusplace.py --current-app-version 1.4.4 MyEditablePlace MyPlace.zip

View のみ、Room のみ、複合の実際のサンプルアーカイブを一時ディレクトリまたは Git の追跡対象外のディレクトリに生成し、検証します。

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

サンプルは、非公開アセットのダウンロードや有料サービスの呼び出しをせずに、ソースから生成されます。ビルダーと想定される構成については、次の文書を参照してください: サンプルの README.