computer graphics」タグアーカイブ

GLMのマニュアルがヘボいので自分で書き始めた

GLM — OpenGL Mathematics というC++のライブラリーがある。これはOpenGLとかで使うようなベクトルや行列の型・関数を提供してくれる。

それはいいのだが、これ、ドキュメントがヘボい。

まず公式の Manual は、ライブラリーの使い方を説明してくれるが、個々のAPIには立ち入らない。

次にDoxygenで生成された API Documentation は、個々の関数の説明をしてくれるが、(ベクトルとか行列の)型の説明が欠けている。そして、「ソースコードに飛ぶ」をやっても関数の実装は見れない(.hppはDoxygenの対象に入っているが.inlは入っていない)。関数がどういう数式を基に実装しているのか、GLMのドキュメントからはわからないのである。

まあGLMはGLSL互換を謳っているので、GLSLを知っていれば(GLSLのドキュメントを読めば)細かい説明はなくても使えるだろうという考えもあるかもしれない。それはまあそうかもしれないが、GLSLにないGLMの拡張機能に関してはそういうわけにはいかない。

たとえば、四元数に関連した mat4_cast 関数のドキュメントには

GLM_FUNC_DECL mat<4, 4, T, Q> glm::mat4_cast ( tquat< T, Q > const & x )

Converts a quaternion to a 4 * 4 matrix.

Template Parameters
T Floating-point scalar types.
See also
GLM_GTC_quaternion

とあるが、果たしてこの説明から関数の動作を予想できる人がどれだけいるだろうか?

したがって、(コピペコーディングではなく)GLMをまともに使おうとしたらGitHubのソースコードをチマチマ眺める必要があるわけだが、そんなのは辛すぎる。というか、LaTeXでもMathJaxでもいいから、数式をふんだんに使ったGLMのマニュアルが欲しい…。

というわけで、自分で書いてみることにした。

https://miz-ar.info/glm-notes/

現段階ではまだ、クォータニオン(四元数)についてちょろっと書いた程度である。筆者の必要に応じて、徐々に拡充していきたい。

なんとなく英語で書いてみているが、文法とか色々怪しいのでその辺はご容赦願いたい。

glm-notes/ 以下のURLは今後変わるかもしれないので、リンクを貼るならトップページ(https://miz-ar.info/glm-notes/)にお願いしたい。

なお、C++の関数の型は(伝統的には)戻り値の型を先に書くが、自分の書いたドキュメントでは(筆者にとっての読みやすさのため)戻り値の型は後置とする。また、引数の型の const& も省く。

おまけ

GLMとは全く関係ないが、筆者のほしい物リストほしい本リストを公開しておく。今月は筆者の誕生月である。

関連記事

OpenGL の投影行列

Catmull-Rom スプライン曲線についてのメモ

たのしい複素積分」や「わくわく解析接続」では、マウス(またはタッチ操作)の入力から曲線を構成する際に Catmull-Rom スプライン曲線を使っている。この Catmull-Rom スプライン曲線についてのメモを書いておく。あくまで備忘録であり、 Catmull-Rom スプラインを知らない人向けの記事ではない。 続きを読む

滑らかな曲線をベジエ曲線で近似する

目次

ベジエ曲線とは

ベジエ曲線とはWikipedia(英語版)によると(本当はちゃんとした文献を当たるべきなのだろうが)、\(n+1\) 個の点 \(x_0, x_1, \dots, x_n\) が与えられた時に\[
B(t)=\sum_{i=0}^{n}\binom{n}{i}t^i(1-t)^{n-i}x_i, \quad 0\le t\le 1
\]で定まる曲線らしい。始点 (\(t=0\)) は \(x_0\)、終点(\(t=1\))は \(x_n\) である。\(n\) のことを次数という。

(1次の場合は単なる線分なので置いておいて)よく使われるのは2次の場合と3次の場合である。それぞれ\begin{align*}
\mathit{quadratic B\acute{e}zier}(t)&=(1-t)^2x_0+2t(1-t)x_1+t^2x_2, \\
\mathit{cubic B\acute{e}zier}(t)&=(1-t)^3x_0+3t(1-t)^2x_1+3t^2(1-t)x_2+t^3x_3
\end{align*}で与えられる。

2次の場合は始点 \(x_0\) と終点 \(x_2\) の他に1個の制御点 \(x_1\)、3次の場合は始点 \(x_0\)、終点 \(x_3\) の他に2個の制御点 \(x_1\), \(x_2\) によって決まる。制御点は始点及び終点における接線を与えるためにある。ここではベジエ曲線についてはこれ以上突っ込んだ事は取り扱わない。

こういう、「制御点を与えて曲線を描く」のは、ドロー系の描画ソフトウエアを使ったことのある方はおなじみだろう。SVGやPostScriptなどのベクター画像形式でも、ベジエ曲線は基本的な描画対象である。

プログラミングに関して言うと、大抵のグラフィックAPIには2次か3次のベジエ曲線を描画するAPIがある。例えば、HTML5 Canvasの場合

context.quadraticCurveTo(cpx, cpy, x, y) /* 2次 */
context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) /* 3次 */

というAPIがあり、Cocoaの場合は

NSBezierPath
-(void)curveToPoint:(NSPoint)aPoint controlPoint1:(NSPoint1) controlPoint2:(NSPoint)controlPoint2 /* 3次 */

というAPIがある。いずれも始点を指定する引数がないが、これらのAPIを使った時の始点は「現在の点の位置」になる。つまり、最後の描画操作における終点か、あるいはmoveToなどのAPIを使って指定した点である。

滑らかな曲線をベジエ曲線で近似する

さて、滑らかな曲線 \(f\colon[0,1]\to\mathbf{R}^2\) をベジエ曲線で近似するということを考えよう。動機としては例えば、プログラミングで曲線を描きたい時に、大抵のグラフィックスAPIには任意の曲線を描画するようなAPIはないので(2次か3次の)ベジエ曲線を使って近似する事になる。2次か3次と書いたが、以後3次のベジエ曲線で近似する事を考える。

続きを読む