OpenSubdiv で mesh smooth のメモ

## 背景

とりあえず Low poly なメッシュを入力したら, subdivision surface で smooth なメッシュを生成して, subdivide された形状情報(vertices, normals, uvs, ...)がほしい.

レイトレレンダー時に subdiv したいのであれば, embree の subdivision surface 機能を使う手もあります(API はとっても使いやすい)

https://www.embree.org/api.html

が, これだと subdivide されたメッシュは取得できないっぽい?

## OpenSubdiv

http://graphics.pixar.com/opensubdiv/docs/intro.html

雰囲気で subdiv したいために OpenSubdiv を使うのは, OpenSubdiv の API が非常にややこしいのでおすすめしません.
オフラインであれば Blender で十分かもしれません(メッシュは .obj で import/export). 代替案を検討してみてダメだったら OpenSubdiv を使いましょう.

### ビルド

オフィシャルだといろいろ機能つけていて, ビルドが面倒です.

https://github.com/syoyo/opensubdiv-aarch64

Android(AARCH64)対応の port(`aarch64` branch)を作りました. x86 も対応しています. 依存ライブラリなしで CPU only のビルドのスクリプトを作りましたので, 可能なかぎりこちらを利用ください.

https://github.com/syoyo/OpenSubdiv-aarch64/blob/aarch64/scripts/bootstrap-linux-mindep.sh

PTex はお好みで追加して.

https://github.com/syoyo/ptex-aarch64

PTex aarch64 版もあります.

ちなみに OpenSubdiv 自体は Ptex は使っていません(example のコードで ptex を使っている)ので, 基本 Ptex off でよいです.

Windows(MSVC) も, たぶん OpenSubdiv-aarch64 でビルドはできると思いますが, 以下では Linux を基本とします.

### 利用方法

基本的には template class を作ってユーザ定義アクセスメソッドを提供して対応していきます(NanoRT 的な使い方ですね)

git repo の example コードは実装がややこしい(+ GPU backend を想定したテンプレートクラスを使っているため, CPU backend だと動作しない)のでおすすめしません.

OpenSubdiv ページの tutotiral がよいでしょう.

https://graphics.pixar.com/opensubdiv/docs/tutorials.html

最低限, 以下の形状データが必要になります.

* 頂点データ
* face を構成する頂点の index データ
* face(面)が何頂点持つかの情報(3 = triangle, 4 = quad)
  * 全ての面が quad であれば省略も可能

自前のデータを処理させたい場合は, 基本四角形オンリーのメッシュを用意して(.obj, .ptx, etc), 上記のデータ構造にしておきます.

tutorial を参考に, .ptx から形状情報を読んで subdivide できました.

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Subdivision Surface with OpenSubdiv   is ... super fun!!! (visualization by NanoRT ray tracer) 🤩🤩🤩🤩🤩🤩😍😍😍😍😍🎉🎉🎉🎉🎉🎉🎉🎉✌️✌️✌️✌️✌️💯💯💯💯💯💯💯💯💮💮💮💮💮 <a href="https://t.co/fKqMIZLAUg">pic.twitter.com/fKqMIZLAUg</a></p>&mdash; Syoyo Fujita 🌸  RayWa(Ray and Peace) (@syoyo) <a href="https://twitter.com/syoyo/status/1195332520788647936?ref_src=twsrc%5Etfw">November 15, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


### Uniform Catmark subdivision

一様分割 + **Catmark**(カットマーク? Catmull-Clark subdivision の短縮系)ルールでまあ普通の利用用途はほぼカバーできるかと思います. Far tutotiral 2 あたりまでやればよいでしょう.

ちなみに Clark のほうは **SGI と Netscape の創立でがっぽがっぽして富豪**になっています.

https://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
https://en.wikipedia.org/wiki/James_H._Clark


### 用語

OpenSubdiv は独自用語があって面倒です.

* Sdc : Subdivision core
* Vtr : Vectorized topology refiner.
* Far : Feature-adaptive refinement(とりあえずは subdiv 分割のルール本体と考えればいいのかしらん?)
* Osd : SubD 補間する?
* Hbr : Hierarchical Boundary Representation
* Primvar : normal uv, 頂点カラーなどの頂点アトリビュート. subdivision するときはこの値が補間される.
  * 頂点データは基本 face-varying とする.

http://graphics.pixar.com/opensubdiv/docs/subdivision_surfaces.html

説明を読んでおくと理解が進みます.

### トポロジ固定 subdivision, crease, adaptive subdivision など

メッシュのトポロジが一定であれば(e.g. blendshape や skinning 変形など, animation したあとに subdivision をかけたい), 分割ルールを事前に計算しておいて, subdivision の高速化を図ることができるのが容易に予想されます.
PatchTable, StencilTable などを使えばいけるのかしら?

edge crease や adaptive 分割などは, これは example のコードを見た方がはやそうでしょうか.

OpenSubdiv のサンプルでは crease tag などの情報を .obj に拡張で指定しています.

一応 TinyObjLoader でも, OpenSubdiv サンプルの .obj の tag のロードに対応していますので, .obj から tag 情報を読んで subdv かけたい場合に利用できそうです.

https://github.com/syoyo/tinyobjloader/blob/master/tiny_obj_loader.h#L340


### Vulkan 対応

https://github.com/PixarAnimationStudios/OpenSubdiv/issues/1153

まだされていません.

## TODO

* GPU backend を試す.
* libigl あたりに subdivision surface 機能が無いか調べる.
* 隣接情報を取得して, ptex と連携をとる(ptex 用の機能が OpenSubdiv にあったような).
* Embree のコードあたりを参考にして, 自前 Subdivision surface 実装を行う.
* **優秀な OpenSubvid 若人さまが, 人類史上最速で優秀な OpenSubdiv + Vulkan 若人さまへと昇華なされるスキームを確立する旅に出たい**