2011年06月23日

ドングル

すっかり梅雨ですが雨雨にも負けず、
休日はバイクで駆け抜けるgood sun晴れこと山口です。
お久しぶりで御座います。

さて少し前に自宅での3DCGのアニメーション用に
messiah studio(http://www.projectmessiah.com/)というソフトを超キャンペーン価格で購入したのですが、
このソフトのライセンス認証が少し面白い仕組みになっていました。
市販のUSBメモリをハードウェアキーとして動作させるのです。

昔はライセンス認証の為だけに専用のドングルと呼ばれるハードウェアを使っていたのですが、
果たして市販のUSBメモリがその役目を果たせるのか気になったので少し調べてみました。
するとWindowsではWMIという機能でディスクドライブのユニークなIDを取得できるようです。
ソースコードも沢山見つける事が出来たのですが、
C#やVBのコードばかりでしたので、C++ではどう書いたら良いのか試しに書いてみました。

今回はUSBのディスクドライブを列挙してその固有IDを表示するものです。
(ソースコードはVisualStudio2010のコンソールアプリケーションで動作確認しています。)


#define _WIN32_DCOM
#include <iostream>
#include <windows.h>
#include <chstring.h>
#include <comdef.h>
#include <Wbemidl.h>

using namespace std;
#pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv){
IWbemLocator *wbem_locator = NULL;
IWbemServices *wbem_services = NULL;
IEnumWbemClassObject *wbem_enumerator = NULL;

// まずはCOMの初期化とか
CoInitializeEx(0, COINIT_MULTITHREADED);
CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
// WMIにアクセスするためのインスタンス作成
CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<LPVOID*>&wbem_locator));
// root\cimv2名前空間に接続
wbem_locator->ConnectServer(_bstr_t(L"\\\\.\\ROOT\\CIMV2"),
NULL, NULL, 0, NULL,
0, 0, &wbem_services);
CoSetProxyBlanket(wbem_services,
RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);

// USBインターフェースのディスクドライブを取得するクエリを発行
wbem_services->ExecQuery(bstr_t(L"WQL"),
bstr_t(L"SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"),
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL, &wbem_enumerator);

IWbemClassObject *wbem_object = NULL;
ULONG returned = 0;
while(wbem_enumerator){
wbem_enumerator->Next(WBEM_INFINITE, 1, &wbem_object, &returned);
if(returned == 0){
break;
}

VARIANT value;
VariantInit(&value);
// ここで取得できる文字列がUSBの固有ID
wbem_object->Get(L"PNPDeviceID", 0, &value, 0, 0);
cout << static_cast<char*>(bstr_t(value)) << endl;
VariantClear(&value);
}

wbem_services->Release();
wbem_locator->Release();
wbem_enumerator->Release();
if(wbem_object){
wbem_object->Release();
}
CoUninitialize();

return 0;
}


COMの初期化関係で行数が多いですが、
実質はインスタンス作成部分から固有ID取得までが目的の処理になります。
この固有IDを基にしたライセンスファイルを作成して、
アプリケーション起動時に二つの整合性を確認出来れば確かにハードウェアキーとして使えそうです。
面白くなってきたのでもしかしたら次回に続くかもしれないです。

posted by 管理人 at 20:10 | プログラミング

2011年06月10日

QtでGUIプログラミング始めました

お久しぶりです。 みやじーですわーい(嬉しい顔)

最近、趣味でQtと呼ばれるC++言語で書かれたGUIツールキットを用いて
ツール作成を行っておりますひらめき

Google Earth や Skype、 Doxygen、 Maya 等もQtを使用して
作られているようですexclamation

Qtについて詳しくはこちら
http://ja.wikipedia.org/wiki/Qt

シグナル・スロットと呼ばれる機能が特徴的で、
オブジェクト間の連携がスマートに記述できます手(チョキ)
これが結構面白くて、いろいろと参考になると思います。

boostにもsignalとslotという機能が入っていますが、
こちらも参考にしてみると良いと思います。
オブジェクト同士の連携を行う仕組みを考える上で非常に勉強になりまするんるん
お勧めの参考書です。
http://www.amazon.co.jp/dp/487311344X

