OpenGLのC++11対応C++ Wrapper OGLplus

OGLplus

Twitterで面白いライブラリを教えてもらったので、ちょっと内部を覗いたりしてました。


OpenGLC++11で使用出来るようにしたWrapperライブラリだそうです。
ソースコードオープンソースで現在も開発中みたいで、Boost ライセンスで配布されています。


依存しているのはSTLのみで、他のライブラリは必要ありません。
いや、pngの部分だけは外部ライブラリ依存かもしれないです。
当然ながら、OpenGL自体は必要です。
コードを読んでみて、中々参考になる部分が多かったので自前のライブラリを作る際に役立つかもしれません。


現在のところLinux上でのみ動作確認されているようですが、OGLplus自体をある程度修正すればWindowsでも動くかもしれないとのこと。
コンパイラC++11の機能を色々と使用しているので、gcc 4.5.1以上必須。


やはり読んでいて楽しいライブラリはいいですね〜。

C++を知らないゲームプログラマ達

マルチプラットホームライブラリを作ってみた。
※リンク先pdf


有名なSEGA本の著者、平山さんによる今年のCEDECでの講演内容である。

ゲームプログラマになる前に覚えておきたい技術

ゲームプログラマになる前に覚えておきたい技術

内容的には十分読み応えのあるのだが、一部釈然としないところもある。
主に4.9章の「標準ライブラリや言語機能について」というところから。

何故標準が嫌なのか

ゲームプログラマはなぜかC++標準ライブラリを使わない。
いや、使おうとする人もいるが何かと理由をつけて使わない。
その理由が大体困ったような内容が多い。


リンク先でも書かれているが、vectorにはpush_back()やerase()がある。
そしてこれは安全性と性能の両面で危険な面がある。その通りである。
しかし「erase()は必要ない」と書かれている。
私は「は?」と首をかしげたくなってしまった。
確かにvectorのerase()は何も考えずに使用すると膨大なコピーコストが発生してしまう。
が、vectorにはErase-Removeイディオムというものを使用することにより効率的な要素の削除を行う事も出来る。
それでもなお、「erase()は使うな!削除はpop_back()だけにしろ!」というのならさすがに私はその人を疑ってしまう。


またnewに対して異常に保守的なのも気になる。
もちろん考えなしにnewを行うのは危険ではあるが、vector程度のnewでコストが気にかかるようなことはまずない。
そもそもvectorではreserve()をしておけば余分なメモリを確保することもないはず。
結局動的なコンテナやそれに近いものを実装する際にはメモリを確保することになるので、わざわざ自分で作る理由はない。

そもそもそれは問題ではない

私はSTLを使うことによって大きな問題に出喰わすような事は過去に一度もありませんでした。
ボトルネックになるようなところはコリジョンなどもっと根本的な部分が殆どで、メモリはプールから使用する場合も多く、そういった場合は大量にnewしようがmalloc()しようがさほどのコストにもならない。
そこに対して異常に保守的になってしまい、使用禁止にしてしまうには勿体なさすぎる。
STLはただのコンテナではなく、"コンテナ"、"アルゴリズム"、"イテレータ"、"関数オブジェクト"を統合的に扱う事の出来る素晴しい標準ライブラリです。
それぞれを理解して使用すれば圧倒的に楽をする事が出来るし、間違いなく自信にも繋がる。
なのに、ゲームプログラマC++を理解しようとしない人が多い。

なぜ理解しようとしないのか

必要性を感じないから。そんなものはなくてもゲームは作れるし、アプリケーションも作れます。間違いではない。
そこを理解しようとするために時間を使うならと勉強をしようとしない。
確かに平山さんの言っている事はもっともでもあるし、自分自身でも正しいというつもりもないと言っている。
だが、そこで使う側に理解してもらおうという努力を怠ってしまっているのは悲しい事実である。
C++は膨大な仕様で面倒な事が多すぎるというのも確かだが、なぜそこで理解しようと思わずに思考停止してしまうのか。


