【本サイトのご利用指針】
当サイトはSPAM対策等のためJavaScriptを使っています。
JavaScriptの実行を可能な状態にしてご利用下さい。
Please enable the execution of JavaScript!

【3次元グラフィックスをExcel VBAで製作してみる】

作成日 2009/01/22
最終更新日 2010/04/07


ここにチェックボックス型外部コンテンツ・メニューが入ります。

20秒経っても動画がスタートしない、または音が聞こえない場合、Internet Explorer 8Firefox Ver. 3.5Google Chrome Version 2.0またはOpera Version 9.64
をお使いください。さらにAdobe Shockwave flash player pluginを使う必要もあります。JavaScriptも実行可能な環境にしてください。
Google O3D Demonstration Program
3D-CG plugin [Haku Yowane]

Google O3D Demonstration Program
3D-CG plugin [Hachune Miku]


Excel VBA版1次元/2次元音響FDTDシミュレーションのソース公開

 YouTubeで要望のあった音響FDTDシミュレーションのソースと使い方を公開しました。
 音響FDTDの原理自体はどこかに書いていたかもしれませんが、様々なシミュレーション結果や理論等をこのページに追加していく予定です。
 今後、段階的に音響系技術の公開を実施していく予定です。


亞北ネル、弱音ハク [MikuMikuDance]
背景の写真は京セラ本社前。京都では恒例となったクリスマス・イルミネーション2008


伊達杏子(だて きょうこ)
1996/11デビュー当時 [堀プロ所属]




MikuMikuDance 初音ミクver2モデルの形状データ(あにまさ氏作)


透視変換に関してはこちらに記載。
光源計算に関してはこちらに記載。
光源計算の追加メモはこちらに記載。
表情処理メモ
IK boneメモ  

【お知らせ】

  ■記載日2010年4月7日■
 ■Microsoft社Excel VBA(Visual Basic for Application)で記述した最新版3次元グラフィック・ライブラリ[Lib_3DGraphic.bas]についてはhttp://www.neo-tech-lab.co.uk/MikuMikuDance/PMD1.htmにソースやリンクを張っていますので、是非そちらをご覧ください。ポリゴン・フィル、テクスチャーマッピング、透視変換、光源計算等のドキュメントが別にあります。

   ●ポリゴン・フィル、テクスチャーマッピングとソース
   ●透視変換とソース
   ●光源計算とソース


【まえがき】      ■記載日2009年1月22日■
 近年、
Windowsパソコンの性能向上が著しい。DirectXを使って3次元CGのリアル・タイム動画が個人レベルで制作できる時代 が到来している。既に3次元グラフィックスで制作した動画を学会講演に使う人もいる。
 私は1/4世紀程前に5年間3次元グラフィックス・エンジンのハードウェア開発を行っていた 。数100ポリゴン程度の粗末なロボット・モデルにフラフープをリアルタイムに回させるのがやっとだったが、今のパソコンの性能ははるかその上を行く。特に昨年は、樋口優氏の開発した
MikuMikuDanceという動画制作ソフトウェアに驚いた。これは革命にも思えた。

 堀プロが数千万円をかけて開発して
199611月にデビューさせたバーチャル・アイドル伊達杏子(開発コード番号DK96:Digital Kids)というキャラクター がいたのを思い出し 、クローゼットに詰め込んであった資料を発掘してみた。最近は周囲50cmが他の物で埋め尽くされていたので発掘作業に1時間程。おお、あった。1997130日付の朝日新聞のスクラップとともに伊達杏子のかなり色褪せたプリント・アウトを発見。 画質が悪いが接写画像を左に示す。当時、堀プロのホーム・ページを見に行くと、堀プロ所属のタレントファイルには伊達杏子も登録されていた。今は削除されてしまっているようだ。
 伊達杏子は100万ポリゴンからなるモデルをモーション・キャプチャー装置で動かし、歌と会話で別の声優を使っていたようだ。生番組出演には数百万円の費用がかかると聞いた覚えがある。確かに声優2人に、モーション俳優、機器操作等の人件費もかかるだろう。