書籍などは少ないですが、サンプルプログラムを解析しながら勉強していますあせあせ(飛び散る汗)

さくさくとスタイリッシュなGUIが簡単に作れて楽しいです。
皆さんもQtを勉強してみてはいかがでしょうか?

posted by 管理人 at 20:07 | プログラミング

2011年05月17日

計算の優先順位

こんにちは。平尾です。
最近、お昼はぽかぽか暖かく、散歩にはうってつけです晴れ
また靱(うつぼ)公園はちょうどこの季節、いろんな種類のバラが咲いており、
オフィス街の人々の癒しの空間になっていますかわいい
自然に触れるのは気分転換にもとても良いですよるんるん

***


つい先日、「この答えわかる?」と、こういう計算式を見せられました。メモ
6÷2(1+2)=

ネットで話題になったものなんですが、皆さんはどんな解答をしますか?
答えは



(↑答えがすぐ分からないよう、白文字で書いています)
とのことなんですが、見事に引っかかってしまいましたあせあせ(飛び散る汗)


プログラムにも同じような計算の優先順位は大事で、
    int value = *p++;

なども見慣れていないと、
何が起こってるのかが分かりにくいと思います。
また、かなり極端な例ですが、
    int c = a++-++b;

こんな書き方もできてしまいますがく〜(落胆した顔)

