mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-27 21:34:38 -05:00
ドキュメント整理
This commit is contained in:
@@ -1,47 +0,0 @@
|
||||
# FastSpringBoneについて
|
||||
|
||||
## 概要
|
||||
UniVRMでは、DOTSを利用した高速なSpringBone実装である「FastSpringBone」を用意しています。
|
||||
|
||||
揺れ物の各房を並列処理・最適化することで1フレームあたりの処理時間を大幅に抑えます。
|
||||
|
||||
VRM0.x と VRM1.0 で、それぞれFastSpringBoneの立ち位置・実装が異なります。
|
||||
|
||||
## VRM 1.0 での FastSpringBone の概要
|
||||
VRM1.0ではFastSpringBoneが揺れものの標準実装です。
|
||||
|
||||
VRMのライフサイクルに紐付いて自動的に生成・破棄されます。
|
||||
|
||||
## VRM 0.x での FastSpringBone の概要
|
||||
VRM0.xでは後方互換性を保つため、デフォルトでは従来のDOTS実装でないSpringBoneで動作します。
|
||||
|
||||
VRM0.x向けのFastSpringBone実装は `VRM/Runtime/FastSpringBone` ディレクトリにあります。
|
||||
|
||||
## VRM 0.x での FastSpringBone の導入方法
|
||||
差し替えを行いたいタイミングで `FastSpringBoneReplacer.ReplaceAsync` を呼び出してください
|
||||
|
||||
これを明示的に呼ばなければ、従来のSpringBoneのまま動作します。
|
||||
|
||||
```csharp
|
||||
using (var loader = new UniGLTF.ImporterContext(data))
|
||||
{
|
||||
var instance = await loader.LoadAsync();
|
||||
SetModel(instance);
|
||||
}
|
||||
FastSpringBoneReplacer.ReplaceAsync(instance.Root)
|
||||
|
||||
instance.EnableUpdateWhenOffscreen();
|
||||
instance.ShowMeshes();
|
||||
```
|
||||
|
||||
## Burstの導入について
|
||||
UniVRM に加えて Burst を別途導入すると、 FastSpringBone が Burst によって高速化されます。
|
||||
|
||||
Burst の導入方法は [こちら](https://docs.unity3d.com/ja/2019.4/Manual/upm-ui-install.html) をご参照ください。
|
||||
|
||||
## FastSpringBoneServiceについて
|
||||
FastSpringBone が実行されると、`FastSpringBone Service` GameObject が `DontDestroyOnLoad` で生成されます。
|
||||
|
||||
これは全 VRM の FastSpringBone を集め、バッファの構築や、 FastSpringBone の実行タイミングの制御などを行う GameObject です。
|
||||
|
||||
明示的に破棄を行いたい場合は `FastSpringBoneService.Free` を呼んでください。
|
||||
99
docs/implementation/format.md
Normal file
99
docs/implementation/format.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# glbフォーマット概説
|
||||
|
||||
JSON記述部と、画像や頂点配列を記録するバイナリ部の2つの部分からなります。
|
||||
|
||||
gltf形式では、URLやパスで参照する方法で外部のバイナリデータにアクセスします。
|
||||
glb形式ではJSON部とバイナリ部をひとつのファイルにまとめていて、バイト列のオフセットでバイナリデータにアクセスします。
|
||||
プログラムから扱うには外部ファイルへのアクセスが無いglb形式の方が簡単[^VRM_glb]です。
|
||||
|
||||
[^VRM_glb]: VRMではglbを採用しています。
|
||||
|
||||
## glb形式
|
||||
|
||||
``ヘッダ部 + チャンク部繰り返し``という構造になっています。
|
||||
実質的には、
|
||||
``ヘッダ部 + JSON CHUNk + BINARY CHUNK``となります。
|
||||
|
||||
ヘッダ部
|
||||
|
||||
| 長さ | 内容 | 型 | 値 |
|
||||
|:-----|:---------------|:------|:-------|
|
||||
| 4 | | ascii | "glTF" |
|
||||
| 4 | gltfバージョン | int32 | 2 |
|
||||
| 4 | file size | int32 | |
|
||||
|
||||
チャンク部
|
||||
|
||||
| 長さ | 内容 | 型 | 値 |
|
||||
|:-----------|:-----------|:---------|:--------------------|
|
||||
| 4 | chunk size | int32 | |
|
||||
| 4 | chunk type | ascii | "JSON" or "BIN\x00" |
|
||||
| chunk size | chunk body | バイト列 | |
|
||||
|
||||
### python3によるパース例
|
||||
|
||||
```python
|
||||
import struct
|
||||
import json
|
||||
|
||||
class Reader:
|
||||
def __init__(self, data: bytes)->None:
|
||||
self.data = data
|
||||
self.pos = 0
|
||||
|
||||
def read_str(self, size):
|
||||
result = self.data[self.pos: self.pos + size]
|
||||
self.pos += size
|
||||
return result.strip()
|
||||
|
||||
def read(self, size):
|
||||
result = self.data[self.pos: self.pos + size]
|
||||
self.pos += size
|
||||
return result
|
||||
|
||||
def read_uint(self):
|
||||
result = struct.unpack('I', self.data[self.pos:self.pos + 4])[0]
|
||||
self.pos += 4
|
||||
return result
|
||||
|
||||
|
||||
def parse_glb(data: bytes):
|
||||
reader = Reader(data)
|
||||
magic = reader.read_str(4)
|
||||
if magic != b'glTF':
|
||||
raise Exception(f'magic not found: #{magic}')
|
||||
|
||||
version = reader.read_uint()
|
||||
if version != 2:
|
||||
raise Exception(f'version:#{version} is not 2')
|
||||
|
||||
size = reader.read_uint()
|
||||
size -= 12
|
||||
|
||||
json_str = None
|
||||
body = None
|
||||
while size > 0:
|
||||
#print(size)
|
||||
|
||||
chunk_size = reader.read_uint()
|
||||
size -= 4
|
||||
|
||||
chunk_type = reader.read_str(4)
|
||||
size -= 4
|
||||
|
||||
chunk_data = reader.read(chunk_size)
|
||||
size -= chunk_size
|
||||
|
||||
if chunk_type == b'BIN\x00':
|
||||
body = chunk_data
|
||||
elif chunk_type == b'JSON':
|
||||
json_str = chunk_data
|
||||
else:
|
||||
raise Exception(f'unknown chunk_type: {chunk_type}')
|
||||
|
||||
return json.loads(json_str), body
|
||||
|
||||
|
||||
with open('AliciaSolid.vrm', 'rb') as f:
|
||||
parsed, body = parse_glb(f.read())
|
||||
```
|
||||
@@ -6,8 +6,8 @@
|
||||
runtime_resource_management
|
||||
texture_manipulation
|
||||
coordinate
|
||||
fast_spring_bone
|
||||
first_person
|
||||
scripted_importer
|
||||
transparent_zwrite
|
||||
format
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user