現実的に言えば上の人にそんな事は言えないし、押し付ける事は出来ない。
問題が出るくらいなら出る前から対策しておくべきという事だろう。
悲しい事だが、これが紛れもない現実である。

C++を勘違いしてる人の多さ

殆どのゲームプログラマは本当のC++を知りません。
既にC++を過去のプログラミング言語と思っている人も沢山います。
しかしそれは勘違いであり、今なお先進的な言語でもあり、最も古臭い言語でもあるのです。
本当のC++プログラマの負担を最低限に抑えるし、現実的な問題の解決法も持っています。
それを知らない人達はC++をdisり、理解しようともせずにコードを書いてしまい、「C++なんてクソ!」と言い放ちます。
そんな日々をみるたびに私は悲しく思います。

Vimテクニックバイブルを買った

表題の通りVimテクニックバイブルを買ってきました。
パラパラっと読んだ感じですが、感想を。

Vimテクニックバイブル ?作業効率をカイゼンする150の技

Vimテクニックバイブル ?作業効率をカイゼンする150の技


今迄ありそうでなかったVimの逆引きTips本です。
何よりも著者陣がよく知っているお方ばかりで普段Twitterでもよくお世話になっている方々ばかりです。


Vimmerの中のVimmerな方々が執筆しているお陰で安心して読めます。
私自身もVimを5年ほど愛用していますが、全然知らない事が書いてあったり、今迄当然のように使っていた機能にこんな機能もあったのか!?と驚かされるような内容があったりして目から鱗なTipsばかりでした。


特にvimfilerなんかは日本語での公式解説が今迄になかったはずなので、これからは有り難くリファレンスとして参照させて戴きます。
他に個人的に知らなくて驚いたりしたTipsが以下とか。

  • 検索パターンにマッチしないワードを検索する
  • コマンドラインでもword単位でカーソルを移動する
  • %コマンドによるジャンプ機能を拡張する
  • インデント量の違いをハイライト表示する
  • VimCalcを使用してVimエディタ上で計算処理を行う
  • Vimエディタで図を描画する
  • 変数名を命名規則に従って変換する
  • ソースコード中のtrue・falseをトグルで置き換える


などなど。
あと最後1チャプターまるごと使って解説されているunite.vimはもう別格の扱いです。
私も最近はこれがないとコーディングが出来ないほどに依存しているかもしれません。
一度知ってしまうともう戻れなくなる快適さなのでぜひ導入に挑戦してみてください。


個人的にはVimを使うならすぐ参照出来るくらい隣に置いておくと便利な本だと思いますので、Vimでもっと濃い使い方をしたい!!という人ならぜひ購入して作業のお供にしましょう。

vimshellでVimでの開発をシームレスに行う その2

前回の内容より続きです。

vimshellで実際にプログラムを実行する

vimshellの基本機能を理解したところで、実際にコードを書いて実行してみましょう。
今回使用するコードは特に意味はないC言語のコードです。内容には一切の突っ込み禁止です。
とりあえず以下のようなテストコードを用意しました。

#include <stdio.h>

int main ()
{
  int i = 0;

  i = 3;

  if (i == 3) {
    i = 4;
  }

  i *= 2;

  for (i = 0; i < 5; ++i) {
    printf("i = %d \n", i);
  }
}


なんの変哲もないただのC言語プログラムです。
別に必要ないけどMakefileを書いておいてgccでmakeしましょう。
おもむろにvimshellを呼び出し、makeと入力してビルドを確認します。


MinGWgccを使ってビルド出来ました。
ちょっと余計な情報がくっついていますが、気にしないで。

プログラムを実行する

実行するのには様々な手段があります。
まずは一番ノーマルな方法で。



これでvimshell上に実行されたプログラムが出力出来ます。
これは一番ノーマルな方法ですが、プログラムの実行方法は他にも色々とあります。

iexeを使ってgdbデバッグ

"iexe"はプログラムを対話コマンドに特化し実行します。

% iexe gdb test.exe