DK96はあらゆる面で時代を先取りし過ぎたようだ。バーチャル・アイドルを受け入れる市場も未成熟だった。
 しかし、市場が形成された現代でも、プロ仕様の機器価格はそれほど変化していないかもしれない。ナムコのアイドル・マスターでも開発には相当な費用がかかっている と思う。

 しかし、
2007年から2008年にかけてそれが 一変した。パソコン1台あれば、ディジタル音源で制作した音楽(MIDI)データにVocaloid2「初音ミク」に歌わせた歌を合成して作曲できる。さらに、MikuMikuDanceで好きなモデルを選んでポーズを付けていくだけで動画制作 までが行える。必要なのは音楽センスと振り付けや編集の才能で、全部揃えても個人で負担可能な範囲だ。
 いやぁ、本当に凄い!
 いまだに科学技術は軌道エレベータも月への移民さえ実現していないというのに、コンピュータ・グラフィックス関連技術はしっかり進歩していますねぇ。

 情報の発信という切り口で見ると、企業レベルでしか成し得なかった規模の情報発信を個人レベルでも行うことが可能になっている。この変化はまだまだ 多方面で加速していると感ずる。

 エンターテイメントの分野だけでなく、多くの電子機器でも3次元グラフィックス表示が求められるケースが徐々に増加している。しかし、携帯機器のように低価格機器に3次元グラフィックス表示や動画を実装しようとすると、大企業なら問題ないが、中小、零細企業の場合にはファームウェアの開発、専用ICの入手性、供給の安定性等未だ問題点が多い。
 これまでもグラフィックスを表示する単なるビデオ・メモリ(フレーム・メモリとも言う)は製作してきたが、高性能
CPLDFPGAの登場により、そろそろ組み込み分野でも3次元CGを表示できるハードウェア開発環境が整ってきたようだ。ここでもう一度一から3次元グラフィックスの演算処理をおさらいし、その上で現状に囚われずに機能の追加を目指そうと思う。

 そこで
Microsoftのサイトでほんの少しだけDirectXを眺めてみた。基本的には当時のアーキテクチャのままのレベルと言っていいようだ。頂点座標リストと頂点ポインタリストに基づくトライアングル・メッシュ構造。 左手座標系。時計周りの頂点ポインタ定義順序で三角形の法線ベクトルを定義し、前方(表)/後方(裏)を示す。シェーディングは、フラット・シェーディングとグロー・シェーディングだけのようだ。テクスチャー・マッピング(UV)は実装されている。

 ざっと見たところでは
IK(Inverse Kinematics) boneclothなどは発見できなかった。物体干渉、重力、風、髪の毛等を実現 したければ、自分で演算モデルを作って実装しろってことなのでしょうかね?まぁ、IKボーンも変にねじれが目立ったりする場合があったりするから、ちゃんと1からオリジナルな方式を考えてみるのもいいかもしれない。

 そんなわけで最終的に
FPGAへの実装を狙って 3次元グラフィックスの描画アルゴリズムを1から作ることに決めました。アルゴリズムの検証だけだからMicrosoft Excel VBAで書いて行きます。これって無謀?

 ■Microsoft社Excel VBA(Visual Basic for Application)で記述した最新版3次元グラフィック・ライブラリ[Lib_3DGraphic.bas]についてはhttp://www.neo-tech-lab.co.uk/MikuMikuDance/PMD1.htmにソースやリンクを張っていますので、そちらをご覧ください。

