Rust+WebAssembly+WebGL で八胞体(4次元超立方体)の描画
この記事はWebグラフィックスAdvent Calendar 2020 の25日目の記事です。
はじめに
今年になってからRust言語の勉強を始めまして、畳の上の水練で終わらないように
WasmとWebGLを利用して4次元図形を表示させてみることにしました、が、
RustコードとJavaScriptコードでのデータのやり取りに七転八倒、やっとのことで
とうとうなんとか動作するようになりましたので、初投稿してみることにしました。
参考にさせていただいた記事です:
RustでWebAssembly: Rust内から requestAnimationLoop() でループさせたり、on_click()を登録する
Rust(wasm)とJavaScript(WebGL)のデータ受け渡し Rust+WebGLでポリゴン描画 (1/2)
wasm-bingenのページでは"1.4 Without a Bundler"を参照し、node.js等がいらない形で(必要な部分はコードに埋め込まれている)構築しました。
四次元オブジェクトの描画法について
三次元での三角ポリゴン描画からの類推で、四次元では三角錐でオブジェクト表面(表体?表胞?)を構成しました。
八胞体なので8つの立方体からなっています。
八胞体の3次元への展開図
各立方体を5つの三角錐に分割すれば計40個の三角錐で八胞体が構成できます。
立方体の三角錐への分解図
この三角錐群を4次元のアフィン変換を行った後、4次元方向への座標が0である3次元空間で切断して目的の図形(三角ポリゴン群)が得られます。
4次元空間において三角錐を3次元空間で切断した場合、以下のパターンで三角形を生成します。
- 三角錐がすべて3次元空間に含まれる場合。
4つの三角形を流用します。 - 一面(三角形)が3次元空間に含まれる場合。
1つの三角形を流用します。 - 三角錐が切断され、1頂点のみが異なる側にある場合。
1つの三角形を新たに生成します。最も多いパターンです。 - 三角錐が切断され、2頂点づつが異なる側にある場合。
2つの三角形を新たに生成します。 - 三角錐が3次元空間と交わらない場合(1点・1辺のみ含まれる場合を含む)。
三角形を生成しません。
生成三角形
Rustのパターンマッチングが非常に有用でした。
立方体からできる平面
回転がなければ、立方体一つからだいたいこのような平面が6つ出来ます。
これを改めて視点座標系の変換を行えば画面に表示できるわけです。
- ローカル変換は4次元で行う。
- 変換したものを3次元で切断。
- 視点変換は3次元で行う。
で、出来たものがこれ。多少回転させてあります。
また、市松模様の床は普通の3次元ポリゴンです。
記事内に一片のコードも無くて申し訳ありません。
ソースコードと、動作しているものは以下にあります。
デモ(ホームページ)
また、ホームページにはJavaScriptのコードですが4次元を歩くオブジェクトなどや3Dテクスチャを貼った八胞体なども置いてあります。それぞれ多少ですが操作可能です。
ただし、最新のものの動作確認はChromeでしか行っておりません。悪しからず。