インタプリタを起動しプログラムの入出力を行う事が出来ます。
上のように実行すると、なんとVim上でgdbが動きます!!



これでVim上でプログラムの実行とデバッグまで出来るようになりました。
基本的な開発ならこれで十分なはずです。
もちろん、iexeはこれ以外にもスクリプトを実行するインタプリタの端末用途として使用出来ますし、これだけに留まりません。
使い方はユーザー次第でいくらでも広がります。
全てはVim上で完結し、Vimのフル機能を使用する事が出来るという最大のメリットがあります。

その他にも様々な実行方法

vimshellは"iexe"以外にもGUIを実行するのに特化した"gexe"というものがあります。
これはゲームプログラムなど、GUIを必要とするものに対して使用出来ます。

更にvimshellには端末コマンドに特化した"texe"もあります。
まだまだ不完全ではありますが、iexeなどでは実行出来ないような特殊なものを実行する事が出来ます。
動作も不安定でCygwinの導入が必須だったりと敷居は高いですが、よりvimshellの可能性をみたいという人にオススメ。
"texe"と同種のプラグインとしてConque Shellというものがあったりしますが、こちらもまだまだ発展途上といった感じ。
しかし可能性は無限大。ぜひ活用してみましょう。

vimshellで快適なVimライフを

と、ここまで様々に取り上げてきましたがこれでもvimshellの機能としてはほんの一部です。
まだまだvimshellには可能性があり、他のプラグインと連携した際にはこれ以上ない快適な開発環境になると思います。
私は仕事でもvimshellを活用し、VisualStudioといったIDEを必要としない生活を送っています。
もちろんIDEにも素晴しいところがあり、それらを否定する気はありませんがVimには他のIDEには絶対にないものがあります。
neocomplcacheやunite.vimだけではなく、Vim自身のもつ機能と合わせていけば仕事や開発を更にシームレスに行える事でしょう。

vimshellでVimでの開発をシームレスに行う その1

vimshellとはVimプラグインのひとつであり、Vim上でその名の通りshellを使えるようにするプラグインである。
作者はneocomplcacheでも有名なVimmerShougoさんであり、その他にもとても優秀なプラグインを開発されております。
今回はvimshellを使うことにより、何が素晴しいのかを焦点にあてて説明したいと思います。

vimshellを使用するために

当然プラグインをインストールする必要があります。
ここでは細かい説明は省くとするのでインストールは各自で調べてみてください。

vimshell

また、vimshellの動作にはvimprocが必須です。こちらも合わせて導入してください。

vimproc

vimshellと連携するプラグイン

vimshellはそれ単体でも非常に有用ですが、今回はそれだけではなくneocomplcacheとunite.vimもインストールしているという前提で進めます。

neocomplcache

unite.vim

vimshellで使用するコマンドをインストールしておく

当然vimshellは通常のshellと同じように使う事が出来るので使用するためにはあらかじめコマンドたちをインストールしておきます。
私がWindowsなので今回はMinGWを使用しています。当然CygwinだろうとSystem32のコマンドを使用する事も出来ます。
前提としてコマンドを使用する場合はコマンドへのパスが通っている必要があります。

:echo $PATH

と、入力してVim環境変数$PATHに実行したいコマンドへのパスを確認しておきます。
問題なければ準備は完了です。

vimshellを起動する

とりあえずvimshellを起動してみましょう。

:VimShell


と、入力すれば上記のような画面になると思います。
ここでとりあえず"cd"コマンドを使ってディレクトリを移動します。


もしここでneocomplcacheがインストールされていれば上記のように次々とディレクトリが補完されたと思います。
これはとても便利な機能です。
と入力すれば補完されたディレクトリを移動し、"/"と入力すればそのディレクトリに入る事が出来ます。
こういう機能を持つshellはほとんどないはずです。私は使った事がないのでわかりませんが、あるとすればzshくらいでしょうか。
これだけでもvimshell+neocomplcacheが強力だという事がわかってくると思います。

vimshellとunite.vimでヒストリ補完