注)Google O3Dへの移植作業に先立って、MikuMikuDanceのモデルデータであるPMDデータから頂点データリスト、面頂点データリスト、材質定義リストをExcel Sheetに読み出して、全てソフトで3次元グラフィックスを実現し、表示してみました。詳細はこちらMikuMikudance関連コンテンツをご参照ください。
Index
  ●3次元グラフィックス
  ●VBAの利用準備
  ●VBAでの画像表示法
  ●bmpファイル形式
  ●2Dピクセル描画
  ●Zバッファ
  ●3Dピクセル描画
  ●2D直線描画
  ●3D直線描画
  ●RGB補間直線描画
  ●スキャンライン描画
  ●三角形描画
  ●任意多角形描画
  ●テクスチャーマッピング
  ●クリッピング
  ●透視変換法
   ●スクリーン平面への投影
   ●2次元座標への変換
   ●単位ベクトルの求め方
  ●ライティング
  ●シャドーイング
  ●モデリング
  ●ボーン
  ■Google O3D結構速いですね。
それもそのはず、WindowsマシンではDirectXに変換して表示しているようです。

 

 


次元グラフィックス

 最新鋭のMRI装置のように画像蓄積メモリの記憶容量が非常に大きく、表示対象の大きさが限られていれば、例えば1mm角の立方体を1画素とする3次元マトリックス(メモリ)に記録しておくことで、任意方向から対象物体を観測した場合の映像を得ることができるかもしれない。しかし、実際の映像には大きな物も写り込む。もし、このように記録する物体側の記録分解能を固定すると膨大なメモリを要してしまうことになる。1m×1m×2mを1mmピッチで3次元的に記録すると、2Gワードを要してしまう。
 人間の眼の分解能は概ね2000×2000画素程度だと言われている。網膜上の個々の視細胞は大体同じ立体角をカバーしている。つまり、人間の眼は遠くにあるものははっきりとは見えないが、近くにあるものは細かく見える。それ故、3次元コンピュータ・グラフィックスの世界では、透視変換法という方法が利用される。透視変換法によって、3次元の物体は2次元のスクリーンに投影される。2次元スクリーンは横○○○画素、縦□□□画素というように長方形形状の2次元マトリックス構造を持ち、画素単位で色情報を蓄積することで成り立つ。上記の例で2Gワードを要した画像メモリも最大4Mワード程度あれば十分になる。
 殆どの場合、3次元コンピュータ・グラフィックスで表示される物体はワールド座標系上に定義された3角形の集合体(Mesh)で定義されている。集合体は、頂点座標を列挙した「頂点リスト」と各三角形がどの頂点によって構成されるかを示す「ポインタ・リスト」からなる。観測者の視点の位置vEyePt、観測者にとってどちらが上側かを示す姿勢ベクトルvUpVec、観測者が注視している場所を示す注視点vLookatに基づいて透視変換処理が行われ、2次元スクリーン座標に変換されてから描画処理が行われる。このスクリーン座標への投影時に、スクリーンから完全にはみ出た図形は無視され、スクリーン枠によって一部分断されている図形は枠からはみ出した分を削り取るクリッピング(Clipping)処理が行われ、効率良く描画処理が行えるように処理される。
 ソフトウェアは、途中結果を見ながら進むためにTop Down方式で作らず、Bottom Up方式で記述してゆく。

    【図1】透視変換法と3次元コンピュータ・グラフィックス
    


VBAの利用準備

 

 以前に2次元グラフィックス描画機能をMicrosoft Excel VBAに実装する方法についての記事を書いてい る。
Excel 2003でのVisual Basic for Applicationの使い方についてはそちらを参考にしていただきたい。
 
Excel 2007Visual Basic for Applicationを使おうとするなら、まずExcel起動状態で左上隅に表示されている円形のOfficeボタンをクリックするとプル・ダウン・メニューが表示される。そこにあるExcelのオプション(I)をクリックする。
基本設定タブに<<
Excelの使用に関する基本オプション>>の中の『[開発タブ]をリボンに表示する(D)』にチェックを入れる。次に、セキュリティー センタータブの『セキュリティーセンターの設定(T)』ボタンをクリックして、Active Xの設定の中の『先に確認メッセージを表示してから、最低限の制限を適用してすべてのコントロールを有効にする(P)』を選択する。さらにマクロの設定タブの『すべてのマクロを有効にする。・・・・』を選択する。また、開発者向けのマクロ設定も『VBAプロジェクト オブジェクト モデルへのアクセスを信頼する(V) 』にチェックを入れます。
 以上の設定で、メニューに[開発]という文字が現れるはずです。図2に示したように[開発タブ]内に