そういえば学生時代にフラグの判定をしようとして、
    if( !flag & 0x01 ) {

と書いて、何がどう間違っているのか気付くのに
かなりの時間を要してしまったのを思い出しました…もうやだ〜(悲しい顔)


例え自分の中では分かっていても、
パッと見の分かりにくさ、不具合の発生を抑えるため、
できるだけ括弧を付け、優先を見やすくした方が良いと思います!
他の人が見る可能性があるのであれば尚更必要だと思います!

そうすれば今回の問題↓も
(6÷2)(1+2)=
間違う人がグッと減ったんじゃないかと思いますパンチ
決して負け惜しみというわけでは…


みなさんも変な記述ミスで失敗しないよう、
計算の優先順位にはお気を付け下さいわーい(嬉しい顔)

posted by 管理人 at 19:27 | プログラミング

2011年04月12日

VisualStudio Tips

こんにちは。平尾です。
寒い間は靱公園にはまばらにしか人がいませんでしたが、
桜が咲くこの時期からかなり多くの人が集う場所になってきました晴れ
それにしても桜はいいですね!わーい(嬉しい顔)
見ているだけで元気が貰える、そんな気がしまするんるん

***


本日はVisualStudioでのtipsを4つほど紹介したいと思います。
細かすぎる技が多いですが、ご了承くださいふらふら


1InteliSenseのジャンプ後に元の位置に戻る
定義元を見るべく、右クリックして
「定義へ移動」
をしたとき、同じファイルだった場合は元の位置に戻るのが大変です。
そんなとき Ctrl + ハイフン!
無駄な時間が省けて便利です。


2複数ファイルを開いたときの選択方法
VisualStudioでファイルを複数開くと、
右の方に▼な感じのボタンが出ると思います。(図を参照)
20110412_20.png
それをクリックした後、ファイルをクリックせず、
ファイル名を直接入力することで選択できます。
(例えば main.cpp と入力すると、選択カーソルが該当ファイルに合います)


3プロジェクト内のファイルを名前順に並べる
ソリューションエクスプローラ内の左から2番目のアイコン(図を参照)
20110412_30.png
をクリックすると、選択中のプロジェクト以下のファイルが名前順に並び替えられます。
もう一度押すと元の状態に戻ります。
ファイルを名前順で見るのはそんなに無いかもしれませんが…あせあせ(飛び散る汗)


4ビルド構成のボックスの枠を広げる
長いプロジェクト構成名が隠れてしまって不便なときは、この方法で広げましょう。
メニュー横の空いているところを右クリックし、
「ユーザー設定」
を選択します。
この状態で、先程のビルド構成のボックスを選択、
マウスを枠の右端に合わせると伸ばせるようなカーソルになります。
20110412_40.png
伸ばし放題です!



普段からよく使うツールではちょっとしたことを覚えるだけで、
無駄な時間がグッと減ります時計
効率の良い開発をして、より多くの開発時間を作る。
それが良い作品につながると信じています手(グー)
これからもより良い作品を作れるよう、がんばっていきたいと思います!ぴかぴか(新しい)


posted by 管理人 at 14:34 | プログラミング

2011年04月05日

続・アンチエイリアス

こんにちは、あっという間にヘキサドライブ4年目に突入したケイタですわーい(嬉しい顔)
今日は月頭の火曜日ということで、東京大阪合同の誕生日会が開催されましたプレゼントぴかぴか(新しい)
今回もおいしいケーキを頂きましたるんるん

20110405_cake.jpg

手前のケーキがイイ感じのボケをしてますねカメラひらめき


さて、少し前にイワサキがアンチエイリアシング技法のMLAAの紹介をしていましたが、
他のアンチエイリアシング技法が発表されていたのでご紹介します。

・Subpixel Reconstruction Antialiasing (SRAA)
http://research.nvidia.com/publication/subpixel-reconstruction-antialiasing
BattleField 3に採用されていることがGDC2011で発表され、一躍脚光を浴びることとなったアンチエイリアシング技法です。
こちらもMLAAと同様に、従来使われていた2xMSAAや4xMSAAよりも遥かにジャギが目立たなくなるようでするんるん
それでいて高速に処理することが出来るというのがSRAAの強みのようですねパンチ


最近はGod of War3でMLAAが採用され、アンチエイリアスをポストエフェクトフィルタで処理させようという研究がとても盛んですグッド(上向き矢印)グッド(上向き矢印)
何故そのような風潮になっているかと言うと、よりフォトリアリスティックな映像を求めるゲームのレンダリング方法に採用されるのが、Deferred Shadingが多いというのが理由の一つです。
Deferred ShadingをするためにはMulti Render Target(MRT)を使用して、一度のレンダリングパスで複数のターゲットに対してピクセルの書き込みをしなければなりません。
しかし、DirectX9までの世代では、Multi Render Targetを使用すると従来使われていたMSAAが使用できなくなってしまうという大きな欠点がありました。
そこで、MSAAは使用せずにアンチエイリアス処理を行うために、ポストエフェクトフィルタでアンチエイリアシングをしようという大きな流れになったと考えられます。

これからも流行の技術の情報をきちんとキャッチできるように、アンテナを広げ続けたいと思います耳ぴかぴか(新しい)
それではまた手(パー)

posted by 管理人 at 22:44 | プログラミング

2011年02月07日

メモリ管理は奥が深い・・・

お久しぶりです、ミヤジーです。
最近はメモリ管理について勉強していますパンチ
皆さん、C言語でメモリ確保する際はmallocを使用していたと思います。
C++言語になってからnewを使用するようになり、直にmallocを使用する機会が減ったと思いますが、
ゲーム制作においては、メモリを厳密に管理したいという理由で、自作メモリアロケータを書くということがあります。
(また、mallocは遅いのでアロケータを書くという話も耳にします。)

そこで、ふと思ったのですが、本当にmallocは遅いのでしょうかexclamation&question
mallocについて調べてみると、高速化を図るためにいろいろな改良をしたmallocが考案されていました。

・dlmalloc
・phkmalloc
・jemalloc
・tcmalloc
・nedmalloc
...etc

以上に挙げたmallocの実装は、ソースコードを見ることができるので勉強してみては如何でしょうか?
メモリ確保と解放のための高速化技法がふんだんに取り入れられていますexclamation×2
また、メモリの使用効率を上げるために、いろいろな工夫がなされています。
下手に自作メモリアロケータを書くと、mallocの方が速くてメモリ使用効率が良いということに・・・たらーっ(汗)

そして、メモリ管理といえばガベージコレクション!
http://ja.wikipedia.org/wiki/%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

ということで、お勧めの本を1冊紹介したいと思います。

http://www.amazon.co.jp/dp/4798025623

ガベージコレクションについて非常に分かりやすく解説されているので、
是非読んでみて下さいexclamation×2
メモリ管理は奥が深いですあせあせ(飛び散る汗)

posted by 管理人 at 21:23 | プログラミング

2010年10月19日

プロファイラ

こんにちは。平尾です晴れ

学生さんは来年の就職活動に向けて制作にとりかかり始める時期でしょうか。
PC上で動く作品だと機種によって大きく性能が変わってくるのであまり意識していないかもしれませんが、今回は処理時間測定プログラムについて説明したいと思いますモータースポーツ

処理時間測定プログラムは一般的にはプロファイラと呼ばれています。
プロファイラはゲームを作る上でとても重要な機能で、どんなゲームタイトルでも開発用機能として用意されていると思います。
ゲームの処理時間は1/60秒や 1/30秒といった感じで非常にシビアなため、高速化できるところはできるだけ行っていますパンチ

ところが、プログラムを組んでいて
「ここは時間がかかるだろうなぁ」
と思っていても、意外と処理時間が短かかったり、逆に
「ここは簡単な処理なので大丈夫だろう…」
と思っていても、呼び出し回数が膨大ですごく処理時間が長くなったりしますがく〜(落胆した顔)


実際にどれくらい時間がかかっているのかを知るためには、測定するプログラムを書けばいいわけです!ひらめき
プログラムのためのプログラム。
というわけで、非常に簡単なプロファイラの説明をします。


考え方は非常にシンプルです。
処理したい区間の前後で現在の時間を測定して、時間の差分を表示する、というものです時計
    int function(void)
{
// 開始時間(A)を取得
:
:

// 終了時間(B)を取得

// (B) - (A) で差分を求め、画面に表示する
}

PCでの時間測定には次の関数を使用します。
 QueryPerformanceFrequency : 高分解能パフォーマンスカウンタの更新頻度(1秒間の更新回数)
 QueryPerformanceCounter : 高分解能パフォーマンスカウンタの現在の値
時間測定には timeGetTime(), GetTickCount() などもありますが、上記関数がより細かい粒度で時間を取得できます。


計測開始と終了で QueryPerformanceCounter を呼び出し、カウンタを取得します。
カウンタの差分を QueryPerformanceFrequency で割れば、処理に何秒かかったか測定できます。
QueryPerformanceFrequencyをそのまま使うと結果には非常に小さい値しか出てこないので、1/1000, 1/1000000 などにして使うことで、ミリ秒やマイクロ秒といった単位で取得することが出来ます。


プロファイラの基本は上記の形です。
さらに使いやすく&分かりやすく変更するなら
・プロファイラに文字列を渡し、同じ名前の処理を後で集計、一覧表示するメモ
・グラフなど使用してグラフィカルに表示する
・使いやすくするため、クラスのコンストラクタとデストラクタを使って時間を測定
といったことが挙げられると思います。
この辺の詳細が気になる方は GameProgrammingGems (3巻1-17、2巻1-11、1巻1-14)を参考にすると良いと思います。位置情報


処理時間に余裕が出来れば、より多くのキャラクタを表示できたり、さらに追加でいろんな演出が出来たりします。プロファイラを使い、一番処理の重い箇所(ボトルネック)を見つけ、そこを高速化していきましょう!新幹線
あっと驚く作品が出来上がるのをお待ちしていますわーい(嬉しい顔)


posted by 管理人 at 11:27 | プログラミング

2010年08月23日

手続きを一まとめ

こんにちはexclamation×2
東京進出で引越をしてから10ヶ月程経ちましたが、免許証の住所変更をまだしていなかったマイキーです。
お店でポイントカードを作る際、免許証記載の住所が滋賀に住んでいた時のままで焦りました・・・あせあせ(飛び散る汗)

こういう事は引越しの時にまとめてやっておけば良いのですが、他にやる事が多くて「また今度でいいや・・」等と後回しにしてしまったり、忘れてしまったりしてしまいがちですよねexclamation
(そしてずるずると1年近く引きずってしまう訳ですねexclamation×2)

引越しに際して必要な手続きを列挙すると、
・役所へ転出手続き
・電気事業者への解約手続き
・水道事業者への解約手続き
・通信事業者への解約手続き
・保険会社への住所変更通知
・携帯電話事業者への住所変更通知
・クレジットカード会社への住所変更通知
・引越し先の役所へ転入手続き
・引越し先電気事業者への契約手続き
・引越し先水道事業者への契約手続き
・引越し先通信事業者への契約手続き
・・・
・・
等など・・・、上に書いたもの以外にも非常に多くの手続きが必要になります。
プログラム中、このような「一つの動作をさせる為に、複数の手続きが必要な処理」を記述する場合、一つの関数にまとめて記載してしまうのがセオリーですひらめき

void 引越し処理( 現住所, 引越し先 )
{
 役所へ転出手続き(現住所, 引越し先);
 電気事業者への解約手続き(現住所);
 水道事業者への解約手続き(現住所);
 通信事業者への解約手続き(現住所);
 ・・・
 ・・
}

こんな感じで。

一つの関数にまとめるメリットとして、大きな所で保守性の向上が挙げられます。
引越しを何度も直書きで記述している場合、例えば「車の住所変更手続き」を追加しようとするとソース中の引越し処理を行っている部分を探し、一つ一つ追記しなければなりません。
その際、見落としや漏れがあった場合バグの原因にもなりかねませんがく〜(落胆した顔)
そしてそのバグを見つける為にもまた、一つ一つ引越し処理の記述されている部分をチェックしていく必要があります。
処理を削除する場合も同じく・・・です。

バリバリプログラムを組んでいる最中は面倒に感じるかもしれませんが、デバッグや保守/拡張の段階になってジワジワ効いてきます。
少し立ち止まって、重複しているコードは無いか見直してみてはいかがでしょうか。

私はこのブログで住所変更していないクレジットカードがあるのを思い出しました。
また今度手続きしておきます。
また今度・・・眠い(睡眠)


posted by 管理人 at 13:33 | プログラミング

2010年08月18日

コードも渡してみました

連日、東京で38度を記録したりと暑い日々晴れが続いている今日この頃。
最近の私の相棒は、エアコンではなく扇風機台風だったりします。意外と快適ですよ。
こんにちは、ハラです。

以前、アプリが使うバイナリデータをRubyで作る事を書きましたが、
データを作るとなると、定数の値のようにアプリ側とデータ側で共通化したいモノが出てきます。

これを別々に定義すると、一方を変更して、他方をそのままにしていた・・・というミスが怖いですがく〜(落胆した顔)

そのため、独立したファイルに定数を定義し、C/C++(アプリ)側とRuby(データ生成)側の両方が参照したり、Ruby側がC/C++のソースコードを参照したりなど、1つの定義で済むようにします。


その際、Rubyの「eval」という関数が面白い活躍をしてくれますひらめき

evalは、渡された文字列をぴかぴか(新しい)Rubyスクリプトとして評価するぴかぴか(新しい)という関数です。
スクリプトとして評価されるので、定数の定義はもちろんの事、各種演算なども行ってくれますメモ

これに、るんるんRubyはC/C++とほぼ同等の演算子が用意されているるんるん
ということを踏まえると下記のような事もできるようになります。


C/C++側でインクルードする事を想定し、以下のような内容のファイルがあるとします。
  DEF_ALPHA   = 123,
DEF_BETA = 456,
DEF_GAMMA = DEF_ALPHA + DEF_BETA,
DEF_DELTA = (DEF_GAMMA * 2 + 1) << 4,
そして、ここで定義された内容を、Ruby側でも定数として使えるようにしたいと思います。

まずは、evalを使わないで実現する方法を考えてみますバッド(下向き矢印)
ぱっと思いつくのは、文字列を1行ずつ解析する方法でしょうか。

DEF_ALPHA や DEF_BETA は数値の代入なので簡単ですが、DEF_DELTA となるとちょっと大変ですもうやだ〜(悲しい顔)
さらに複雑になれば尚更ですねちっ(怒った顔)

では、evalを使う方法を考えてみましょうグッド(上向き矢印)
行末のカンマはRubyの文法上ダメなので、文字列を読み込んだ後で削除します爆弾
あとは、1行ずつevalに渡すだけですfax to

スクリプトとして評価されるので、定義された定数の参照や演算は
インタプリタが処理してくれるという寸法ですひらめき

実際に試すと、evalを使った方がどのくらい簡単になったかを実感して貰えると思いますわーい(嬉しい顔)


普段、C/C++のようなコンパイル型言語を扱っていると、
プログラムを実行する時点でコードを渡すという発想が出てこなくなるかもしれません。
(ちなみに、私はまったく出てきませんでしたふらふら

でも、別の言語なら簡単に出来てしまいます。

言語だけでなく使っているツールやゲーム、考え方など、新しい何かに触れたら、
今まで無理だと思ってたことがあっさり出来るようになるかもしれません。
もしかしたら、想像もしてなかった事が見えてくるかもexclamation&question

そう考えると、ちょっとワクワクして来ませんか?

夏休みも残り少ないですが、是非色々と試してみて下さい。手(チョキ)
きっと面白い何かが見つかるんじゃないかなと思います。

posted by 管理人 at 18:59 | プログラミング

2010年07月12日

原因、見えますか?

7月も中旬になり、晴れ晴れが近づいてきたかなと思う今日この頃・・・
まだまだ、雨梅雨雨は健在だと雨がアピールしてきます。
雨は大切ですが、蒸し暑くあせあせ(飛び散る汗)なるのは許して下さい・・・・わがままですかねふらふら
こんにちは、ハラです。

今回は、プログラムでエラーが発生した時がく〜(落胆した顔)について書いて見たいと思います。

といっても、単にエラーというとものすごく広い話になるので、
Rubyでちょっとしたツールを作り、それを使う時の1例に留めたいと思いますひらめき

尚、Rubyのバージョンによって、これから書く出力内容が違うかもしれませんが、
そこは各環境に置き換えて頂ければと思います猫

ということで、まずはファイルを読み込んでみましょうるんるん
File.foreach("test.txt") do | line |
puts line
end
上の例では、ファイルから1行ずつ読み込み、その内容を出力しようとしていますメモ
test.txtファイルが存在すればその通りの動きになりますが、
ファイルがない場合は、以下のように表示されました。
test.rb:1:in `foreach': No such file or directory - test.txt (Errno::ENOENT)
from test.rb:1
test.txtという名前のファイルかディレクトリがない。といった内容ですね。

実際にコードを書いた人には十分な内容ですが、
中身を知らない人やプログラムを知らない人には、ちょっと不親切かもしれませんもうやだ〜(悲しい顔)
なので、ファイルが存在するか事前に調べるように変えてみましょうひらめき
name = "test.txt"
if !File.exist?(name)
puts "#{name}ファイルがありません。スクリプトがあるディレクトリに#{name}を置いて下さい。"
exit -1
end

File.foreach(name) do | line |
puts line
end
事前に調べてファイルが存在しない場合は、日本語でエラーの内容を伝え、
簡単な解決方法を提示するようにしました。

変更する前に比べると、多少は分かりやすくなっているかと思います。

他にも、
1ファイルは存在するが、読み込むデータがなかったケース
2読み込んだデータが不正だったケース
3正しく処理出来たが、出力が出来なかったケース
などなど、ツールを使う際に起こりそうなエラーは色々考えられます。

これらのエラーには、原因を正しく伝えれば、ツールの使い手側で問題を解決出来るものがあります。

そんな時は、コーディングを行う時点で手間をかけあせあせ(飛び散る汗)
エラーの解決方法まで提示出来るようにするのもありかなと思います。

使い手側の手間を減らせるだけでなく、作り手側へのエラーの問い合わせが減り、
結果的には、全員の効率があがるかもしれませんよ?わーい(嬉しい顔)


posted by 管理人 at 15:11 | Comment(0) | プログラミング