vimshellにはunite.vimがインストールされていれば可能となるヒストリ補完機能があります。
おもむろにvimshellのプロンプト内でと入力してみましょう。


これまで入力してきたコマンドのヒストリが表示されたと思います。
これはunite.vimの機能でvimshellのhistoryをsourceとして使用し、一覧としています。
unite.vimに関して今回の本題ではないのでここではsourceに関して説明はしません。
このヒストリを使用して補完し、よりスムーズなコマンド入力が可能となります。
ヒストリ内の移動は今までと同じようにで行います。
いつも同じようなコマンドを打ちまくるアナタにオススメです。

vimshellの設定とマッピング

非常に便利に使う事が出来るvimshellですが、とりあえず_vimrc(.vimrc)あたりにでも便利なマッピングを書いておきましょう。
よりスムーズにvimshellを呼びだす事が出来るようになりシームレスな開発が可能になります。

" vimshell setting
let g:vimshell_interactive_update_time = 10
let g:vimshell_prompt = $USERNAME."% "

" vimshell map
nnoremap <silent> vs :VimShell<CR>
nnoremap <silent> vsc :VimShellCreate<CR>
nnoremap <silent> vp :VimShellPop<CR>

上記ふたつの設定は好みですが、"g:vimshell_prompt"の設定はWindows用なので注意してください。
マッピングは単にvimshellを呼び出しやすいようにするだけのものです。
キーは各自使い易くて他のマッピングの邪魔にならないようにするように。
とりあえず":VimShellPop"は手軽に呼び出しが出来てすぐ閉じたり出来るので設定していると便利です。

まだまだ便利なvimshell

ここまでだけでもかなり便利という事がわかったと思います。
特に補完を利用したneocomplcacheとunite.vimとの相性が抜群でこれだけでも他のshellを圧倒しています。
しかしこれで終わらないのがvimshellです。
次回は更にプログラムの実行とデバッキングを行ないたいと思います。

MinGWでBoost1.47.0をビルドする

今回は一度やったことがあったはずである、MinGWを使用してのBoostのビルドなんですがどうにもやり方を完全に忘れてしまっていて、大分手間取ったのでここに備忘録として改めて残しておくとします。

ビルドを行う環境

ビルド手順

MSYSを起動し、Boostの置いてあるrootディレクトリに移動し、以下のコマンドを叩く。

start cmd

MSYSからcmdが起動するので、次は以下のコマンドを入力。

bootstrap.bat gcc

以上でrootディレクトリ内にgccでBoostがビルド出来るb2.exeというファイルが出来る。
あとは以下のサイトを参考にしつつ、オプションを正確に入力してb2を実行する。

Boostライブラリのビルド方法

b2 install --prefix=C:\lib toolset=gcc link=static,shared threading=multi var
iant=debug,release runtime-link=shared -j 8

オプションを確認する

"--prefix"はインストールディレクトリの設定。ここは自分の好きなように。
"link"オプションで静的リンク(.a)と動的リンク(.dll)の二種類を作ることを指定。
"threading"はマルチ一択なので"multi"で指定。シングルは上手くビルド出来ない?
"variant"はdebug用とrelease用と二種類あるが、基本はreleaseだけでもよさそう。
"runtime-link"はC++標準ライブラリとリンクするために必要?よくわかっていません。

あとは最後に"-j n"で並列ビルドするためのスレッド数を指定します。
実コア数の2倍くらい指定してもいいんじゃないかと思います。

実際に出来たライブラリを確認

ビルドが完了すると指定したディレクトリ内に"libboost_****-mgw45-mt-1_47.a"みたいなファイルが出来ていると思います。
あとはこれを必要に応じてコンパイル時にリンクするなりしてBoostのライブラリを堪能しましょう。

Vimで精度の高いC++のコード補完を行う

Vimでコード補完するプラグインと言えばneocomplcacheが有名ですが、さすがにC++の補完はなかなか辛いところがあります。(それでもかなり高機能ですが)
そこそこに精度が高い補完を求めるのならOmniCppCompleteを使う手もありますが、これでも限界はあります。
そこでもっと高い精度でのC++のコード補完行うためのプラグインでclang_completeというものがあります。