Visual Basicはあります。

【図2】VBAを使う準備


VBAでの画像表示法

 

 VBAで画像を表示する方法の選択肢はそれほど多くないかもしれない。
 オリジナルActive Xコントロールを作って張り込む方法はあるが、それだとインストール作業が必要になる。他のパソコンですぐに利用できない場合があるし、何よりコントロールのバージョンが一致しなければならず面倒だ。
 そこで標準実装されている機能だけを使う方法を検討する。

 
MicrosoftExcelPower PointVisual Basic for Applicationに標準実装されているActive Xコントロールの中でグラフィックスを表示するために利用できるものはImageコントロール(Forms.Image)しかないようだ。ImageコントロールにはPictureプロパティがあり、画像ファイルを読み込んだり、書き込んだりすることができる。

 開発タブにある挿入ボタンをクリックすると、図3のように
Excelシート内に張り込めるActive Xコントロールが表示される。中央下にあるを選んで、シート上の矩形領域を選択すれば、図4のように、灰色の矩形領域が表示され、同時にデザインモードボタンの色が変わるはずだ。このとき4隅をドラッグして大きさを調整することができる。
デザインモードボタンが選択されているときに
imageコントロールをマウスでクリックして選択してから、ボタンを押すと、プロパティー・ウィンドウが表示される。Pictureと書かれた枠の右側にある枠内をダブル・クリックすることで図5に示すようにimageコントロール内に画像ファイルを読み込むことができる。Imageコントロールが取り扱えるファイル形式は、bmp, jpg, gif, ico, cur, wmfである。

 
VBA (Visual Basic for Application)でImageコントロールを用いた画像ファイルの読み込み/書き込みの操作を行うには以下のようにする。

   ■指定ファイルを
Imageコントロールに読み込む方法の例
     
Image1.Picture = LoadPicture("ファイル名.bmp")
   ■Imageコントロール内の画像データを指定ファイルに書き出す方法の例
  
   SavePicture Image1.Picture, "ファイル名.bmp"

 取り扱えるファイル形式の中では、ソフト的に
bmp形式の取扱が最も容易だろう。 特に、1画素当たりRGB24bit (1670万色表示)の書式が最も目的に適合している。

 
ImageコントロールにはPictureSizeModeというプロパティもあり、
 ●
fmPictureSizeModeClipモード:元画像と同倍率で表示し、枠からはみ出た分は表示されない
 ●
fmPictureSizeModeStretchモード:Imageコントロールの縦、横のサイズに自動的に調整される
 ●
fmPictureSizeModeZoomモード:枠の短い方の長さに合わせて表示する
3つの表示モードがある。

 以上のように、1フレーム分のグラフィック描画処理をメモリ上で行い、完了後ファイル化して
Imageコントロールに読み込 んで表示する方法をとることにした。これは実際のフレーム・メモリのダブル・バッファ(表示用と描画用を分けて持つ)方式に対応する。

   【図3】
Active Xコントロール
   
 

   【図4】Imageコントロール                 【図 5】Imageコントロールのプロパティ
     
 

bmpファイル形式

 RGB24bit形式のbmpファイルのヘッダー情報のフォーマットは次のようになっている。

