ここは個人の趣味のページです。
私がプログラミングを好むわけは、プログラミングは私の「物づくり」に対する探求心と創造性を十分に満たしてくれるからです。
ここの管理人、
AI の利用やめるってよ。
AI の問題点:
これらが向こう10年解決されないだろうと見込んで、やめることにしました。(2025年5月23日~)
私は AI に頼らず「自分の力」を大切にしたいです。
…とはいえ、人間は新しく見つけた技術を手放すということは基本的にやらないと思います。
だから私も後々 AI を利用することにはなると思います。
でも上記の問題点は確かなもので、将来 AI ロボが私の家の扉をコンコンと叩いて
「市からの要請で、お手伝いするため おうかがいしました」
と言うまでの間は、この AI 技術を導入せず、頑張ってみようと思います。
でもこの考え方、キツイと思うのでマネしなくていいです。
2016年/アメリカ/SF・サスペンス/1:43/公的評価★★★☆☆3.4/私的評価★★★☆☆3.7
YouTube である動画を見ていて、右端の「オススメ」のリストに「面白い SF 映画 3 選」(これ)という動画があって、それを見てこの映画を観ることにしました。
Amazon で 400 円レンタル。これ
終わり方が、、観ていて、口をパカッと開けてしまい、開いた口が塞がらない状態。
この主人公の女優さん見たことあるなと思って調べたらやっぱり、「遊星からの物体X」の数年前に出た続編の主人公の人。
あと「スーサイド・スクワッド」のあのバット持ってる変な女の人もその人らしい。
「カモーン!」とか「FUCK…」のセリフが痛快だった。
(訪問者のどんなニーズと この記事がつながるか)
先月、5月25日の記事で紹介した不具合をなんとか直せました。
▼腰をそらすと腕組みがほどける不具合(クリックで繰り返します)
▼不具合について、どういう計算にすればいいのか探った試作
親子関係において、親の上に乗った子は一緒に回転する。子は子で自分の回転も行う。
その回転を、親が30度、子が30度だから子の回転は合わせて60度と考えてしまうと、うまくいかない。*1
3Dでは、x軸、y軸、z軸の3軸の回転を組み合わせて回転を表現する。
親と子の回転を足し算してから、x, y, z の回転を行うことと、(←上記の *1 の考え方)
子の x, y, z の回転を行ってから、重ねて親の x, y, z の回転を行うことは、(←正しい考え方)
どうやら違うみたい。
それを突き止めたのが上図の試作です。
>この試作を元の人間のプログラムに当てはめたいんですが、人間のプログラムは複雑で当てはめるのは難しいので、人間のプログラムをまた1から作り直すことにしています。
と言って、途中入院しつつも、その難しい当てはめがやっとできました。↓
▼人間のプログラムに当てはめた試作
こちらは人間のモデルを描くことを前提としたプログラム(システム)であり、先の試作の成果を当てはめてあります。
赤をおなか、緑を胸、青を腕、に見立て、青が90度の姿勢を持っていて、緑を回転しても青はその姿勢を崩しません。
良かった。
当てはめは簡単ではなくとても大変でした。試作の方では親子関係は平易に作られていますが、本番の方ではいくつかの拡張性を考えたやや複雑なものになっているので、その複雑な中で回転の関係を落とし込むのはすごく難しかったんです。
頭が足らないだけかもしれないけど。
ところで、青の水槽の中で魚が泳いでいるように見えますが、今日はもう疲れたので、あとで直せばいいと思います。
画面の上部にはファイル名があって、…-20-net.html となっています。
この 20 という数字は、20回、一から作り直したという意味です。
何度やっても、上手くいかなかったり、納得がいかなかったり、手詰まりになったり、そのたびに人間システムを一から作り直しをしたんです。
一から作り直すのは少し大変ではあるけど、べつに苦しいことではありません。
苦しいのは、回転計算を頭の中でいっぱい考えているのに、なかなか思い通りにいかなくて、延々と何度も何度も考え直している状態が苦しいです。
こんなの簡単だよー
…って言う人もいるでしょうけど、、「そういうふうに言う人と私の関係」を考えると、プログラミングができなくて困っている人の気持ちが分かる気がしました。
”できないのは私であって、あなたが出来ても何の解決にもならないんだ…”
私もできるところを見せつけるように知恵袋で回答を示すことがあるけど、もちろんその回答は質問者さんのために役に立つように書いているので役に立つとは思うけど、できるという部分は余計で、何の解決にもならない無意味なことなんだ、と思います。
もっと精進しなくては。
(訪問者のどんなニーズと この記事がつながるか)
人体の動きを表現するプログラム。
一つ前の記事で「腕組みがほどける不具合が直った!」と言っていましたが、実は直ってませんでした。orz
「難しい当てはめがやっとできました。」と言って示した試作にて、赤い直方体をスピンするように回すと(Y軸回転すると)動かないはずの青い直方体が動いてしまいます。(下図)
青い直方体は緑の直方体にピッタリとくっついて動かないはずですが、狂ったようにめっちゃ動いています。
…それでさらに試行錯誤して悩んだんですけど、結局、
「回転するときはすべての親の回転をひとつひとつ適用しなきゃいけない」
…ということでした。
つまり、「赤→緑→青」と親子関係があり、
緑を正しく回転させるには「緑に対して、緑のローカル回転→赤のローカル回転」の順に回転を行わなければならず、
青を正しく回転するには「青に対して、青のローカル回転→緑のローカル回転→赤のローカル回転」の順に回転を行わなければなりません。
一つのパーツに対して、親子関係ツリーの根っこへ向かってひとつひとつ回転を行っていくのは計算量が多くなりそうで避けたいのですが、現状、それしか方法が思いつきません。
これはたぶん、”任意軸の回転” という数学の問題で、クォータニオンという難しい計算を行えば解決できるのかなと思います。
クォータニオンができないなら、「根っこへ向かって回転させていく」という原始的な方法を使うしかありません。
それで、原始的な方法を使って実現させた「腕組みをしてちゃんとその姿勢を維持しながら胸をそらす人間」です。
↑↑この動きを見てると、なんかリアルで、生きてるみたいですよね。
その秘密はこれです。
▼スマホの「ImageMeter」というアプリを使って ダビンチの画像を読み込み、あちこち測り、 ![]() |
▼作ったメモ(入院中にベッドの上で作っていた) |
ちゃんと人体の現実の寸法を測ってモデリングしているんですね。そのためリアルに見えています。
人間の身体の各パーツの寸法をきちんと調べてそれを元に作品を作ると、人の心に届くものができるってことかなと思いました。
人々が長年見てきた「人」というのは伊達ではなくて、ちゃんと記憶に刻み込まれている。
だからきちんとその実態を調べてその上で作れば、人の心のカネをガランガランと鳴らすことができる。
それは絵だけではなく、物語にしても同じで、出来事をきちんとよく見て、できれば体験して、よく知ったうえで物語を描けば、人の心をガランガランと鳴らすことができる。
それは「こうかな?」と思って適当に作って鳴らせるものではない…。
16歳くらいの頃から絵を描いていて、人体のサイズが重要だというのは聞いていたけど、実際にサイズを測って使ったのは今回(50歳になった現在)が初めてで、今までどうしてサイズを測らなかったのかと言うと、「単に面倒くさかったから」です。
34年もの間、面倒くさいで通してきたのか…
あんまりまじめにやりすぎても続かないので、面倒なものは30年くらい後回しにしても良いってことです。
そういう私みたいな「いい加減スタイル」の人は個人的には花開いても、公的にはどこか届かないところがあるので、マネしないほうが良いのかも…
でも自分の心に逆らって勉強勉強だと、死んじゃいますよね。
人体のS字カーブというものがあります。
▼体の姿勢がS字を描いている。![]() |
▼なんも意識していないとこう。I字みたいな。![]() |
左の方がかっこいいですよね。
左のようにS字カーブを意識すると、胸やお尻が強調され、魅力を放ちますが、右のように棒立ちだと出っ張ってる胸とか(図では無いけど)、出っ張ってるお尻とか、ただそこに「くっついてるだけ」、と生かされていない感じがします。
▼S字にするために、各パーツどうしの位置関係など ソラでは難しいので紙に描いてからデータ作成した。 ![]() | ▼余談ですが、消灯して寝床に入り、ムクッと起き上がって デスクライトを点け、メモをサラサラっと書いてまた寝る。 ![]() |
そういうテクニックがあって、今回もそれを使いましたというお話でした。
S字カーブについて参考になるサイト これ
右側のメモの写真は、おなかより上の「胸」が回転したとき腕や頭も一緒に動く、おなかより下の「腰」が回転したとき両足も一緒に動く。であれば、人体の中心(親子関係ツリーの一番上)は「おなか」である。ということに気づいて、忘れないうちにメモした感じです。
▼「胸」が回転したとき腕も頭も一緒に動く![]() |
▼「腰」が回転したとき両足も一緒に動く![]() 残念ながら私は↑これをやりたい人間です。 |
人体をモデリングするとき、「ボーン」とか作りますが、それを「頭」を一番上にして作る手法ももしかしたらあるのかもしれませんが、頭を回転させて身体全体が動くというのはおかしいですよね。
おなかにへその緒があって、そこから成長が始まったというのは、もしかしたらこの関節の動きの話と少し関係があるのかもしれません。
思いついたアイデアというのは逃すわけにはいかないので、こうやってすぐにメモしたほうが良いです。
3DCG で簡易的に簡単に回転を実現しようとすると、「ジンバルロック」という問題に直面します。
X軸、Y軸、Z軸を中心にそれぞれ回転する、という楽な方法で任意の回転を実現しようという場合、「一部の回転が表現できない」という問題が発生します。
それを体験する教材を作りました。下の画面はクリックすると進めることができます。
今回、これについては何も対処していないので、問題はそのまま残っています。
クォータニオン(四元数)という計算を行うと、これを回避できるそうです。
私にもし、子供がいて、その子が以上のようなことを「自分もやりたい」と言うなら、いくらでも教えてあげるし、別に無理して何かやらなくても、自然と私と同等かそれ以上の力を付けて、喜ぶだろうと思います。
そこには難しさはありません。
(でもそう思うのは親の思い込みで、子が親を気に入らなければそれも実現されませんね。私は嫌われる想像しかできません)
時間をかけて優しく丁寧に、あれこれ工夫をして教え、褒めるところはしっかり褒めるので、たぶん上達するはずです。
私が2、3年くらい続けていた仕事(自動機による金属加工)を、ある日新しい人に教えることになったとき、そういうスタイルで気長に教えたので、けっこうマスターしてくれました。2人に教え、2人ともマスターしたようです。私よりもうまくその仕事をこなすところもあり、願ってもないです。
でもこのホームページで、いくらその内側を開示して教えようとしても、結局限界があるみたいです。
これを読んでいる人たちは、私の生徒ではないし、私も教える立場にありません。
金属加工の仕事はよく知っているから教えることができる。
プログラミングも絵もよく知っているので教えることができるはずだけど、ここはホームページでありマンツーマンの場ではなく一方通行なのであまり与えることができません。
毎回毎回、
教えようとして、教えることができないでいます。
なーんか、うまく教える方法ないかなー
(訪問者のどんなニーズと この記事がつながるか)
人体の動きを表現するプログラム。
3DCG で回転を考えるとき、「立方体のような単純な1つのモデル」だけで回転する分にはあまり問題になりませんが、今回取り組んでいるような、「親と子の関係を持った複数のモデル」で回転をする場合は、単純な回転計算だけではうまく回転を表現できません。
▼立方体のような単純な1つのモデル![]() 割と自由に回転できる。 |
▼親と子の関係を持った複数のモデル![]() 緑以降は、赤を基準にした回転が必要で、 また、青は、緑を基準にした回転が必要だ。 |
読んでいる人が「分からない」になるのを恐れずそのまま書いてしまうと、
人体を 3DCG で表現するとき、それはツリー構造になっています。
おなかから始まり、上方向に、胸があり、首があり、頭がある。胸には両肩があり、左右の上腕、前腕、手へとつながる。
また、下方向に、腰があり、両足の太もも、すね、足首、つま先へとつながる。
マイケル・ジャクソンの踊りのように、つま先を中心に全身を 25 度前方へ傾けるような回転を考えるとき、
▼マイケル・ジャクソンの踊りの一場面を再現した図
※画面はハメコミ合成です
全身はつま先という1つのモデルの状態(位置とつま先自体の回転)の影響を受けます。
たとえば、(位置はともかくとして、)つま先が北を向いていれば、全身も北を向くはずで、東を向いていれば東を向くはずです。
(ここから話が複雑ですが、)それと同時に、つま先は、おなかから始まって、腰、太もも、すね、足首があり、その先にあります。
もし太ももが付け根を中心に 45 度曲がれば、つま先も 45 度曲がるはずです。
普通につながっていますからね。
腰を 10 度ひねれば、つま先も(角度だけを見ると) 10 度曲がるはずです。
つま先の向いている方向というのは、おなかから始まって腰の角度、太ももの角度、すねの角度、足首の角度などさまざまな角度の影響を受けてはじめて決定されます。
よく分かっていない人の説明は長く複雑になりがちですが、今の私の説明がまさにそれです。
まぁ、つま先を描画するためにいちいち、おなかから足首まで各部位の回転計算を繰り返した上で決定するのは面倒で、今現在つま先が X軸回転何度、Y軸回転何度、Z軸回転何度、回転していると分かっているなら、その分かっている角度で一発で回転したい。
ところが、X軸回転何度、Y軸回転何度、Z軸回転何度と、順番に回転していく計算だと、どうやっても思い通りの回転になりません。(オイラー角による回転にはジンバルロックという問題がある、、かな?)
そこで、XYZ順番回転ではなく、XYZ一度に回転を行う(?)クォータニオン(四元数)という計算の導入を考えるわけです。(今調べたら「XYZ一度に回転を行う」ではなく、「任意軸で n 度回転」でした)
クォータニオンという難し気な新しいモノを導入するのは学習の時間と手間がかかりそうなので、避けたかったんですが、やりたいことをやるためには、どうも必要みたいだ。と結論したわけです。
必要だから導入する、と簡単にいけば良いんですけどね。
とりあえず、
この2つのサイトさんの説明を読ませてもらって、それでどこまでできるかです。
(訪問者のどんなニーズと この記事がつながるか)
今回のこの記事は少し長くなっています。記事の概要を先に書いておきますと、
3DCG プログラミングでちょっと必要になる「クォータニオン」の学習のために「wgld.org」というサイトでクォータニオンについての記事(5ページ分)を読み、その5ページそれぞれの読んだ感想と言うか見解みたいなものを書き示し、ページに掲載されているサンプルプログラムを自分なりに同じようなものを作成してここに掲載しています。
そんなふうにしてクォータニオンを学び取っていきました。
しかしそこまでやっても目的が達成されないので、「高校数学の美しい物語」というサイトの「四元数と三次元空間における回転」というページを読み、たとえば「肩→上腕→前腕」のような親子関係のある 3DCG モデルでの親子の回転の合成の方法が分かり、それでやっと、目的のものにたどりつきました。
…という内容の記事となっています。
「webGL」は、インターネットブラウザ上で 3DCG を描画するための API(プログラミングで使える外部機能)です。
「web 上のグラフィクスライブラリ」という意味で webGL です。
CPU 内に 3DCG を描画するためのハードウェアがあり、その部分を openGL と言います。
webGL はその openGL にアクセスすることで、web上で高速に 3DCG を描画できるようにしているものです。
「wgld.org」というサイトさんはその webGL を中心に、いろいろな 3DCG 描画の方法について説明してくれています。
私は基本的に webGL を利用していませんが、以前、このサイトさんの説明のおかげで、「スペキュラ反射」(球面に光を当てたときのハイライト、光沢)を実現したことがあります。
そして今回は「クォータニオン」について読ませていただき、理解を深めることができました。
難しいことをなるべくおさえて説明してくれるので、習得しやすいんですね。
クォータニオンについては5ページにわたり整った文章で説明されています。
というわけで、5ページすべて、しっかり読み進めることにしました。
「行列、内積、外積が欠かせない」と説明されていますが、私はそれらをまともに勉強していません。。
でもやはりここでも、「X軸、Y軸、Z軸の3つの回転を組み合わせて回転を行う方法では限界がある」と説明されていて、その点は私の今回の目的に一致しています。
クォータニオンは、
Q = (t; x, y, z)
という、t, x, y, z の4つの値で表されると説明されています。
JavaScript 的に書けば、クォータニオンは、
Q = [ x, y, z, t ];
のように配列として書くことができます。t が末尾に来ていますが、配列上の位置は人それぞれの好みで問題ありません。
クォータニオンとは英語で、Quaternion と書きます。意味は「四元数」ですが、語源としては「4つ組」という意味があるそうです。
1つもののセット | 1 element | ワンエレメント |
2つもののセット | binary number | バイナリ |
3つもののセット | ternion | タニオン |
4つもののセット | quaternion | クォータニオン |
5つもののセット | (pentonion) ※辞書に単語として登録が無いが翻訳では出る | ペントニオン |
6つもののセット | (hexatony, hexatonion) ※辞書に単語として登録が無いが翻訳では出る | ヘクサトニオン |
7つもののセット | (heptadion) ※辞書に単語として登録が無いが翻訳では出る | ヘプタディオン |
8つもののセット | octonion | オクトニオン |
9つもののセット | 9 elements | ナインエレメンツ |
10個もののセット | 10 elements | テンエレメンツ |
英単語の「-on」という接尾辞は、もともとは「ion」(化学のイオン)から来ているそうです。語源事典より
1つのクォータニオンは、4つの値で示され、それらが「元素」のように扱われるので Quaternion と命名したのでしょうか。
ページの説明を読むと、外積と内積が出てきます。
私はそれらについては知りませんが、公式だけは知っています。
▼私のページのこのリンクの… | ▼このリンクを見ると… |
![]() |
![]() |
▼内積はこういう式だというのを参照でき、 | ▼外積はこういう計算だ(法線を求めるのに使用している)、というのを参照できます。 |
![]() |
![]() |
内積も外積も四則演算(+-×÷)なので、意味や仕組みは知らなくても、その式を利用することはできると思います。
そしてクォータニオン自体も、四則演算だと説明されています。そのため、
>演算負荷も少なく、比較的高速に動作させることができる処理
ということで、大変助かります。
「ベクトルを正規化する」というのも出てきて難しそうに聞こえます。
下図の?の部分を求める式は、?=√( 3 * 3 + 5 * 5 ) で求まります。(三平方の定理)
√( 3 * 3 + 5 * 5 ) = √( 9 + 25 ) = √34 = 5.83 です。
正規化というのは、?の部分を1としたときの x, y のことです。つまり、
「正規化 x」= 5 / 5.83、
「正規化 y」= 3 / 5.83、
ということです。
3次元になると、これに z も加わります。
√について、2×2=4で、1辺が2である正方形の面積は4だというのは分かると思いますが、
このとき、逆に考えて面積にルートを付けて√4と書けば、それは1辺を表す。という意味です。
√はルートと読みます。日本語で平方根と言います。
「もともとどういう計算をしてその面積になったのか?平方の根っこはなんだ?」という意味で「ルート」と呼んでいます。
√4は2ですが、これは分かりやすいので答えられる人は多いですが、基本的に√いくつは暗算不可能です。
√2は、ひとよひとよにひとみごろ、で 1.41421356…であり、
√3は、ひとなみにおごれや、で 1.7320508…です。
√5は、ふじさんろくおうむなく、で 2.2360679…です。
暗算できないから語呂合わせがあります。
語呂合わせのない、そして√4とか√16みたいな単純なものではない、その他の√いくつについては、電卓を使うのが普通です。
▼私の 3DCG の説明のページでも、このように正規化の関数を使っています。
正規化というのは計算としてはこれだけのことですが、分からない人にとっては「これだけ」では済まないんですよね。
慣れていないし、勝手もわからない、という状態だと、たとえ理屈は簡単でも「難しい」の範囲内に入りますね。
だから初心者の人に対して、「たったこれだけのこと」と言わないほうが良いんです。
クォータニオンの [ x, y, z, 角度 ] の x, y, z の部分は、3次元空間中のある点( x, y, z ) のままではいけなくて、その点までの距離が1であること、つまり正規化された x, y, z でなければならない、ということで正規化を使います。
正規化しないと計算結果が狂います。
ページでは、いくつかクォータニオンに関する式の説明が行われていますが、これらを私自身のいつもの 3DCG プログラムにどう落とし込むかがポイントでした。
このページでは実際にクォータニオンを使って物体を回転させると案内しています。
このページのサンプルの内容を、私のいつもの 3DCG プログラムへ落とし込んだ試作が下図のプログラムです。
「いつもなら、X軸で回転」させるところですが、このプログラムではクォータニオン [ 1, 0, 0, 角度 ] で回転させています。
「いつもなら、X軸で回転」というのは、
こんな感じのプログラムをいつも書いていました。
このオレンジ色の部分を、クォータニオンに差し替えると…
※ これは JavaScript です。Array ではなく Float32Array を使っているのは高速化のためです。
※ このプログラムを実際に使っているプログラムリストはこれです。(上図で動いている「落とし込んだ」のプログラムと同じものです)
※ このプログラムをもっと短縮して高速化を図ったバージョンのプログラムリストはこれです。4つあった関数が1つしかなく、draw() 関数の中に短縮された計算が書かれています。この短縮が実用できるかどうかはまだ分かりません。
上記の //1 ~ //4 のコメントで示した関数がクォータニオン関連の関数です。
サイトの説明で使用されている minMatrixb.js との対応は下表のとおりです。
私が作った関数 | サイトの関数 |
---|---|
//1 function makeRotationQuaternion() |
( new qtnIV() ).rotate() 任意軸での任意角回転を表す四元数(クォータニオン)を生成します。 |
//2 function applyQuaternion() |
( new qtnIV() ).toVecIII() 三次元空間上の任意の点を表す、三つの要素を持つベクトルを、四元数(クォータニオン)によって座標変換します。 |
//3 function getKyoyaku() |
( new qtnIV() ).inverse() 四元数(クォータニオン)を反転し、共役四元数を生成します。 |
//4 function multiplyQuaternions() |
( new qtnIV() ).multiply() 四元数(クォータニオン)を掛け合わせます。 |
両者で関数の見た目(ぱっと見のコード内容)は異なっていますが、やっていることは同一です。
このページを読んだ時点で、クォータニオンを自分なりのプログラムで使えるかどうかが最重要ポイントのひとつでしたが、上図で示した試作プログラムのとおり、なんとかできて良かったです。
正直言うと、
だから比較的短時間でクォータニオンのプログラムを自分のプログラムの中に落とし込めた、という感じはしました。
もし、3DCG についてあまりよく知らない、ベクトルについてよく知らないという状態だったら、もっと時間がかかったと思います。
この記事を読んで、クォータニオンをやってみようと思った方は、その点、注意してください。
学ぶ際のアドバイスですが、世間で良く知られている行列を使った 3DCG プログラミングは私が思うに「ものすごく難しい」ので、私がいつも言っている、
s = 50;
h = x * s / z;
v = y * s / z;
この原理の式だけを使い、行列は一切使わないという方針で 3DCG プログラミングを学んだ方が、今回のようなクォータニオンの導入も、ずっと手早いと思います。
前ページでは「ベクトル」にクォータニオンを適用させる例でしたが、このページでは「行列」にクォータニオンを適用させる例を示しています。
「ベクトルってなんだよ…」って思う人も多いと思います。
ベクトルは分からなくても、「3次元空間中で ( x, y, z ) で示される点」は想像できますよね。
原点からその点に向かって矢印を引っ張ると、それがベクトルです。
つまり、( x, y, z ) 自体がベクトルだということです。
ある方向を示すとき、空間中の1点を示せば、方向を示すのにこと足りますよね。
だからベクトルとは点なんです。
ベクトルとは英単語で、vector と書き、その意味は「ベクトル、方向量、動径、方向、進路(方位)、媒介動物、保菌生物」です。
点をベクトルとして見てベクトル同士の関係を計算すると、さまざまな問題を解くことが可能になる…ということで数学にはベクトルというものがあります。
前のページでは x, y, z の点(ベクトル)にクォータニオンを適用し、回転を行っていました。
それがこのページでは「行列」を使うと言っています。
私は行列は全然使わないので、このページは読むだけとなりました。
サイトのサンプルでは3つのドーナツがあり、2つのドーナツのあいだを1つのドーナツが行き来(球面線形補間)できるプログラムを示していますが、私はドーナツを作るのは大変なので、「板」にしました。
下部の「赤側←→緑側」のスライダを動かすと、赤と緑の板の間を透けてる青い板が行き来します。
えらいこっちゃ…どうやってんのコレ、みたいな。
板状のモデルが3つあり、赤と緑は通常のモデルで、それらを回転させるクォータニオンも通常ですが、青だけは slerp() (たぶん、エス・エル・イーアールピーと読む)という関数を「赤のクォータニオン」と「緑のクォータニオン」、そして「スライダの値」の3つを引数として渡して実行し、戻り値として結果のクォータニオン(球面線形補間されたクォータニオン)を受け取っています。
それらのクォータニオンを使ってそれぞれ回転させているので、この画面となっています。
slerp() とは、spherical linear interpolation(スフィアリカル・リニアー・インターポレーション、球面線形補間)の略だそうです。
slerp() が何をやっているのかは分かりませんが、なんとか自分のプログラムの中で実現できて良かったです。
サイトのサンプルではスモークのかかった板の上で球が浮いています。
しかしこの球はモデルではなくて、小さな板に描かれた球の絵です。
板は常にカメラの方向に正面を向けているので、あたかもそこに球の 3DCG モデルを描いているかのように見えています。
そのサイトのサンプルの下部の billboard というチェックボックスにチェックを入れると、正面を向くのをやめるので絵(画像)だと分かります。そういうサンプルです。
このビルボードの機能を使えば、板に描かれた絵を常にカメラのほうに向け、複雑なモデルを描いて処理速度が落ちるのを防止できる、というわけです。
私の 3DCG プログラミングの技術には、「画像を三次元空間に配置する "テクスチャ" の機能」がありませんので、下図のサンプルでは代わりにただの板(赤色)を表示しています。
板は野球のホームベースみたいな五角形のトンガリ部分に配置しています。
画面上でマウスを動かしたり、画面をタッチすると動きます。
サイトのサンプルプログラムを見たところ、正直、何をやっているのかいまいち分からなかったので、自分なりに考えて作りました。
最初はどうにもうまくいかず、かなり時間がかかりましたが、なんとかできました。途中でくじけそうになったよ。
そして、
5ページすべて読んだので、
人体の親子関係を作るために、親子関係をクォータニオンで表現する試作を作り始めましたが、知識が足りないせいでとりあえずできませんでした。
「知識が足りていない」と分かっていて、「クォータニオンの [ x, y, z, t ] の x, y, z の部分はベクトルであり、その親子関係」ということだから、「ベクトルの足し算」とか「ベクトルの掛け算」について勉強しました。
しかし、それでもうまくいかない…
まるで X軸、Y軸、Z軸での回転のときのように、親の回転により子の回転が影響を受けて不正に回転するような、そういう動きをしてしまう。orz
そこで、「クォータニオン」についてウェブ検索し、
「高校数学の美しい物語>四元数と三次元空間における回転」
というページを見つけました。(ここ)
そのページでは、
>さらに回転の合成が四元数の積に対応していることを説明します。
と書かれていて、
(この先、話が少し難しくなります)
ベクトル a に対して回転 q を作用させてから回転 p を作用させると,
となる。ここで四元数の共役の性質と結合法則を使うと上式は
と等しい。
つまり,pq という四元数で表される回転を一回作用させたものになっている。二回の回転が一回の回転で表現できる!
こんなふうに書かれていました。
また、先の「wgld.org」の1ページ目「クォータニオン(四元数)」のページの最後の方にて、
( Q は回転を表すクォータニオン)
( R は Q の共役四元数)
( P は三次元空間上の座標 (0; x, y, z) )
P を回転させるための計算は……
R * P * Q = (0; X, Y, Z)
この最後の X, Y, Z のそれぞれが、任意軸・任意角の回転を行なったあとの座標
のように説明されていて、
ただの回転は「R * P * Q」、これを「高校数学の美しい物語」の書き方に替えると「」。
「高校数学の美しい物語」では、親の回転に子の回転を加えるというのは、
だと言っています。この = の右側である右辺は形が「」とよく似ていて、すでに私が作った関数の applyQuaternion() の内容とほぼ同じです。
つまり、親の回転と子の回転について、「クォータニオン同士の掛け算」(関数 multiplyQuaternions() )を行い(= pq を作り)、その掛け算結果のクォータニオンを 空間内の各点(= a)に対して適用(つまり )すればよい、ということです。
…何言っているか分かんないですよね。
(このことは、下図のプログラムこれの中の Model クラスの updateM() というメソッドの中でコメント①②で示しています)
まぁ、それでできたのがこの試作です。
赤緑青の各モデルはそれぞれで親に対して任意の方向に 90 度回転していて、赤がどのように回転されていても、緑と青はその姿勢を保っています。
ここまで行きつくのは以上で説明したとおりとても大変でした。でもなんとかこぎつけることができて良かった…
以上により、「腕組みしている状態で腰をそらすと腰の角度の影響を受けてしまって腕組みがほどけてしまう」という不具合
(※クリックすると繰り返します)
について、
クォータニオンが無いときは、前の 2025 年 6 月 14 日の記事で、
>クォータニオンができないなら、「根っこへ向かって回転させていく」という原始的な方法を使うしかありません。
>それで、原始的な方法を使って実現させた「腕組みをしてちゃんとその姿勢を維持しながら胸をそらす人間」です。
と言っていたように、「1つのモデル(パーツ)の描画ために、ツリーの根っこへ向かってすべての親の回転を1つ1つ適用していく」というようなことをやって、これ↓を実現していたんですが、
今度からはクォータニオンを使って、もっとシンプルな計算、計算量で同じことができる…! ということです。
以上、ここまで「なんとか」という言葉を4回繰り返していますが、私は別に数学が得意な秀才というわけではなく、「ぼちぼちの数学」(得意だった中学校数学+卒業してない高校の部分的な数学)と「根気」をもとにしてなんとか達成している、ということです。
プログラミングは今年でだいたい 40 周年(40th anniversary)なので、その経験によるところも大きいと言えます。
「wgld.org」さんと、「高校数学の美しい物語」さんの説明が無かったら実現はしませんでした。ありがとうございました。m(_ _)m
(訪問者のどんなニーズと この記事がつながるか)