SOG / SPZ / PLY Actors:単一ファイルの 3DGS 読み込み
ASogActor、ASpzActor、APlyActor の 3 つの Actor はそれぞれ .sog、.spz、.ply の 3 形式に対応し、単一の 3DGS ファイルを読み込むために使う。LCC のディレクトリ構造は不要である。いずれも ALCCActorBase を継承する。
| モジュール | LCC4UnrealRuntime |
| ヘッダーファイル | SogActor.h、SpzActor.h、PlyActor.h |
| 親クラス | ALCCActorBase |
| 内部の Component | ULCC2Component |
#include "SogActor.h"
#include "SpzActor.h"
#include "PlyActor.h"
3 つはいずれも内部で仮想の FLCC2MetaInfo を構築して完全な LCC2 のレンダリングパイプラインを再利用する。つまり LCC2 の機能はこの 3 形式でも同様に使える。球面調和の次数の制御、ライティングの法線モード、クリッピングと断面、カラー調整を含む。同様に LCC2 パイプラインの制限も一緒に継承する。たとえば複数ビューポートのインターフェースが効かない点である。
Supported Formats
| Actor | 拡張子 | 適する場面 |
|---|---|---|
ASogActor | .sog | 圧縮形式。サイズが小さく読み込みが速い |
ASpzActor | .spz | 圧縮形式 |
APlyActor | .ply | 汎用の点群 / 3DGS の交換形式。多くの学習ツールのネイティブな出力 |
各形式の対応範囲は 概要 - 対応形式 を参照する。
Comparison with LCC Directory Formats
.sog / .spz / .ply | LCC / LCC2 のディレクトリ | |
|---|---|---|
| ファイルの構成 | 1 つのファイル | メタ情報ファイル + 複数のデータブロック |
| LOD の階層 | なし | あり。距離に応じたストリーミング読み込み |
| 適する規模 | 中小規模のシーン | 大規模なシーン |
| コリジョンデータ | なし | ありうる |
| 配布のしやすさ | 高い。単一のファイル | ディレクトリを完全に保つ必要がある |
選択の基準:データ量が大きくない、素早く効果を検証したい、単一ファイルで配布したい場合はこの 3 形式を使う。大規模なシーンで LOD によってパフォーマンスを制御する必要がある場合は、LCC / LCC2 のディレクトリ形式を使わなければならない。
Methods
3 つの Actor の公開インターフェースはすべて ALCCActorBase から継承しており、次のメソッドのみをオーバーライドしている。
SelectFile
// ASogActor
virtual void SelectFile() override; // ダイアログは .sog のみを一覧に出す
// ASpzActor
virtual void SelectFile() override; // ダイアログは .spz のみを一覧に出す
// APlyActor
virtual void SelectFile() override; // ダイアログは .ply のみを一覧に出す
ファイル選択ダイアログを表示し、それぞれ対応する拡張子でフィルターする。Details パネルでは Load ボタンとして表示される。
エディターでのみ利用でき、パッケージ化した後の実行時は Load を使う。
Load(APlyActor のみオーバーライド)
// APlyActor
virtual void Load(const FString& String) const override;
.ply ファイルを読み込む。拡張子が .ply でないパスは直接拒否され、解析を試みない。
ASogActor と ASpzActor は Load をオーバーライドしておらず、基底クラスの実装を使う。
Examples
単一の .sog ファイルを読み込む
#include "SogActor.h"
#include "LCC2Component.h"
void AMyLoader::LoadSogFile()
{
ASogActor* SogActor = GetWorld()->SpawnActor<ASogActor>(
ASogActor::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator);
if (!SogActor)
{
return;
}
SogActor->Load(TEXT("D:/Data/scene.sog"));
// 内部は ULCC2Component なので、LCC2 の機能をすべて使える
ULCC2Component* Comp = Cast<ULCC2Component>(SogActor->GetLCCComponent());
if (Comp)
{
Comp->SetSHBands(2);
Comp->SetSplatScale(0.9f);
}
}
拡張子に応じて Actor を自動的に選ぶ
形式ごとに専用の Actor があるため、実際のプロジェクトでは拡張子に応じて振り分ける必要が出てくることが多い。
これを行うために DetermineFileFormat に依存しないよう注意する。この関数は .lcc、.splats、.las、.ply のみを識別し、.lcc2、.sog、.spz にはすべて None を返す。拡張子を直接判定するほうが確実である。
#include "Tools/LCCUtilLibrary.h"
#include "LCCActor.h"
#include "LCC2Actor.h"
#include "SogActor.h"
#include "SpzActor.h"
#include "PlyActor.h"
ALCCActorBase* AMyLoader::LoadAnyFormat(const FString& Path)
{
if (!ULCCUtilLibrary::CheckPathValid(Path))
{
UE_LOG(LogTemp, Error, TEXT("Path does not exist: %s"), *Path);
return nullptr;
}
const FString Ext = FPaths::GetExtension(Path).ToLower();
UClass* ActorClass = nullptr;
if (Ext == TEXT("lcc")) ActorClass = ALCCActor::StaticClass();
else if (Ext == TEXT("lcc2")) ActorClass = ALCC2Actor::StaticClass();
else if (Ext == TEXT("sog")) ActorClass = ASogActor::StaticClass();
else if (Ext == TEXT("spz")) ActorClass = ASpzActor::StaticClass();
else if (Ext == TEXT("ply")) ActorClass = APlyActor::StaticClass();
if (!ActorClass)
{
UE_LOG(LogTemp, Error, TEXT("Unsupported format: %s"), *Path);
return nullptr;
}
ALCCActorBase* Actor = GetWorld()->SpawnActor<ALCCActorBase>(
ActorClass, FVector::ZeroVector, FRotator::ZeroRotator);
if (Actor)
{
Actor->Load(Path);
}
return Actor;
}
Blueprint には拡張子を直接取得するノードがないので、文字列で判定できる。
[Custom Event: LoadAnyFormat]
Path (String)
│
▼
[Check Path Valid]
Path = Path
│ Return Value ──┐
▼ │
[Branch] ◀───────────────┘
│ True
▼
[Ends With]
Source String = Path
In Suffix = ".sog"
Search Case = Ignore Case
│ Return Value ──┐
▼ │
[Branch] ◀───────────────┘
│ True
▼
[Spawn Actor from Class]
Class = SogActor
│ Return Value ──┐
▼ │
[Load] ◀─────────────────┘
Target = (Return Value)
String = Path
(False の分岐で Ends With を使って ".spz"、".ply"、".lcc2"、".lcc" を続けて判定する)
Notes
- この 3 形式には LOD の階層がない。読み込み時に構築されるのは単層で単一ノードのツリー(総階層数が 1、ルートノードに子がない)なので、
StartLevel、EndLevel、LevelFactorといった LOD のパラメーターは読み取られはするが、選択できる階層がないため実際には効果を生まない。パフォーマンスの制御は主にMaxSplatNumとSplatScaleで行う。 - この 3 形式はコリジョンデータを持たない。代替手段は コリジョン - 単一ファイル形式の代替手段 を参照する。
- データ量が大きいファイルは一度にすべて読み込まれるため、ビデオメモリの使用量は一定で視点によって変化しない。読み込みの上限と計算方法は レンダリング - 単一ファイル形式の読み込み上限 を参照する。
- LCC2 のレンダリングパイプラインを通るため、基底クラスの複数ビューポートのインターフェースは適用されない。
- 3 つはいずれも構築時に Component の
bUseMipFilterをfalseに設定し(基底クラスの既定はtrue)、Actor の回転を(0, 0, 90)に設定する。 .plyにはいくつかのサブ形式がある。プラグインが対応するのは 3DGS の属性を含む派生形式である。通常のジオメトリメッシュの.plyは読み込みに失敗する。
See Also
- ALCCActorBase:継承してくるすべてのインターフェース
- ULCC2Component:この 3 つの Actor が内部で使うコンポーネント
- ULCCUtilLibrary:形式の識別とパスの検証