Public Type RGB24bitBitMapHeader ' RGB24bitタイプのBitMapファイルのヘッダー
  B As Byte                      ' ファイル識別子 "B"
  M As Byte                      '      :     "M"
  FileLength As Long            ' ファイルの長さ=ヘッダーサイズ(54バイト)+データサイズ
  Null1 As Long                  ' 0
  HeaderSize As Long             ' ヘッダー領域のサイズ        (54バイト)
  Offset As Long                 ' 画素データまでのオフセットサイズ(40バイト)
  Nx As Long                     ' x方向画素数
  Ny As Long                     ' y方向画素数
  NumberOfPlanes As Integer      ' プレーンの数              (1プレーン)
  BitsOfPixel As Integer         ' 1画素を構成するビット数  (24ビット)
  Null2 As Long                  ' 0
  SizeOfData As Long             ' 画素領域のバイト・サイズ
  Null3 As Long                  '
  Null4 As Long                  '
  Null5 As Long                  ' 0
  Null6 As Long                  ' 0
End Type

上から順に説明すると、
 ●最初の2バイト(B, M)はファイル識別子であり、アスキー・コードで"B"、"M"と書かれている。
 ●次の4バイトFileLengthはファイルの総バイト数である。下の例では0x000CC44A=836682バイトである。
 ●次の4バイトはnull(意味がない隙間)である。
 ●次の4バイトHeaderSizeはヘッダー情報のバイト数を示している。下の例は0x36=54バイトである。
 ●次の4バイトOffsetは画像データ領域までのオフセット値を示す。この情報を含めて40バイトである。
 ●次の4バイトNxx方向の画素数を示す。例では0x00000219=537画素である。
 ●次の4バイトNyy方向の画素数を示す。例では0x00000207=519画素である。
 ●次の2バイトNumberOfPlanesはフレーム・メモリの何画面分(プレーン数)を持っているかを示す。例は1である。
 ●次の2バイトBitsOfPixelは1画素を構成するビット数を示す。例では24である。
以上がヘッダー情報部分の概略である。
 

             【図6】ヘッダー情報部分
             
             

ヘッダー情報に続いて、画像データ情報が続く。
bmp形式ファイルでは、横軸がx軸、縦軸がy軸であり、右側がx軸の増加方向、上側がy軸の増加方向である。
1画素のデータはB(Blue:青), G(Green:緑), R(Red:赤)の順で並んでいる。

Public Type RGB24bitPixel ' 画素データの構造(RGB24bitタイプ)
 B As Byte ' 青(0~255)
 G As Byte ' 緑(0~255)
 R As Byte ' 赤(0~255)
End Type


x
の増加方向に1スキャンライン単位で並んでいる。1スキャンライン分のデータは4の倍数となっている。従って余りが生じる場合もある。横9画素、縦5画素の場合は図7のように並んでいる。
 
【図7】
画像データ領域
                 x=0     x=1        x=2       x=3        x=4     x=5        x=6        x=7       x=8
      y=0            
      y=1            
      y=2            
      y=3            
      y=4            
      
 

2Dピクセル描画

 1スキャンライン分のデータのバイト数cg.Nwを予め以下の関数を使って求めておくことで、スクリーン上の任意整数座標(x, y)のピクセル描画アルゴリズムを得る。但し、cgRGB24bitBitMap型, PRGB24bitPixel型である。
  ところで、ピクセル描画ルーチンの中でLを求める際に
X*3&を演算している。一見、乗算を行う必要があると思いがちだが、FPGAにこの演算を入れる場合にはX*(2&+1&) ⇒ X*2& + Xと考える。*2というのは左1ビットシフト演算と同じなので加算器で実行できる。

'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'%%% x方向画素数×3に最も近い4の倍数を求める。
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Private Function GetNw(Nx As Long) As Long
  Dim i As Long, j As Long

  i = Nx * 3&
  j = i Mod 4& '
  If j > 0 Then '
    i = (i \ 4& + 1&) * 4& '
  End If
  GetNw = i
End Function

'###########################################################
'### カレントイメージに指定色で点を描画する
'###########################################################
Public Sub DrawPixel(cg As RGB24bitBitMap, X As Long, Y As Long, P As RGB24bitPixel)
  Dim L As Long

  L = X * 3& + Y * cg.Nw
  cg.PixelBuffer(L) = P.B
  cg.PixelBuffer(L + 1) = P.G
  cg.PixelBuffer(L + 2) = P.R