clang_complete

これはClangという静的コード解析ツールを用いてVim上で解析結果を補完に反映させようというプラグインです。
実際のClangはC++などのコンパイラフロントエンドであり、静的コード解析はあくまでその機能のひとつです。
LLVMと共に現在も絶賛開発中でC++11対応なども期待出来るところです。

clang_completeとneocomplcache-clang

実はclang_completeはneocomplcacheと衝突するため、同時にそのままでは使えません。
なので今回はその競合を解消したneocomplcache-clangを使用します。
とりあえず最低限必要なものは以下の通りです。

clang

neocomplcache

neocomplcache-clang


また、以下は絶対ではないもののあった方がいいもの

python

vimproc

Clangの導入

今回の環境はWindowsの32bit環境なのでリンクから"Clang Binaries for Mingw32/x86"を選択し、最新のClangバイナリを手にいれます。
64bit環境の場合はバイナリがないので自分でLLVMのソースからコンパイルする必要があります。
もちろんそれだと一気に敷居が上がるのでオススメはしません。出来るなら64bit環境でも32bitのVimを使った方がいいでしょう。私がそうなので。
ここらへんはOSや環境に応じて選んでください。場合によってはここで摘んでしまいます。
あとはClangのバイナリ(exeやdll)を適当な場所("C:/llvm/bin"みたいな)に置いてClang側の準備は完了です。

neocomplcacheとその他の設定

まず当然としてneocomplcacheneocomplcache-clangをインストールしておきます。
出来ればここでpythonが使えるようにpythonインタフェースを導入しておくといいです。
pythonインタフェースがあるとlibclangが使用可能になり、更に高速な補完が可能となります。
pythonインタフェースに関しては以下を参考に。

Hack #132: Pythonインタフェースを使う(1)

更にvimprocを使えるようにするとコード補完が非同期になり、操作しやすくなります。

_vimrc(.vimrc)への設定

" 1だとlibclang(clang.dll)を使用する ※要pythonインタフェース
let g:neocomplcache_clang_use_library=1
" Clangバイナリがある場所を指定する
let g:neocomplcache_clang_library_path='C:/llvm/bin'
" ライブラリ指定などのオプション 必要に応じてパス変更で
let g:neocomplcache_clang_user_options =
        \ '-I C:/MinGW/lib/gcc/mingw32/4.5.2/include '.
        \ '-I C:/lib/boost_1_47_0 '.
        \ '-fms-extensions -fgnu-runtime '.
        \ '-include malloc.h '
" neocomplcache で表示される補完の数を増やす
" 補完の数が少ないとstd::vectorなど一部が補完に出現しなくなったりします
let g:neocomplcache_max_list=1000

以上でClangを使用したC++の補完が可能となります。


実際の補完時

その他注意事項

  • 補完する側のコードにシンタックスエラーがある(静的解析なのでエラーがあると補完出来ません)
  • パスがちゃんと通っていない
  • let g:neocomplcache_clang_complete_use_libraryが0と1の場合は挙動が違うので注意
  • 上記が1の場合はpythonインタフェースが動作しておらずエラーが出る可能性あり
  • Vimのバイナリが64bitのケースはClangもpythonも全て64bitの必要があります
  • プリコンパイルヘッダは更に設定が必要なのでこのままでは動作しない(私も動作確認出来ていません)
  • BoostやC++標準ライブラリを使うとそれなりに補完に時間がかかります(マシンスペックで差がでます)
  • Vimプラグインの中ではトップクラスにメモリをくうのでswapに注意(下手するとマシンが固まります)


とりあえず色々とややこしいです。ひとつでも間違っていると正常に動作しないので根気強くやりましょう。
上手くいけばC++の補完をかなりの精度で行うことが出来るようになっているはずです。

2011/8/24追記

neocomplcache-clangのオプション名が変更されたので現在のものへと変更。
旧オプション名は最新では使えないので注意。