End Sub

Public Type RGB24bitBitMap
  Header As RGB24bitBitMapHeader ' RGB24bitタイプのBitMapヘッダー
  PixelBuffer() As Byte ' RGB画素バッファ領域
  Nw As Long ' (x方向画素数×3に最も近い4の倍数) = (y方向に隣接する画素までのバイト距離)
End Type

  【フレーム・メモリ】

 DirectXコンピュータ・グラフィックスの画面は、

 3次元グラフィックスでは、不透明な3次元オブジェクト(物体)を描画する場合には、描画する順序に依らず、常に手前にある物体を優先して表示しなければならない。
 通常のフレーム・メモリは後書き(上書き)優先となるため、予め視点(カメラの位置)から遠い順にソートして遠くの物体から順に描画するようにしておけば矛盾のない画像が得られる。このソート法を奥行方向(Z方向)にソートするのでZソート(Z-sort)法と呼ばれる。しかし、図2のような入れ子になっている図形の場合はZソートすることができないので、この方法は万能とは言えない。
 これに対して、Zバッファ法と呼ばれる方式がある。R,G,B8bitの画素単位の色情報を格納するメモリ以外に、


 

【図2】Zソートできない図形の例


透視変換法

スクリーン平面への投影 理論

 図1に示すように、視点(観測者の位置)をP、注視点(見ている場所)をO、座標変換される点をQとし、視点Pから注視点Oへのベクトルを、 視点Pから点Qへのベクトルをとする。ここで、点Oを含み、ベクトルと直交する 3次元空間中に存在する平面W(スクリーン平面)を考え、線分

延長線と交差する平面W上の点Rへ点Qを投影する問題を考える。

【図1】座標変換

 平面WOを始点とし、ベクトルと直交するベクトルから成ると考えるこ

とができる。従って、投影された点をRとし、点Pおよび点Oから点Rへのベクトルをとすると、次の2式が成立する。

                    (1)  [直交しているから]
                 (2)
上記、2式より
             (3)
ここで、
                              (4)
とおくことができるので、(3)式に(4)式を代入して
           
           
よって
                   (5)    
となりαが求まる。
 従って、(4)式より、が求まり、さらに(2)式に代入してが得られる。
以上のように、任意の3次元の点(座標)がスクリーン平面W上に投影される。

2次元座標への変換
 ベクトルは3次元空間に存在する平面W上のベクトルである。これを平面W上の2次元座標に変換する。点Oを始点とする平面W上の互いに直交する2つの単位ベクトルをとする。これらのベクトルは視野の横(左右方向)軸および縦(上下方向)軸である。ベクトルとこれらの単位ベクトルの内積をとると、
              (8)
               (9)
となり、ベクトル上に投影される。これによって、3次元座標が2次元座標に変換されたことになる。

            【図2】2次元座標への変換
            

平面W上の直交する2つの単位ベクトル
 それでは一体どうやって、平面W上の互いに直交する2つの単位ベクトルを求めればよいのだろうか?

Dirext X の世界では、
  ●視点座標を定義するため   vEyePt(xeye, yeye, zeye)
  ●注視点座標を定義するため  vLookat(xL, yL, zL)
  ●観測者の上方を示すため  vUpVec(xup, yup, zup)
2つの座標と1つのベクトルを指定する。

ず、上方向のベクトルを求める。
vUpVec(xup, yup, zup)は平面Wと並行であるとは限らない。
そこで、観測者の上方を示す姿勢ベクトルvUpVec(xup, yup, zup)を使って注視点Oより上方向の点Mを決定する。
      点Mの座標 (xL+xup, yL+yup, zL+zup)
前述の方法を用いて、点Mが平面Wに投影される点Nを求める。

ベクトルを正規化すればが得られる。  次に、ベクトルの外積をとれば、平面W上でベクトルに直交するベクトルが得られるので、これを正規化すればが求まる。
 
       【図3】単位ベクトルの求め方