2004年09月03日

LightflowをC++から使おうと試す

DLし展開して出来たinlude の下にチュートリアルのソースをコピーしたソースファイルを置き、コンパイルする。
インクルードファイル内でエラー。
なんか、インクルードファイルがWWWの中にいるとか、仕方ないのでWWWをLightflowに置換する。
後、インクルードファイルをすべてVCのインクルードの中のLightflowへコピーする。
そしたら、iostream.hがないとか言われる。
iostreamに書き換えて、using namespace std;も追加する。
そしたら、iomanip.hがないとか言われる。
マニピュレーター用? たぶんいらないと思うのでコメントアウト。
で、とりあえずコンパイルは通るようになった。
でも、リンク時にいろいろとないと言われる。
どうやら、/link Lightflow.libが必要な模様。
で、やっとメイクできた。
実行したらエラー。
C++で組んでもやっぱり環境変数の設定はいるのね。
LIGHTFLOWPATH=C:Lightflow
LIGHTFLOW_SE_MEMORY=32000
LIGHTFLOW_VE_MEMORY=32000
PATH=%LIGHTFLOWPATH%
を設定。で、実行。
tgaイメージが出来た。GIMPで読める。
Lightflow.libも面倒なので、VCのlibフォルダにコピーしてしまった。

投稿者 Takenori : 11:38 | トラックバック

2004年09月04日

LightflowのI/Fをまとめる

Lightflowの各パラメータをクラスにまとめる。早く、I/F作って、ごりごりレンダリングさせてー。まあ、まずはLightwaveのデータをレンダリングできるようにしよう。で、サーフェイスとかパラメタいろいろいじって楽しむんだー。(子供のように楽しげに話す) かっけーって言うようなものを作るっすよー。
 でも、どんなI/Fにするかが問題だな。まずはファイル喰わせてレンダリングするようなのを作りたいと思っているけど、その次はパラメタいじってレンダリングしてって言う作業を手軽に出来るGUIが欲しくなってくるかも。最終目標はシーンをごりごりいじれるツールだな。後ネットワークレンダリングも。あー、わくわくしてくる。
 後、Yさんに教えてもらったのだがXSIがかなり安くなったとか。一番安いのは8万円弱。ちょっと買ってみたい気もする。でも先立つものが。。。お金入ったらまず豪速新PCを買いたいしなぁ

投稿者 Takenori : 06:40 | トラックバック

2004年09月05日

I/Fなどについて悩む

一般的には、レンダーツリーとか言われるものが使われるようだが、どこまでツリーで表現しているのだろうか?
マテリアルの属性や位置はツリーで表しやすいが、特定のオブジェクトにだけライトを当てたい場合などはステートマシンのように設定できる方が望ましい。丸描いてこの中にあるオブジェクトには有効で、こっちの丸の中にあるオブジェクトにはこれで、両方が重なっているところにはこれをといった具合だ。
というか、そんな使い方はしないのかな?
あまりにステートマシンの性質が頭の中にあるせいでそう言う発想になってしまっているのだろうか?
そもそも、Lightflowでそう言うことが出来るのかどうかまだよくわかっていないので、そっちを先に調べるのが先決だな。
ま、今日は他のことで時間がなくなってしまったので、何げに考えていたことを書いただけなのだが。

投稿者 Takenori : 06:41 | トラックバック

2004年09月06日

Lightflowのファイル

Lightflowのシーンは独自のファイルフォーマットがあるようだ。
それも、アスキー形式とバイナリ形式がある。
シーンプロキシをLfASCIISceneProxyにすれば、指定したストリームにアスキー形式でシーンを出力してくれる。
当然、そのファイルをレンダリングさせたり、そのファイルからシーンを構築できたりする。
つまり、I/Fがなくても直接このスクリプトを書けばレンダリングさせることが出来る。でも、それはかなり面倒くさい。やっぱり、I/Fは必要だ。
アレ?ということはこの発見は意味ないか。
ま、ネットワークレンダリングの時に役立つぐらいかな。
でも、なぜか少しI/Fのイメージがわいた。

投稿者 Takenori : 06:42 | トラックバック

2004年10月12日

DirectX9で遊ぼうとする

3DのPRGのシステムを作ろうと思って、まずはDirectXのスキニングサンプル(人が歩いているやつ)を改造して、自分で動かせてナビゲーションメッシュで動きを制限できるようにしようと考えたのだが・・・
3Dまともに動かないっす。
とりあえずサンプルをビルドして動かしたら、ハードウェアがないとかでリファレンスドライバで動く始末。
リファレンスドライバはソフトウェア処理だから・・・1FPSも出ていない。
そういや、開発用マシン買うときにリアルタイム3Dのことはあんまり考えてなかった。
まあ、最近リアルタイム3Dでゲームを作るぞと思って、買い替えを考えていたから大丈夫といえば大丈夫だけど、しばらく3Dのプログラムをいろいろといじって遊べないのは痛い。
そこで、もう一台のマシンで動くかどうか試してみることにしたが、エラーが出て起動しなかった。
もう一台のマシンはGeForce2 MXなので、ある程度は動くと思うのだが、ドライバのバージョンが古いせいだろうか。
ドライバのバージョンを上げたいのだが、このマシンはテレビを見るのにも使っていて、以前に新しいドライバに変更したらテレビを見ることが出来なくなって、古いのに戻した記憶がある。
やはり、新PC待ちかなぁ。

最近、テレビをPCで見るのは少々きつく感じてきたので、これの購入を検討中。
と言うか、まだ買えないので、買えるのを待っている状態。
出たら、即買いかも。
これを買えば、テレビを見ているマシンのドライバを新しく出来るので、このマシンを使って動かせなくはないかな。

どっちも、ああ、なんてこったって感じだな。

投稿者 Takenori : 04:39 | トラックバック

2004年11月26日

FBX形式

モデルとかアニメは何で作るのか? って話しをしていたら、最近はFBX形式が主流らしい。
どうやってFBX形式からXファイルへ持っていくのか少し調べてみたがよくわからない。
Alias FBXにFBX SDKってのがあるみたいなので、欲しいと思ったが、詳しくはメールで問い合わせとか。しかも、英語っぽい。
ちょっと躊躇したが、メールを送った。
でも、モデルもアニメもXファイルでもらえるのなら、別にSDKとかなくていいんじゃ・・・

投稿者 Takenori : 10:22 | トラックバック

Mayaのフリーバージョン

Maya Personal Learning Edition 6ってのがあって、どうやらフリーの様子。
でも、商用利用は出来ない。
つっても、私に商用に値するモデルとかが作れるわけないので、お遊びとしてはこれで十分だろう。
で、System Requirementsを見てみると・・・ 512MB RAM!?
そんなに積んでないっす。
これは、しばらく動かせないなぁ。

投稿者 Takenori : 10:28 | トラックバック

FBXからXファイルへ

FBXからXファイルへする方法をいろいろと調べたが、結局よくわからない。
MotionBuilderの体験版を落としてみても、Exportの項にX形式はない。
さて、どうしたものか?
FBX SDKか、File Formatの仕様書があれば、作れなくもないが、面倒臭い。ってか、なんかあるでしょう?
やっぱり、MayaからXにするのが筋なんだろうか?
よくわからない。

投稿者 Takenori : 10:44 | トラックバック

2004年11月27日

mikotoでアニメーション

mikoto楽しいです。
とりあえず、歩くアニメを付けてみたけど、楽しい。
プログラム面倒くせーなーと思ってみたり。
でも、やっぱりゲーム中で使いたいので、システムは作らないといけない。
早く新マシンのパーツ届かないかなぁ。

投稿者 Takenori : 10:51 | トラックバック

Xファイルが持つ情報

少し調べてみたのでメモ。
Xファイルは、回転、スケール、位置、行列の複数のキーによるアニメーションが可能。
アニメーションはフレームに設定される。
フレームは親子関係構造を持ち、行列とメッシュを持つことが出来る。
スキンウェイト情報は関連するフレームと、その影響を受ける頂点を持つ。

つまり、Xファイルを使うば、ボーンアニメーションと単に物体が動くアニメーションが可能。
ライトやカメラ、モーフは含まれない。
ただし、独自のデータ型が定義出来るので、それによって補うことは可能。

投稿者 Takenori : 10:55 | トラックバック

2004年11月30日

FBX SDK返答

---- 以下引用
Sorry for the slow response on your inquiry. We are currently working on integrating the FBX and Open Reality SDK products into the Alias Conductors third party developer program. http://www.alias.com/eng/partners/index.shtml
This transition is not complete yet but should be soon. I would be very happy to provide you with an evaluation copy of the FBX SDK as soon as it becomes available.

I'm also wondering if you can also supply me with some background details regarding your interest in developing for or with the FBX SDK.
---- 引用終わり

要約すると、今統合中、もうちょっとしたらできるから待っとけ。って、感じでしょうか。
で、文中にあるHPを見ると、pdf読んで、メンバー登録の申し込みをしないといけない様子。。。
なかなかSDKもらえないなぁ。

投稿者 Takenori : 01:34 | トラックバック

Alias conductors program

3つのレベルがある。内容は、簡単に言うと以下のような感じ。

Conductor
いろいろともらえる。

SemiConductor
ペータ版の提供とテクニカルサポートがない。

Conductor Community
開発情報へのアクセスとAlias logoの使用ができるが、開発ツールやテクニカルサポートはない。

つまり、SDKを手に入れるには、SemiConductorレベルじゃないといけないってこと?
料金は、Conductor $1999, SemiConductor $999, Conductor Community ただ。
10万強ですか。
それは辛い。
後、申し込み用紙にはすごくいろいろと書かないといけない上に、約款も長い。
なんか、FBX SDKどうでも良くなってきたなぁ。
どうしても欲しい時は、MayaとMotionBuilderを買ったほうがいいかも。
一番安いので、Maya ¥266,000、MotionBuilder ¥120,000もするけど。
計約40万。高い。。。
これはちょっと・・・

投稿者 Takenori : 01:54 | トラックバック

2004年12月07日

続RAIDへのOSインストール

検索すると同様の症状に悩んでいる人を発見。
このページ
上述のページではGIGABYTE GA-8ANXP-D Rev2.0だが、GIGABYTE GA-8I925X-G Rev2.0でも同じだと思われるので、同じように試す。
まず、Intelのドライバページから最新バージョンのドライバとフロッピー設定ユーティリティの両方をDL。
フロッピー設定ユーティリティを使ってFDを作る。
マニュアル通りに、インストール途中でF6を押す。
ドライバの入力を促された画面で、FDを入れEnter。
以下の4つが出てくる。
Intel(R) 82801FR SATA RAID Controller
Intel(R) 82801FR SATA AHCI Controller
Intel(R) 82801ER SATA RAID Controller
Intel(R) 6300ESB SATA RAID Controller
この内、一番上のIntel(R) 82801FR SATA RAID Controllerを選択。
後は、そのままインストールを続けると・・・ きた! 以前止まっていた場所を越えてインストールが進んだ。
GIGABYTEめぇー。
ま、なんにせよインストールが進んでよかった良かった。

投稿者 Takenori : 01:12 | トラックバック

新PCのセットアップ

新PCも届き、組み立ても終わったので、コードをつないで電源ON。
なぜかCPUファンが回っていない。
なぜ?
一度電源を切り、ケーブルを確認。
問題なさそう。再度電源を入れたら、普通に回った。
なんだったんだろう?
まあ、いいや。
で、BIOSの設定&RAIDボリュームの作成を行う。
作成が終わったら、インストールするOSのCDをMSDNの中から探す。
WinXP Pro SP1a。これだな。
SP2もあるけど、不評なのでやめておく。
で、プロダクトキーの取得方法を見る。
MSDNのサブスクリプションのページから取得するようだ。
Win2kまでは普通にCDに書かれているのに、WinXPは取得しないといけない。
面倒な話だ。
で、ログインしようとしたら.NET Passportになっていた。
いつの間にか統合されたようだ。
.NET Passportは以前メッセンジャーを使うために登録していたので、それを入力。
が、エラーメッセージが出てきた。
エラーメッセージは英語。いったんログアウトして、.NET PassportからMSDNのIDを追加をクリックするような内容のことが書かれている。
そのままログアウトしたら英語のページに飛んだ。
日本なので、日本語のページじゃないといけない気がしたから、日本語のページに戻ってそれらしきページを探す。
探してもないのでヘルプを見てみるが、.NET PassportにMSDNのIDを統合する方法がイマイチよくわからない。
もう一度エラーメッセージの画面を見てみる。
英語のページで手続きをする。
Fast Nameと書かれていたので、ローマ字で名前を入力したらエラーになった。
登録しているのと違うと書いているようだ。
漢字で入れてみる。
うまくいった!
でも、なんか釈然としないものが・・・ Fast Nameとか書かれた英語ページなのに漢字で名前を入れる・・・ 違和感ありありだ。

登録が成功してログインも出来たので、プロダクトキーの取得を行う。
CDをPCに入れ起動。
インストールが進むが、ハードディスクがないと言われる。
あれ?
マニュアルを読むとRAIDのドライバFDを作って、それを途中で入れないといけないらしい。
その通りにしてFD作成、ドライバを読み込ませるが、またハードディスクがないと言われる。
英語マニュアルやマザーボードのCD内のドキュメントを読んで、何通りか試すが全部ダメ。
なんだ、いったい何がいけないんだ。
RAIDボリュームにOS入れられないのか?
でも、マニュアルにはその方法の説明がある。
なぞだ。
ちなみにマザーボードはGIGABYTE GA-9I925X-G。
誰か教えてくれー。

仕方ない、明日いろいろと検索して試してみるか。

投稿者 Takenori : 12:29 | トラックバック

2004年12月24日

元となるサンプルの選択とフォルダの移動

新PCに開発環境も設定できたので、徐々に3Dゲームを開発していくことにした。
で、まずはキャラクターを動かすためのサンプルとしてよさげな物を探す。
MultiAnimationが良さそうだ。
MultiAnimationなら、キャラクターの背後にカメラを設置した状態にし、ユーザーコントロールにチェックを入れると、キーボードでキャラクターを動かすことが出来る。
また、複数のアニメーションをサポートしていて、歩くと走るが入っている。
以上の理由から、MultiAnimationを元に変更を加えていくことにした。

まずは、Sampleフォルダから移動できるように、Commonにあるファイルをプロジェクトのあるフォルダの下にcommonフォルダを作り、プロジェクトが参照しているファイルをコピーした。
そして、フォルダを移動、ビルド。
するとコンパイルとエラー、プロジェクトにはないDXUTMesh.h と DXUTEffectMap.h もヘッダーファイルのみ必要なようだ。
後、プロコンパイル済みヘッダー ファイルを使用するから、プロコンパイル済みヘッダーを作成するに変更した。自動生成や、使わないではなぜかうまくいかなかった。
アイコンのリソースも、前のディレクトリ構成に依存しているので、MultiAnimation.rcを直接編集して、参照するアイコンをプロジェクト下のcommonフォルダのアイコンファイルを参照するようにした。
以上の変更によって、Sampleフォルダ下から移動したところでもビルドが通るようになった。

投稿者 Takenori : 08:21 | トラックバック

初期状態の変更

DWORD g_dwFollow = 0xffffffff; を DWORD g_dwFollow = 0; に変更し、1人目のキャラクターの斜め上視点が初期状態になるように変更。
最初にキャラクターが生成されるところで、pTiny->SetUserControl();として、ユーザーコントロールモードが初期状態になるように変更。
これで、起動したらすぐにキャラクターを動かせる状態になる。

移動できる範囲が狭いので、床のメッシュを生成しているところ ( g_pMeshFloorにメッシュを設定しているところ ) を探し、生成されるメッシュを大きくした。
D3DXCreatePolygon の3番目の引数を16にしただけ。
で、実行。
なんか、円盤形になった。移動させてみると・・・ あり? 移動範囲は変わらない。
コードを追ってみると、CTiny.cppのIsOutOfBoundsメソッドで判定している様子。
で、判定式は、if( pV->x < 0.0 || pV->x > 1.0 || pV->z < 0.0 || pV->z > 1.0 ) ・・・ 床を大きくしても移動範囲は変わらないはずだ。
まずはナビゲーションメッシュで移動範囲を設定できるように変更だな。

投稿者 Takenori : 08:35 | トラックバック

2004年12月25日

ナビゲーションメッシュの導入

単純に、床のメッシュに対して、D3DXIntersectを使って、キャラクターの移動位置のY 1.0から Y -1.0へレイを飛ばして当り判定をすれば、移動範囲を制限できるかと思いきや、g_pMeshFloorがWriteOnlyを指定して生成時されていたため、D3DXIntersect が失敗を返していた。
そこで、ナビゲーションメッシュ専用のメッシュを作り、pMeshFloorと同じものをセット。
これでうまくいくと思ったけど、レイが当たらないと返ってくる。
なぜ?
g_pMeshFloorにテクスチャ座標を設定しているところでブレイクを張り、ポリゴンの座標を見ると、X-Y平面上にポリゴンが生成されていた。
これでは当たるはずがない。
でも、描画時はX-Z平面上に描かれている。
コードを追うと、どうやら描画前にトランスフォームされている様子。
そこで、ナビゲーションメッシュを生成時にトランスフォームすることにした。
トランスフォームは単純に、ポリゴンの各頂点座標をD3DXVec3TransformCoordで、g_pMeshFloorが描画される前に使われるマトリックスで変換するだけ。
でも、g_pMeshFloorが描画される前に使われるマトリックスはD3DXMATRIXA16とか言うやつで、D3DXMATRIXじゃないからだめと言われた。
D3DXMATRIXA16は、効率を上げるために16バイトでアライメントされたD3DXMATRIXだそうだ。 ( SSEとか用ですな。でも、これってDirectX9から追加されたのか? 前からあった? )
で、単純にD3DXMATRIXA16をD3DXMATRIXに代入して、それを渡すようにしたらコンパイルが通った。
レイの当り判定もうまくいった。
が、なぜかまったく移動できない。
IsOutOfBoundsを見ると、論理が逆だった。
関数名からしたら、領域外かどうかを判定するもののようだけど、気分的には領域内にあって移動できるかどうかを判定したいので、気づかなかった。
で、逆にするとうまくいった。
これで、とりあえず平面上は歩けるようになった。

次は、ちょっとg_pMeshFloorが描画される前に使われるマトリックス周りを追いたいところ。ナビゲーションメッシュを外部のファイルから読むためにも。
他にも、CTinyを少し汎用化したい。
徐々に汎用化していかないと。

投稿者 Takenori : 05:08 | トラックバック

2005年01月29日

シーングラフについてメモ

GNU 3DKit
OpenSceneGraph
OpenSG
Open Inventor
NVSG
LAMP
Irrlicht

投稿者 Takenori : 05:45 | トラックバック

2005年01月31日

Boost.Python

Boost.Pythonって言うのがあった。
これを使えば簡単に関数やクラスなどをPythonへ公開出来るようす。
.NET Frameworkに傾きかけていたけど、Pythonも捨てがたいなぁ。

だけど、このコンセプトは他にも使えそうな気がする。

投稿者 Takenori : 03:49 | トラックバック

SWIG

Perl のモジュールが作りたくなり、以前から気になっていたSWIG(日本語ページ) について調べてみた。
これはすごい!!
Perl5、PHP、Python、Ruby、C#などのモジュールが同じソースで簡単に作れる。
C#のモジュールが作れるのであれば、VBやJScriptもサポートされることになるはず。
まあ、あんまりサポートスクリプト言語を増やしても、メンテナンスが大変になるのである程度絞ると思うが・・・ どうしよう?
問題はスクリプト言語にどこまでやらせるかと言うことだな。
もし、ゲームシステム自体をスクリプトで記述するのであれば、全てをサポートしてしまっても問題ない気がする。
動作保証するスクリプト言語は限定することになるだろうが。
逆に、スクリプトを内部から呼び出して使用する場合は、そのスクリプトのインタプリタの内蔵が必要になるため、言語を絞らないとかなり辛い。
もう少し検討が必要だな。

投稿者 Takenori : 16:28 | トラックバック

2005年02月12日

Pythonのライセンス

Python 2.3.4ライセンスPython Software Foundationライセンス(日本語訳)
を読むと、著作権表示とライセンスの添付をすけば、Pythonを組み込んで使えるみたい。

投稿者 Takenori : 00:20 | トラックバック

Pythonを組み込んでみる

簡単なコードでPythonの組み込みを行ってみる。
使ったバージョンはPython 2.3.4。
とりあえず、ソースコードは以下のような感じ。

#undef _DEBUG
#include <python.h>
#define _DEBUG

int main( int argc, char *argv[] )
{
  Py_Initialize();
  PyRun_SimpleString( "from time import time,ctime\n"
    "print 'Today is',ctime(time())\n");
  Py_Finalize();
  return 0;
}

#undef _DEBUG と #define _DEBUG で、#include <python.h> を囲んでいるのは、python.h 内でデバッグ時は python23_d.lib を要求しているため。
ソースDLして python23_d.lib を作ろうと思ったけど、途中で断念。
まあ、Python内まで追わなければ大丈夫なので、いらないはず。
で、_DEBUG のdefineをとってインクルードすることにした。
後、追加インクルードディレクトリに C:\Python23\include を追加。
リンクに C:\Python23\libs\python23.lib を追加。
で、ビルドして実行したら、PyRun_SimpleString に渡しているPythonスクリプトがキチンと実行された。
ここまでは簡単だな。

で、問題はC++のクラスから派生したクラスをPythonで書き、そのクラスをC++から実行するということが出来るかどうか。
シーングラフを使いたいと思っているので、そのシーングラフに追加するオブジェクトをPythonで書けないかなぁというのが動機。
SWIG 楽チンだったけど、boost::pythonはどうだろう?
相互にアクセスするなら boost::python の方が良さげだが。
とりあえず、使ってみないとな。

投稿者 Takenori : 00:28 | トラックバック

boostのVC.NET 2003へのインストール

letsboost::インストールフルインストール方法を参考にして、VC.NET 2003へBoostをインストールした。

インストールディレクトリは、載っているものと違ったので、自分の環境に合わせてbjamへは次のようなパラメタを渡した。

bjam -sTOOLS=vc-7_1 --with-python-root=c:\Python23 --prefix="C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7" install

で、しばらく待てばインストール終了。

※初出時、上記のコマンド引数が"-sTOOLS=vc7"となっていました。VC.NET 2003の時は、"-sTOOLS=vc-7_1"とする必要があるようです。

投稿者 Takenori : 01:43 | トラックバック

2005年02月19日

LAMPページを久しぶりに見る

LAMPのページを久しぶりに見たら変化があった。
デモをDLすると、アクションゲームとしてそれなりに出来ている。
STLやboostが使われておらず、またテンプレートの利用も極力避けたと言うのが少し難。
std::stringではなく、独自stringクラスなのはちょっと・・・
まあ、それは書き換えるか、ラップするかで何とかして我慢するとして、とりあえず使ってみようと思ったが、Xファイルのコンバーターはアニメーションをサポートしていない?
DirectXのSDKについているtiny.xをコンバートして、シーンビューアで見たがアニメが消えているっぽい。
また、コンバータのソースコードを追ってみてもそんな感じ。
となると、今のところMaya専用か?
せめて、Metasequoia + MikotoLightwaveから読み込む方法が用意されていて欲しいところ。

投稿者 Takenori : 15:59 | トラックバック

ファイルフォーマットを考える

ファイルフォーマットは、Xファイルを拡張したものにしようと考え中。
Xファイルのみでは、オブジェクトに関する物にしか扱えないので、シーンを再生したい場合などは困る。
確か、Xファイル拡張可能だったはずだし。

で、とりあえずコンバーターとして、Metasequoia + MikotoLightwave用のものを用意したいところ。
Mikotoからアニメ付きのXファイルを出力するツールはあるようなので、Mikoto用としてはそれが使えるかもしれない。
Metasequoiaでモデリング、Mikotoでボーンのアニメーション、で、シーン周りはどうしよう?
Mikotoである程度出来るようだけど・・・
それは追々考えよう。

スクリプトからシーンの構築が出来るようにして、そのシーンを書き出せるようにしたい。
そうすれば、ある程度シーンをプログラムで作ることが出来るようになるはず。
スクリプトとのIOがあれば、シーンを作るツールも比較的簡単に出来るような出来ないような。
まあ、もう少し検討が必要だな。

投稿者 Takenori : 16:10 | トラックバック

2005年02月24日

またまたMayaを調べる

LAMPがMayaをサポートしているので少し調べてみた。
まず、LAMPのMayaプラグインをビルドするには、OpenMaya API/SDKなるものが必要。
OpenMaya API/SDKはMayaに付属。
Maya PLE版には付属しない。
ってことなので、Mayaプラグイン ビルドできません。
現時点ではバイナリの配布はされていないっぽいので、Mayaプラグインを試すことは出来なかった。
後、Maya PLE版では出力系のプラグインなどは制限されており使えない。
また、FBX SDKも前回書いた通り有料。
Mayaは厳しいっすなぁ。

投稿者 Takenori : 00:57 | トラックバック

dotXSIに惹かれる

SOFTIMAGEのdotXSIについても調べた。
登録すれば、SDK ( FTK ) をダウンロードできて、ドキュメントも日本語化されている。
dotXSI Viewerやオープンソースのライブラリなどもある。
コンバーターツールとして、オープンソースの3ds max用のプラグイン、無料のMaya用プラグインやFBXコンバーターもある。
オープンソースのdotXSICTK 以外は、ライセンスドキュメントが付属していないのが少し気がかりだけど、大丈夫かな?
まあ、いざとなればフォーマットは公開されているので、なんとでもなる。
にしても、FTKのライセンスドキュメントが見当たらないのは・・・
英語サイトを読むとなんとなくフリーっぽいが。

ま、dotXSIをメインにしよう。
ドキュメントなども整備されているし。

投稿者 Takenori : 01:05 | トラックバック

2005年03月03日

FTKのDeveloper's Guidを見るが

FTKのDeveloper's Guidを少し読んでみた。

FTKは、IOレイヤとセマンティックレイヤで構成されており、IOレイヤはdotXSIファイルのパーサーでXMLのパーサーなどのように単純にデータを読むだけのレイヤで、セマンティックレイヤはIOレイヤ上に構築されデータの意味を解釈するレイヤと言う事らしい。
そして、セマンティックレイヤを利用すれば、マテリアルやテクスチャなどのデータを簡単に取得できると言うことになっているらしい。

dotXSI にはバージョンがある。
V1.0,2.0,3.0,3.5,3.6というのが大きな分類で、3.0が一番汎用的っぽいのだが、これはいやーな感じだ。
まあ、パラメタはどんどん増えていくのでバージョンもどんどん新しいなっていくのは仕方ないと思うが・・・
とりあえずは、3.0を使うということにしておこう。
一番対応範囲が広いようだし。

で、dotXSIファイルの読み込みを行うべく、API部分を見てみるが、セマンティクレイヤの説明がほとんどない。
クラスライブラリのようだが、その一覧と各メソッドの説明はない。
仕方ないのでヘッダーと例を見ながら書いていくことにした。
Grepとか使ってヘッダーを追い、テンプレートリファレンスを見ればドキュメントがなくても比較的すんなり書けそうだ。
とりあえず、マテリアル部分を書いてみたがそんなに難しくはなかった。
まだビルドはしていないけど、何とかなりそうだ。
ただ、値の意味などで時々はまるとは思うが。

投稿者 Takenori : 03:29 | トラックバック

2005年03月04日

dotXSIの読み込み

dotXSIの読み込みにFTKを使うことはいいが、アーカイバからの読み込みも大丈夫なんだろうか?
ゲームで読み込みを行う場合は独自実装も考えた方が良さそう。
flex + bisonで作るか。
bisonで汎用的に書くか、型名など固定で書くかはどうしよう?
汎用的な用途のためにFTKがあるので、思いっきり固定で書いてしまっても良いかもしれないな。

とりあえずは、FTKで読み込み部を作って、後々flex+bisonで実装しよう。

投稿者 Takenori : 01:58 | トラックバック

SDLとか予定とか

使わない気がするけどとりあえずメモ。
SDL

今のところDirectXを使う関係で環境依存しまくりなので、マルチプラットホームとかは全然考えてない。
グラフィック周りはLAMPをベースに使用と思っているが、他は検討中。
スクリプトは積むとしたらPythonの予定。
サウンドのファイルフォーマットはOgg Vorbisの予定。ライブラリは未定。

スクリプトについて少しメモ
シーンセットアップ
シナリオの進行
3D オブジェクトの振る舞いの拡張。
がスクリプトで出来ればいいかな?
その内もう少し検討してまとめていこう。

投稿者 Takenori : 02:08 | トラックバック

2005年03月07日

視点と操作方法

LAMPのチュートリアルとして付いているソースでは、斜め上から見下ろし、矢印キーでの移動は押した方向に進むというものになっている。
これを、上矢印キーで進み、左右矢印キーで方向をかえる操作系に変更した。
左右矢印キーが押されたら、角度を増減する。
上矢印キーが押されたら、ベクトルの方向を角度で変更したものを現在位置に加算する。
で、この上矢印キーでの移動だが、次のような仮想ソースコードのようにしてやりたかったのだが、出来なかった。
Matrix44.rotationY(angle);
Vector3 *= Matrix44;
Vector3& operator*= (const Matrix44 &rhs)がVector3に実装されていなかったのだ。
いろいろと調べるがやり方がよくわからない。
仕方がないので、D3DXを使うことにした。
次のような感じだ。
D3DXMATRIX rotMat;
D3DXMatrixRotationY( &rotMat, rotAngle );
D3DXVECTOR3 tv( 0.0f,0.0f,moveSpeed);
D3DXVECTOR3 tvd;
D3DXVec3TransformCoord( &tvd, &tv, &rotMat );
これで移動量が取得できたので、後は現在位置に加算して移動完了。
とりあえず、操作方法は変更できた。
次は視点の変更。
キャラクターの斜め後ろから見るような視点にした。
これはCamera::setLookAtを使えば簡単に出来るはずということで、キャラクター位置を適当な高さとキャラクターの向きと逆方法(つまり後ろ方向)へ少し移動した位置をカメラ位置へ、注視点はキャラクター位置の真上でカメラより少し下、上方向ベクトルは普通に0.1.0を使い、設定したら難なく出来た。(向きなど少し間違ったり、微調整はしたが)

にしても、LAMPを使おうと思ったら結構ソースコードを読まないとダメっすなぁ。

投稿者 Takenori : 23:57 | トラックバック

2005年03月08日

マップデータを差し替える

以前Xファイルとして作ってもらったマップデータをLAMPについているコンバーターで変換して、LAMPで読めるようにした。
シーンビューアーで見てみると、問題なく読み込めている様子。
で、これをチュートリアルのやつに読み込ませようとするが、よくわからない。
とりあえず、フレームワークのloadSceneを参考にして、新しいシーンへ読み込ませ、SceneNodeをもともとあるシーンにつなげてみるが表示されず。
いろいろと調べるがよくわからない。
で、demoのソースを追ってみることにした。
すると、シーンをシーンノードに読み込ませ、そのシーンノードをもともとあるシーンへつなげているようだ。ああそうか、シーングラフだった。
ソースコードは次のような感じ。

SceneNode *scnNode = scene_->getSceneNodeManager()->createSceneNode("floor");
scene_->getRootNode()->addSceneNode(scnNode);
TextSceneLoader* loader = new TextSceneLoader();
loader->load("Yuka_m01_FIX.tsn", scene_, scnNode);
delete loader;

これで、scene_にYuka_m01_FIXが追加される。
で、もともとあった床のノードだけを次のようにして削除。

SceneNode *yuka;
yuka = scene_->getSceneNodeManager()->search("Yuka");
scene_->getRootNode()->removeSceneNode( yuka );

が、初めYuka_m01_FIXの中にも"Yuka"と言うモデルとメッシュがあり、なぜか読み込めず悩んだ。
シーンノードは削除しているはずなのに・・・
LAMPは致命的エラーで落ちるだけと言う不親切さ。
結局、Yuka_m01_FIXの中の"Yuka"をリネームしたらうまく読み込めた。
どうやら名前が競合していたようだ。
それぐらいわかるように停止してくれよ・・・
たぶん、シーンノードを削除してもメッシュデータなどは残るので、それらの名前が競合していたのだろう。

これで、床の入れ替えに成功した。
でも、作ってもらった床は凹凸があるので、めり込みまくり。
次は当たりだなぁ。
なんか、これも専用フォーマットあるっぽいけど・・・
Maya以外からLAMPを使おうとしたら大変だなぁ。
まあ、Mayaがあってもいろいろと大変な気はかなりするけど。
ソースをかなり読まないといけないし。

投稿者 Takenori : 07:54 | トラックバック

2005年03月09日

当たり辛そう

*.tclとか言うファイルがコリジョン(当たり/衝突)ようのファイルみたい。
で、中を見てみると、メッシュと大差ないので、これは何とかなりそう。
そして、使い方だけど・・・よくわからない。
軽くdemoのソースコードを見てみたのだが、よくわからん。
setCollisionMask(1);って何かなぁ? とdoxygenのドキュメントを見るのだが、
virtual void Lamp::CollisionLeaf::setCollisionMask ( u_int collisionMask )
setCollisionMask : コリジョンマスクの設定
collisionMask : コリジョンマスク
って書いてあるだけ。そして、ソースコードを見るとcollisionMask_へ代入しているだけなので、collisionMask_を見ると、
// コリジョンマスク
u_int collisionMask_;
・・・ そんなのコメント見なくたってわかるって。
ハァ・・・ かなりコードを追っかけないとダメそうだな。

あー、やっとなくとなくわかった。
demoのPrismaticUmbrellaのAnzuState.cppのvoid AnzuState::landCollide() で判定して、位置補正している。
関係ないところばっかり見ていた。
なんか、計算しかしていないなぁ・・・と。
collisionMask は、それによって当たる物と当たらない物を識別するために使っている様子。
次は勘でコード書いてみるか。

コードを見たらわかるコメントと言うか、変数名を和訳しただけとか言うコメントは書かない方がいいな。そんなの見なくてもわかる。
それが、どのように使われるかか、どのような物を入れたら良いかを書いたほうが良い。
ところで、自分のは・・・ ああ、まだマシだ。少し説明してある。
メソッドの説明はそのままのもあるけど、ややこしいのは少し補足説明があって、変数も少し説明がある。
今後はもっと気をつけよう。
後、サンプルコードも大切だな。どのように使うかがわからないと使えない。
適切な規模で使い方を表したサンプルコードも書くようにしないと。

投稿者 Takenori : 23:43 | トラックバック

2005年03月11日

コリジョンファイル

とりあえず、1個だけなので手作業で変換できるかなとテキストのコリジョンファイルを見てみると・・・ メッシュがインデックス形式じゃない!
で、シーンファイルのメッシュはインデックス形式。
困った。手作業で変換するのは現実的じゃない。
そこで、Meshとして読み込まれたデータを変換しようとLAMPのコリジョン部分のコードを追ってみようとしたら、CollisionConverter とかいうクラスがある。
これは! メソッドのconvertではSceneとCollisionSceneが引数に渡されている。
constが付いていないので、どちらからどちらへ変換するのかわからないが、これで変換できそう。
とにかくやってみることに。

シーンを読み込み、コンバーターでコリジョンシーンへ変換し、コリジョンセーバーでファイルに保存。
ビルドして実行してみるとうまくいった。
ファイルの中身もそれっぽい。

ソースコードは次の通り。

Scene *map = LampGraphics::createScene("Map");
TextSceneLoader* loader = new TextSceneLoader();
loader->load("sceneFile.tsn", map);
delete loader;
CollisionScene *mapCollisionScene = new CollisionScene();

CollisionConverter *converter = new CollisionConverter();
converter->convert( map, mapCollisionScene );
delete converter;

TextCollisionSaver *saver = new TextCollisionSaver();
saver->save("sceneFile.tcl", mapCollisionScene );
delete saver;

delete mapCollisionScene;
map->clear();
LampGraphics::destroyScene(map);

後始末の部分は少し違うかも。
ツールを作る場合はもう少しキチンと調べた方が良さそう。
後、わざわざnew する必要があるのかどうかはよくわからないが、demoなどではそのようにしていることが多いのでそれに従った。

でも、テキストコリジョンファイルの拡張子のtclって・・・ TCLスクリプトのファイルに見えてしまう。
次はdemoのソースを参考にして当たりを書いてみるか。

投稿者 Takenori : 06:29 | トラックバック

当たりを入れられた

demoのソースを見つつコーディング。
なぜか交差されていなかったりしてよくわからないので本体のコードを追う。
traverse()は両方のノードに対して行わないといけないんすな。
後、当たり前だけど下に下がるようにしないと、坂を上ったらずっとそのままの高さにいて空中を歩いてしまう。
で、なんとか当たりを使えた。
坂を下ったり上ったり出来るし、急な坂は上れない。
この辺りはキャラクターに設定する当たりの球の半径で調整するのだろう。

次はWidgetを作ろう。
吉里吉里の方でも使えるようにある程度汎用的にしたいところ。
DX9では、サーフェイスの画像データへのポインタ取得、矩形塗りつぶしぐらいしか出来ないので、大体吉里吉里と一緒。
まあ、メッシュを作ってしまうと言う手もあるが。
でも、両方で使えるように矩形塗りつぶしと画像データを直接扱うぐらいにして、その上に線描画などを構築して描画部分は作ることにする。
と言っても、描画部分と管理部分は独立するだろうからそれほど効果ないかも。
Compositeパターンを基本として設計するか。

投稿者 Takenori : 08:54 | トラックバック

dotXSI周り

前に書いたかもしれないが、dotXSIをメインフォーマットにしようと考えている。
そして、他のツールとはdotXSIを介してやりとりしたいと思っている。
そしたら当然のことながら変換の問題が出てくると考えられる。
完全に問題なくやり取りすることは難しいかもしれないが、このシステム用に必要なデータをdotXSI内に入れると同時に、オリジナルデータほぼそのままのデータも内包するようにすると良いかもしれない。
そうすれば、もとのツールでの編集は問題なくサポートされることとなる。
でも、待てよ、複数のツールでいじった場合汎用の共通部分は常に更新されることとなるが、各ツールに依存する部分は更新されないので先祖返り発生しまくりじゃ・・・
共通部分を基に独自部分を読み込み時自動的に更新する仕組みが必要に・・・って、それなら独自部分は必要ないんじゃ・・・
なら差分を保存するのがいいかな。
差分部分の相互変換(共通パラメータ)を考えるとツール調べまくらないといけなくなるので、その辺りは気にしないことにして。
将来的にその部分は徐々に埋められていくことを期待するけど。
なんかいろいろと考えていくと専用フォーマットでいいんじゃないかって気がしてきたなぁ。
どうするかなぁ。
とにかくゲームで必要な部分のみ受け渡しできれば良いとも言えるが・・・
この辺りはもう少し検討した方が良いな。

投稿者 Takenori : 10:35 | トラックバック

2005年03月12日

GUI部クラス図

各クラスの関連のみを表したクラス図を作成。
widget.png

こんな感じかな。
メソッドなどを追加しつつ、さらに練る必要があるけど。

まずは最低限必要だと思われる物しか入れていない。
EditBoxなども欲しいけど、初めはいらないかな。
とりあえず、これだけあればだいたい何とかなるはず。
後は必要になった時に追加していくことにする。
基本のデザインさえしっかりしていれば、追加も楽なはずだし。

投稿者 Takenori : 11:35 | トラックバック

Xファイルコンバーター拡張

コーディングしたくなってきたので、Xファイルのコンバーターを拡張することにした。
LAMPについているものでは、剛体しか変換できない。
せめて、ボーンを持ったモデルとアニメーションぐらいは変換できて欲しい。
そうすれば、他のツールからの読み込みも何とかなるはず。

DXのSkinnedMesh サンプルとLAMPのXファイルコンバーター、LAMPのシーン読み込み部のソース、テキストシーンファイル、Xファイルを参考に書いていくことに。

SkinnedMesh では、描画を行うために読み込み時に描画に必要なデータへの変換なども行っている。
なので、この辺りは省かないと。(残してもいいけど、やはりソースは少ない方が見通しがいい)

DXの場合、ボーンの位置はマトリックスで持っているが、LAMPは回転、拡縮、位置で持っている。
確か、マトリックスを分解する関数がD3DXにあったはずと調べる。
D3DXMatrixDecompose だ。
でも、回転はクォータニオンで得られる。
クォータニオンからオイラー角に変換する関数は・・・ ない!?
どうしよう。
LightWaveのシーンやオブジェクトを読み込むライブラリの中に変換する関数があったような・・・ あれ? LAMPにあったかも。
Quaternion::getRotationXYZ だ。
良かった。
これは何とか変換できそうだ。

LAMPのボーンのInversePoseMatrixって何だろう?
例によってdoxygenドキュメントではポーズ逆行列と書いてあって当てにならない。
たぶん、ボーンのオフセットマトリックスの逆行列だろう。
ボーンのローカル座標系に変換するのに使う物だと考えられる。
そういうことにして進めることにする。

投稿者 Takenori : 11:47 | トラックバック

2005年03月13日

Xファイルからボーンリンクの読み込み

Xファイルではフレームと言う単位でデータが階層化されている。
ボーンの情報は ID3DXSkinInfo インターフェイスで得られる。
だが、ボーンのリンク構造をどのように得るのかわからず、フレームのツリー構造を利用していろいろとやって取得することが出来たが、この文書を書く前にID3DXSkinInfo とサンプルソースを確認してみたら、ConvertToBlendedMesh で得られる D3DXBONECOMBINATION 配列へのポインタを使えばリンクを得られるよう。
D3DXBONECOMBINATION にはBoneId 配列へのポインタがあるので、これを使えば・・・ あれ? 無理かな? 出来ないかも。
やっぱり、フレームのツリー構造を利用する方法でないとダメそう。
サンプルソースでは、フレームの結合済み行列へのポインタをポーンへ代入している。
つまり、まずはフレームの階層を走査して結合済み行列を作り、ボーンリストと同一属性(同時に描画できる)頂点リストを利用してトランスフォームするということか。
ボーンには結合済み行列へのポインタがあるので、ボーンリストとウェイトから行列をブレンド出来る。
なんだ、フレームのツリー構造を使う方法で良さそうだ。

まず、スキン情報の入った D3DXSKININFO を得る。
D3DXSKININFO のボーンリストからボーン名リストを作る。
ボーン名リストは、そのフレームがボーンかどうかを判定するのに利用する。
つまり、ボーン名リストに名前があればボーン、なければボーンでないと言うこと。
フレームを走査して、フレームにボーンかどうかのフラグをつけると同時に親へのポインタを保持する。 (ボーンフラグは別になくてもいいのか。毎回ボーン名リストから判断すれば。親も毎回走査することで得られるけど、それはちょっとしんどい。)
フレームを幅優先で走査して、親がボーンで自分もボーンのものを親の子供として追加する。
って、別に幅優先じゃなく深さ優先でも、親ボーンにaddBoneするのならいいのか。
Modelがボーンリスト持っていて、Modelからボーン検索して、見つかったボーンに子供を追加するだけだし。
わかりやすいようにファイルへ書き出して見てみるのに幅優先が必要だったからそうしたけど。
まあ、幅優先でいいか。スタックの心配が少ないし。

投稿者 Takenori : 07:05 | トラックバック

ゴールオブジェクトは残す?

Xファイルはゴールオブジェクトをそのまま残しているみたいだけど、LAMPの場合は削らないとダメっぽい。
LAMP自体に手を加えて保持しておくようにしても良いが・・・
IKなどを使わない限りゴールオブジェクトは必要ないので、とりあえず削ってしまうか。
とにかく先に進めよう。
ゴールオブジェクトは必要になった時に追加することにする。

投稿者 Takenori : 08:07 | コメント (3) | トラックバック

2005年03月21日

FBX SDK

ダウンロードしてImportSceneサンプルをビルドして、出力をテキストに出してみた。
すげーいっぱい情報がありますな。
実際に利用する情報はこの中の一部になるとは言うものの・・・
まあ、何とかなるか。

まずはFBXを読み込んで、LAMPを使い描画するViewerを作らないとなぁ。

投稿者 Takenori : 12:32 | トラックバック

2005年03月23日

FBX SDKのLIBはCOFF

FBX SDKをC++ Builderから使おうとLIBファイルをプロジェクトに加えてみるが、リンクエラー。
「LIBがOMFじゃなくて、COFFっぽいよ」と言われる。
COFFをOMFへ変換する物を探すとCOFF2OMFと言う物があったが、これはインポートライブラリのみを変換してくれるようだ。
つまり、今回のには使えない。
他にも探してみるが見つからない。
なんで、LIBしか提供していないんだ。
DLLもあれば何とかなる物を。
ラップするDLLを作ることでC++ Builderでも使えるだろうが、そんな面倒なことをするのならVCで作った方がマシだ。
ツリービューでFBXの中にある情報を表示する簡単なツールを作ってみようと思ったのだが、やめるか。
それとも、VCでwxWidgets を触ってみるかなぁ。

投稿者 Takenori : 15:08 | トラックバック

2005年03月24日

wxWidgetsの検討

FBXファイルの構造を表示するツールのUIにwxWidgetsを使おうと思い、少し触ってみた。
wxWidgetsのセットアップで、すでにライブラリは作ってあるので、ビルドは楽なはず。
まずはwxGladeを使って適当にコントロールを配置して、ソースを吐かせる。
次にサンプルのプロジェクトを参考にして、新たにプロジェクトを作る。
で、ビルド。
すんなり動いた。
次にサンプルのソースを見たり、wxGladeで少しいじったりしてみたが、C++ Builderのように開発途中にGUIをサクサク変えるには、ソースを直接触らないと難しそうだ。
wxGladeで、フォームに変更を加えてソースを吐かせ、そのソースと開発途中のソースをマージするような感じになるだろうか。
でも、さわり部分だけ見た感じでは比較的簡単に利用できそうだ。
サンプルも豊富なので、何とかなりそうかな。
とりあえずやってみるか。

投稿者 Takenori : 14:55 | トラックバック

wxGladeで変更しまくり可?

wxGladeが吐いたソースを見ると、
// begin wxGlade:
// end wxGlade
と言うようなマーカーとおぼしきコメントが入っている。
これは!?

ちょっと実験。
あれ消えた? と思ったが、Overwrite existing sourcesのチェックをはずしたら、消えなくなった。
つまり、マーカー外にコードを書くようにすれば、GUIを変更しまくってもいいってことか!
でも、ツリーコントロールのサンプルでは、wxTreeCtrlを継承してハンドラを実装しているみたいだけど、これは・・・ PropertiesのClassに継承したクラス名を書けばいいのかな?

投稿者 Takenori : 23:35 | トラックバック

2005年03月25日

イベントへ応答

wxWidgetsを使いメニューを追加して、イベントハンドラのテーブルを作り、メニューのフォイル 開くからファイルオープンダイアログを表示し、選択されたファイルのパスを取得してみた。

まずは次のようにしてイベントハンドラのテーブルを定義する。

#define MENU_LINK(name) EVT_MENU(FBXMenu_##name, MainFrame::On##name)

BEGIN_EVENT_TABLE(MainFrame, wxFrame)
  MENU_LINK(FileOpen)
END_EVENT_TABLE()

その際、忘れずにイベントを追加するクラスに DECLARE_EVENT_TABLE() を追加。
たぶん、Dispatchメソッドみたいなものなんだろう。
で、上のイベントテーブルはその実体だと思われる。
まあ、中身はどうだっていいんだけど。

ファイルオープンダイアログ部分は次の通り。

wxFileDialog *fileDialog = new wxFileDialog(this,wxT("ファイルを選択してください"),wxT(""),wxT(""),wxT("FBX files (*.fbx)|*.fbx"),wxOPEN);
if( fileDialog->ShowModal() == wxID_OK )
{
  wxString selectedFilePath( fileDialog->GetPath() );
  // ここでいい感じにファイルを開く
}
delete fileDialog;

いたって普通。
この普通に使えるって言うのはいいな。
ファイルオープンダイアログ程度であればHPのマニュアルを見ながらさくっと作れた。
wxWidgets いい感じだなぁ。
wxGlade と VCを立ち上げて、GUI編集をwxGladeでやって、コードをVCで編集すればC++Builderに近い使い勝手が実現するかも。
wxWidgets 用のカスタム ウィサードを作っておけば、プロジェクトの作成もお手軽になる。
まあ、もう少し触ってみないことにはわからないだろうけど、自分の中では期待大。

投稿者 Takenori : 00:27 | トラックバック

FBX SDKを追加してみる

wxWidget を使って作っているツールのプロジェクトへFBX SDK のサンプルを元にライブラリやインクルードディレクトリを追加。
が、リンクエラーでまくり。

とりあえず、次のように設定すれば、リンクが通るようになった。
ライブラリへAdvapi32.lib fbxsdk_md.lib zlib_md.lib を追加。
LIBCMT を無視。
デバッグオプションに K_PLUGIN;K_FBXSDK;K_NODLLを追加。

ライブラリは次の3種あるが、どれを使えばいいのかよくわからない。
fbxsdk_mt.lib zlib_mt.lib
fbxsdk_ml.lib zlib_ml.lib
fbxsdk_md.lib zlib_md.lib
サンプルでは、すべてfbxsdk_mt.lib zlib_mt.lib が使われているが、同じようにmtのを追加したらエラーでまくりだった。
なんとなく、mdにしたら通った。
mlにしても、エラーがでまくり。

リリース版もfbxsdk_mt.lib zlib_mt.libを使用。
LIBCMT ではなく、LIBC を無視するように変更。
が、次のようなリンクエラーが出る。
error LNK2001: 外部シンボル ""public: void __thiscall wxStringData::Free(void)" (?Free@wxStringData@@QAEXXZ)" は未解決です。
コードを見るとデバッグオプションから_MTをはずせば消せそうだが・・・
wxBase,wxUniv,wxWindowsのプロジェクトを確認すると_MTは入っていなかった。
そこで、_MTを入れてビルドし、ライブラリを作り直すが、やはり同様のエラーでビルドが通らない。
まあ、サンプルなどは普通に通るので、そういう問題ではなさそうだが。
コードの書き方の問題だろうか?
でも、デバッグだと通るのはなぞだ。
とりあえず、マルチスレッドではないので_MTをはずしておくことにした。
DLLだと_MTをつけても大丈夫なようなので、マルチスレッドにする時はdllを使うことにする。
としようとしたが、__HUGEが見つからないリンクエラーが消えない。
で、デバッグ版との違いを調べていたら、リンクするランタイムライブリがデバッグ版ではマルチスレッドデバッグ DLLになっていた。
リリース版はシングルスレッド。
そこで、リリース版もマルチスレッド DLLへ変更。
無視するライブラリをLIBCMTにしたらビルドが通った。

wxWidget の方はなんとなくわかったが、FBX SDKのm?の違いはなぞ。
ビルドの設定の違いだとは思うが・・・

投稿者 Takenori : 22:25 | トラックバック

2005年04月11日

FBXInfoViewer

とりあえず出来た。
サンプルにあったFBXファイルをテキストで表示するプログラムのGUI版みたいなものだけど、ツリービューで見る事が出来るので、少し見やすいかも。
でも、開くファイルによっては、表示までにかなり時間がかかるのと、メモリ使用量もかなり激しい。
まあ、テキスト化した時と同じぐらいのサイズなので、当然と言えば当然。

投稿者 Takenori : 00:20 | トラックバック

2005年04月18日

頂点情報数

FBX SDKを使ってツールを作り、なんとなくわかったので、少し前にやっていたXファイルの読み込みの続きをやることにした。
FBX ファイルの読み込みは内部的にFBX>Xファイル>LAMPと言った変換方法をとることを検討している。(一部データは直接LAMPへ変換する必要があるかも)
FBXからXファイルへの変換があれば、他でも使えて汎用性が高まりそうな気がするし。

久しぶりなので、ブログを読み返し、ソースコードを漁ってやっていたことを思い出す。
ボーンとボーンリンクの変換まで出来ているようなので、各頂点に対応するボーンインデックスを探すのとウェイトを設定する部分を作りつつソースを追っていたら、そこはもう作っていた。
ありゃ?
各頂点ごとのボーンインデックスとウェイトが収められたリストが出来てる。
いつの間に作ったんだ俺?
と思ったら思い出してきた。
なぜか正確な頂点数が得られないと悩んでいた記憶が・・・
ソースを見るとID3DXMesh::GetNumVertices で頂点数を得ているようだけど、なんで正確な頂点数が得られないと悩んでいたんだっけ?
中間データを吐き出したテキストを見ると、ボーンに関連付けられていない頂点があるので、それで正確な頂点数じゃないと思った・・・
あーっ、頂点数じゃなくて、頂点インデックス数を得ないといけないと思っていたんだ。
いや、違う、頂点数と頂点インデックス数は同じになる。頂点情報数を得たいと思っていたんだった。
ID3DXSkinInfo::GetBoneInfluence で得られるボーンの影響を受ける頂点の配列は、頂点インデックスの配列のハズ。
頂点情報数よりも、頂点数は常に大きくなるはずなので、問題ないといえば問題ないけど、やっぱりすっきりしない。ってことで悩んでいた。
そのことはすっかり忘れていたので、各頂点ごとのボーンインデックスとウェイトをLAMPのメッシュデータへ設定する部分を先に作った。
悩んでいたことはブログを書いていて思い出した。

頂点情報数は、ID3DXMesh::GetAttributeTableでD3DXATTRIBUTERANGE 構造体 を得て、その中のVertexCount を参照すればいいみたい。
DXヘルプでは、頂点情報数と頂点数は両方、頂点の数と書かれているが、たぶんD3DXATTRIBUTERANGE のVertexCount は頂点情報数をさしているはず。
まあ、とにかくやってみることにする。
やってみたら、勘違いしていたようだ。
詳細は、ここに書いた。

頂点数関連の言葉の定義
ここで言っている頂点情報数とは、各頂点の座標などを収めた情報の数。
頂点数は実際に存在する頂点の数。
隣接するポリゴンは頂点を共有するので、頂点数は頂点情報数よりも多くなる。
そこで、各頂点は頂点情報へのインデックスを持ち、情報の重複をなくす。
このインデックスが頂点インデックスで、当然頂点数と同じになる。
で、その数を頂点インデックス数とした。

投稿者 Takenori : 03:42 | トラックバック

頂点インデックス数

D3DXATTRIBUTERANGE のVertexCount はやっぱり、頂点数だった。
もしかして勘違いしている?
頂点数は頂点情報数で、頂点インデックス数は別にある?
頂点インデックス数は、D3DXATTRIBUTERANGE::FaceCountを3倍するか、IDirect3DIndexBuffer9 ::GetDescで頂点インデックスフォーマットを調べて、全サイズを1インデックスのサイズで割れば出る。
実際やると、両者は同じ値になったので、これが頂点インデックス数のようだ。
そして、D3DXATTRIBUTERANGE::VertexCount とID3DXMesh::GetNumVertices は一致したので、これが頂点情報数のようだ。
なんだ、やっぱりあっていたのか。
と言うことは、ボーンの影響を受けない頂点が入っていると言うことなのか?

投稿者 Takenori : 04:43 | トラックバック

2005年06月06日

FBXInfoViewerが使われているみたい

textファイルじゃ見づらいので、なんとなく作ったツールだけど、使われているみたい。
せっかく作ったのに、最近こっち関係のコードいじってなかったので、FBXInfoViewerを全然使ってなかった。
でも、使われていて良かった。

こちらサイトにトラックバックしていただいていた。
モデルとスケルトンの階層も欲しいとか。
だいぶ前なので、少し記憶が薄れていたり。
ソースコードを見返すとHierarchyは、全ノードを階層につないでいた。
モデルやスケルトンで分けていなかった。
でも、モデルやスケルトンのみの階層をつけるとなるとAttributeがないノードによって階層がつながれている場合、困るな。
Hierarchyの各ノードにモデルやスケルトンなどのAttribute 名を付与する方が良いかも。と言うか、そうしないと厳しそう。

投稿者 Takenori : 22:47 | コメント (2) | トラックバック

FBXInfoViewer V.1.1.0を公開

FBX Info ViewerにHierarchyの各ノードにモデルやスケルトンなどのAttribute 名を付与した。
これで、幾分見やすくなった。

投稿者 Takenori : 23:21 | トラックバック

2005年07月09日

TJSをVC++でコンパイル

掲示板の書き込みに触発されて、TJSのVC++でのコンパイルを試してみることに。
とりあえず、吉里吉里 2.25 beta 5からTJSの部分のみコピーして、使い方のサンプルだけのソースを追加してビルドしてみることに。
デバッグオプションに__WIN32__を追加して、ワイド文字列の結合に悩む。
コメントを見るとBCC用のパッチ的な記述になっているようだが、VCでは通らない。
いろいろやるが出来ない。
使っているところを見ると、特になくても問題なさそうだが… 後他にもいろいろと修正を加えないといけなさそうなので面倒になって、掲示板に添付してあったソースをビルドしてみることに。
そしたら、SDLのヘッダーのいくつかが必要なようなので、SDLをダウンロードしてヘッダーをコピー。
ビルドが通る。
で、問題のコメントアウトしているというところを見て、コメントアウトをはずす。
よくわからないエラーが出る。
変換したい型が何なのかよくわからないので、STLのソースを追う。
ググる。
そしたら関係ないけど、boostのインストール方法を間違ってたのに気付く。
過去のboostのVC.NET 2003へのインストールを修正し、インストールしなおす。
でも、関係なし。
引数が1つの時はstd::mem_funではなく、std::mem_fun1じゃなかったかなぁと、std::mem_fun1に書き換えてみる。
エラーが変わって変換できない型が表示された。
関係ないところを省くと、どうやら__cdeclを__thiscallに変換できません。と言っているようだ。
__thiscallとstd::mem_funで調べてみるが、特に問題はない様子。
よくわからない。
メンバ関数ポインタに使われているメンバ関数に__cdeclを追加してみるが、エラーは変わらず。
ソースコードをよく見てみるとTJS_cdeclが付いている。
TJS_cdeclは、__declと定義されている。
これか!とTJS_cdeclを削除。
std::mem_fun1のエラーは解決したが、std::bind1stのエラーが出た。
あらら。
ちなみに、std::mem_funは引数の数を自動的に決めてくれるみたいで、std::mem_fun1じゃなくてもいい様子。
たぶん、std::mem_fun1の方が階層が浅いので、エラーメッセージがわかりやすい物だったのだろう。

std::bind1stのエラーは、『コンパイラ エラー C2535 'identifier' : メンバ関数は、既に定義または宣言されています。』。
このエラーは見たことがある気がする。
確かテンプレートを使っていた時だったような…
ヘルプを見るけどよくわからない。
grepしてみると、標準のSTLとboostの中で同じ物が見つかる。
競合しているのではないかと思ったが、そうではないような気がする。
一体なんだろう?

投稿者 Takenori : 22:03 | トラックバック

2005年09月24日

LAMPのライセンス

LAMPのライセンスはLGPLと言うことを思い出した。
動的リンクすれば、ほとんどライセンスについて気にしなくていいが、ライブラリの性質上動的リンクは難しい。
つまり、LAMPを使って作ったらLGPLかGPLになる。
LGPLでもいいけど、一から作った方がいいかも。
STLやboost, D3DXを使えばそんなにしんどい作業ではなさそうだし。
だいぶ前にやっていた、Xから独自形式への変換を行う方が面倒だし。
何よりドキュメントがほとんどないのが辛い。
ってことで、一から作ろうと再考中。

メモ:
LGPL日本語訳

投稿者 Takenori : 19:00 | トラックバック

D3DXのアニメーション

D3DXを使えばボーンのアニメーションは簡単に出来る。
サンプルもついているのでわかりやすい。
でも、カメラなどのアニメーションはどうやるのかよくわからない。
ってことでMultiAnimationサンプルとヘルプをひたすら追った。
サンプルではメッシュ内にアニメーションが定義されており、ファイルを読み込んだら勝手にアニメーションコントローラーがボーンと関連付けされ、アニメーションコントローラーの時間を進めれば自動的にボーンのマトリックスが更新されているっぽい。
初め、どこで誰がどうやって動かしているのかなぞだったが、ソースを見る限りはそのようになっているように思う。
つまり、D3DXのアニメーション機能はxファイルから読み込んだメッシュにのみ使えるのかとも思ったが、インターフェイスを見る限りアニメーションのキーを登録できたりしている。
カメラのアニメーションは独自実装にするかなと思ったが、さらにいろいろと調べるとID3DXAnimationController::RegisterAnimationOutput というメソッドを発見。
このメソッドによってアニメーションの出力を設定するようになっているようだ。
D3DXLoadMeshHierarchyFromX を使って読み込んだ場合はすべて自動的に登録されるとある。
つまり、こいつでカメラの回転と移動を設定してやれば、D3DXのアニメーションコントローラーが使えそるようだ。

とりあえず、使えそうなことはわかったが、そのためのデータをどうやって作るのかが良くわからない。
D3DXCreateKeyframedAnimationSet でキー フレーム アニメーション セット を作り、ID3DXKeyframedAnimationSet::RegisterAnimationSRTKeys で各キーフレームのスケーリングや回転などの設定が出来、ID3DXAnimationController::RegisterAnimationSetでそのアニメーションセットを登録してやれば、アニメーションコントローラーで操作できそうなことはわかる。
が、各キーの時間はどこで設定する?
D3DXCreateKeyframedAnimationSet の引数TicksPerSecondで1 秒間に経過するキー フレーム ティックの数を設定できることはわかる。
が、ティック値はどこで設定するのだ?
と思いながらヘルプを見ていたら、ID3DXAnimationController::RegisterAnimationSetの引数で指定するスケーリング値の配列がD3DXKEY_VECTOR3とかってなってた。
で、これは
typedef struct _D3DXKEY_VECTOR3 {
FLOAT Time;
D3DXVECTOR3 Value;
} D3DXKEY_VECTOR3, *LPD3DXKEY_VECTOR3;
と定義されている。
なんだ、そう言う事か。

これでアニメーション関連で疑問だったことが解決した。
独自で作ってもたいした事ないが、やっぱりD3DXを使っておいた方が何かといいだろう。(独自の方が良いことも多いけど……)

マテリアル値やライトのアニメーションをさせたい時は独自にするか、Vector3などで代用すればいいかな。
ま、かなり先だろうし初めは実装しないだろう。

投稿者 Takenori : 19:38 | トラックバック

2005年09月25日

Xファイル読み込みメモ

アニメーション付きでないxファイルをD3DXLoadMeshHierarchyFromXで読み込んだ場合、S_OKが返ってくるが、ppAnimControllerはNULLになるみたい。
D3DXLoadMeshHierarchyFromXのppAnimControllerがNULLかどうかでアニメーション付きかどうか見て、NULLならD3DXLoadMeshFromX で読み込むようにすれば良さそう。

投稿者 Takenori : 00:25 | トラックバック

2005年11月08日

構成を考えていて

LAMPはやめて、独自の3Dライブラリにする。
wxWidgetsとTJSを使う。
と言うことを考えていてふと思う。

吉里吉里3のレンダリングエンジンだけを差し替えられれば、他は共通化(流用)して楽に作れるんじゃないか?
DirectXを使うので思いっきりWindowsに依存するけど。
まあ、流用出来そうなら流用して、出来なさそうなら自前で実装しよう。

投稿者 Takenori : 18:35 | トラックバック

メニューを動的に追加/削除する

メニューを動的に追加するためにwxWidgets 2.6.2について少し調べる。

イベントテーブルは単なる配列。
イベントテーブルへエントリーを追加するメソッド(wxEventHashTable::AddEntry)は用意されているが、特定のエントリーのみを削除するものは用意されていない。
wxEventHashTableはクラス属性としてsm_firstを持っており、wxEventHashTableがインスタンス化された時に、sm_firstへつながっていく。
削除される時は、sm_firstからリンクが解除される。
より後に生成されたものが先につながるようになっている。

wxEventHashTableを継承したメニュークラスを作り、メニューが追加される時にイベントテーブルにエントリーを追加していけば良さそう。
メニュークラスが削除されればwxEventHashTableがなくなり、リンクから外れてイベントが来なくなる。

こんな感じでいけるかな。

投稿者 Takenori : 18:36 | トラックバック

シーングラフについて調べる

Java3DSSGLAMPについて構造を調べた。

Java3Dはかなり汎用的に作られている。
Java3Dからかなり機能を削って、SSGとLAMPの良さそうな部分を取り込んで作ろう。
先月末ごろに頼んだ3D Game Engine Designは明日届くよう。
届いたらこれも参考にしよう。

でも、もう暫定的なものを作りかけていたりする。
とりあえず、3Dオブジェクトを適当に配置して町を作るツールと、その町の中でカメラアニメーションが作れるツールを作り、出来た町とアニメーションが再生できることを目標にする。
ここまで出来れば、背景を3Dにしたものが出来る。

投稿者 Takenori : 18:56 | トラックバック

2005年11月12日

インクリメンタル

mixi Alertの改修を少しやる。
再設計してコードのほとんどを書き直しているけど、一気にやりすぎたせいでやる気が持続させ辛い。

で、飽きたので3Dのプログラムをいじってみる。
Xファイルを読み込んで絵が出るくらいまでは作っている。
ここから一気にシーングラフへ設計変更…… と思ったが思い留まる。
少しずつ変えていこう。
レンダリングを別スレッドにして、排他処理機構をつける。
1回レンダリングするごとにメッセージを投げて、メッセージを受けた別スレッドが全体に関係する処理をする。
よしよし。
次はXMLでXファイルの位置指定したものを作り、それを読み込む処理を作ろう。
と、その前に配置する建物をモデリングしてみるかな。

投稿者 Takenori : 00:08 | トラックバック

モデリングやめて配置データを

モデリングしようかと思ったけど面倒なので、友達に「適当なデータない?」と聞いたらないと言われたので、素材などでググってみるがWeb用のばかりヒットするので、面倒になりComicStudio 3Dデータコレクション Vol.5 住宅・ビルディングをAmazonで注文。
これで数日待てばデータはなんとかなる。

そこで配置情報をどのようなフォーマットにするか考える。
なんとなくXMLにしようと思っていたけど、別にXMLにする必要はないので、他のものを検討してみる。
よくある汎用的なものとしては次の3つだろうか。
EA IFF 85 ( WAVEファイルなどのRIFFファイルフォーマットも同じはず ) : 4文字の識別子+サイズ4byte+データで表されるもの。バイナリデータ。
テキスト形式のXファイルライクのフォーマット : 中括弧やカンマ、セミコロンでデータを表すもの。
XML : タグで属性や階層、データを表すもの。

アニメーションのデータやポリゴンデータなどをバカ正直にXMLで書いていったらすごくでかくなる。
XMLには汎用的なパーサーがいろいろある。
EA IFF 85はバイナリデータなので、そのままであれば一番サイズが小さくなるし、値もそのまま入っているので読込み速度が有利。
テキスト形式のXファイルはXMLよりは小さくなり、手打ちするのであれば記述量が少なくなる。Cのテーブルっぽいので見やすく感じる。

結局は、配置情報にどのような情報を含めるかによりそうだな。
配置情報に入れるのは、シーングラフの階層情報とアニメーションとの関連付け情報、モデルデータとの関連付け情報、位置情報ぐらい。
モデルデータはXファイルをそのまま使うし、ボーンアニメーションもXファイルにあるのでそれを使う。
他のアニメーションは…… Xファイルを拡張するかEA IFF 85かな。
Direct3DXのアニメーションをそのまま使うのであれば、Xファイルを拡張するのが楽かも。

よし、やっぱりXMLにしよう。
そうするのが楽そうだ。

投稿者 Takenori : 22:10 | トラックバック

2005年11月13日

XMLパーサーの選定

Radium software developmentのここTinyXMLexpatParsifalが比較されている。
だいぶ古い記事だけど、TinyXMLは遅いのか。
expatはかなり早いらしい。

実在するライブラリ云々の前に、SAXかDOMかと言う問題もある。
一般的に言われることとしては……
SAXは高速でメモリ使用量が少ない。
DOMはランダムアクセスが可能。
がある。
だが、それだけではアプリケーションの設計には不十分だと言う。
C++によるXML開発技法の第8章のC++DAXとC++DOMの比較などで、設計の指針について記述がある。

今回はどうだろう?
今回予定しているのは、シーングラフの構造そのものを書き出したものの読み書きだ。
XMLのツリー構造がそのままシーングラフに対応している。
ランダムアクセスや複数回のアクセスは必要とするが、それはシーングラフに対してだ。
ほとんどの処理は独自構造(シーングラフ)に対して行われる。
では、XMLの構造へは何度もアクセスしないかと言うとそうではない。
同じシーングラフを何度も読み込むだろう。
もし、これをキャッシュしておくならDOMを使い、最初の1度だけパースしてしまえば後のアクセスは早くなる。
しかし、シーングラフに複製機能を持たせるのなら、シーングラフ自体をキャッシュすることも可能だ。この場合、意味的な解析も済んでいるのでDOMよりも高速だろう。

どうやら今回はSAXを使う方が適していそうだ。

では、実際に使用するライブラリはどうする?
上述のRadium software developmentで、expatはかなり高速だが大きいのが難点だとある。
そこで、1.95.6のDLLのサイズを見てみると140KBだ。
XMLからの読込みのためだけに使うのには大きいかもしれない。
だが、wxWigets 2.6.2ではXMLの読込みにexpatを使っているようだ。
srcを除くとexpatの1.95.6が入っている。
それならサイズを気にすることはなさそうだ。
wxWigetsでリソースファイルを使ったりするのならどの道入ってくる。
また、wxWigetsにはwxXMLDocumentというクラスがある。
これはexpatのDOMラッパーのようだ。
つまり、これを使えばDOMが使える。
ただし、ソースには注意書きがあり、将来インターフェイスが変更されるかもしれないから、このクラスをアプリケーションで使うとwxWigetsの将来のバージョンではコンパイル出来なくなるかもしれないそうだ。
ま、expatを直接使うのでそれはどちらでもいい。(expatが使われなくなったらここに書いているサイズ云々は意味なくなるけど)

と言うことで、expat 1.95.6を使うことにした。

投稿者 Takenori : 20:27 | トラックバック

2005年11月14日

XMLからの読込み

expatをそのまま使うのは面倒なので、expatppのexpat v1.95.6を使っているものを使うことにした。
Betaとかついているけど、気にしない。
簡単なラッパーなので大丈夫だろう。

現状シーングラフには対応しておらず、Sceneに対してモデルをひたすら追加していくような構造になっている。
なので、作ったxmlもフラット。
読込み部もフラット。
で、とりあえず2体のトラを違う位置になるよう配置したXMLファイルを読み込んでみた。
トラが2体回ってる。
よしよし。

これでとりあえずはオブジェクトを適当な位置に置いたXMLファイルを読込んで表示できる。
配置は現在手打ちなので何とかしないと。
専用のツールを作るか、別のツールで作られたファイルを変換するか。
テストのために数個配置したいだけなら手打ちでも何とかなるが。
ま、その前にシーングラフのノードで必要なものだけを作ろう。
で、ノード自体にXML書き出し機能をつければツールを作るのも楽になる。

投稿者 Takenori : 00:13 | トラックバック

2005年11月15日

データコレクションのライセンス

先日注文したComicStudio 3Dデータコレクション Vol.5 住宅・ビルディングが届いたので、使用許諾を読んだ。
が、ロイヤリティーなどについてまったく書かれていない。
想定されている用法であるComicStudioで使用した場合のライセンスなどについても明記されていない。
少なくともデータコレクションをComicStudioで使用して、その漫画を販売したりする場合に発生するロイヤリティーなどについては書かれているべきだと思うのだが……
と言うことで、問い合わせ窓口へその辺りの事に付いての質問を送った。

投稿者 Takenori : 16:27 | トラックバック

2005年11月16日

グラフィック周りの処理

トランスフォーム以降の処理はDirect3Dに任せるので、それよりも前に必要な処理について整理。

・ユーザー入力やアニメーションによる移動、拡大縮小、回転
・移動と拡大縮小、回転の行列合成
・アニメーション時間を進める
・当たり判定とそれによる位置移動 (何度か繰り返す必要あり?)
・Zソート
・境界ボリュームの再計算
・カリング
すぐに思い付いたのはこれぐらい。
他にも気付いたら加筆していく。

ユーザー入力やアニメーションによる移動、拡大縮小、回転移動と拡大縮小、回転の行列合成
移動などと同時に行列を合成してしまっても良いが、わざと別々にした方が良いかもしれない。
別々にすれば、移動の反映を意図的に遅らせることも出来る。

アニメーション時間を進める
シーングラフを巡回して、アニメーションオブジェクトのみに対して処理していくか、アニメーションオブジェクトのリストを別に持ちそれに対して操作するか。
シーングラフにあるノードの数とアニメーションオブジェクトの比で効率が大きく変わりそう。
アニメーションオブジェクトの方が圧倒的に少なくなりそうなので、リストを別に持つようにしたほうが良いかもしれない。

当たり判定とそれによる位置移動
位置を移動させた時に他のものに当たったら、食い込んだ分逆に移動させる必要がある。
逆に移動させたら、また他のに当たることもある。
無限ループにならないようにある程度で打ち切る必要もある。
LAMPでは、当たり判定を持つオブジェクトのグラフを表示とは別にしていた。
当たりを持たないオブジェクトや当たりの必要のないシーンを考慮し、効率を考えてそのようになっているのだろうか?
同じにするか別にするか考える必要がある。

Zソート
Zバッファを使っていても、半透明のオブジェクトを表示する場合は奥のものから描画するように並べ替えないといけない。
また、Zバッファを使うのなら、出来るだけ前のものから描画していったほうが効率的。
単純に奥のものから処理できるように順にソートするか、境界ボリュームや半透明の有無などから賢くソートするか。
初めは、単に奥から順にで良さそう。

境界ボリュームの再計算
シーングラフはツリー状に構築され、ノードも境界ボリュームを持っている。
これはツリー上方の境界ボリュームで視錐台に含まれないと判定出来た場合に、その下につながっているノードの描画処理を行わなくて良いからだろう。
このようにする場合、下方のオブジェクトが移動したり、境界ボリュームが変更された場合、親となるノードの境界ボリュームの再計算が必要になる。

カリング
視錐台に含まれるかどうかの判定を行い、描画処理の量を減らす。
いきなり視錐台で判定するのではなく、カメラの前後判定などをやってから視錐台をやった方が効率的かもしれない。


順番や処理方法を考えないと。

投稿者 Takenori : 00:51 | トラックバック

マルチスレッドの話

少し前に書いたけど、レンダリングを別スレッドにした。
現在のソースは元々吉里吉里のプラグインとして書いていたもので、描画の更新はTJSから呼び出されていた。
が、これが重い重い。
なので、何とか描画の更新は別スレッドにしたかった。
また、フレームごとに呼び出すような形にしたかったと言うのもある。
レンダリング時にV-Blank待ちがあるので、そこのレスポンスの改善という意味もある。

今後は出来るだけマルチスレッド化していかなければならないと言う流れのようだ。
HTが積まれ、デュアルコアになって……
クロックがひたすら上昇して勝手に処理速度が速くなっていくと言うのは期待できない。
CEDEC2005 - デュアルコアプロセッサのためのマルチスレッド対応ゲームの開発事例に、3Dゲームエンジンのマルチスレッド化についていろいろと書かれている。


マルチスレッドは難しい。
リソースの競合とデッドロックと同期。
タイミングによる発生頻度の低い不具合に悩まされる。

リソースの競合はファイルへの書き込みを考えるとわかりやすい。
スレッド1はファイルへ1234と書き込み、スレッド2はABCDと書き込む。
もし、ファイルへの書き込みが排他処理されていなければ、書き込み途中にスレッドが切り替わり、12ABC34Dなどと書き込まれてしまうかもしれない。
スレッド1は1234と書き込まれていることを期待し、スレッド2はABCDと書き込まれていることを期待しているとしたら、このように書き込まれてしまっては困る。
このような問題は何らかのリソースを共有する場合に起こる。
ファイルに限らず、特定のメモリ領域もありえる。
マルチスレッドを使う場合は、出来る限りリソースを共有しないようにした方が、不具合の発生を減らし、効率的に動作するようになる。(常にと言うわけではないが)

デッドロックはリソースの競合を避けるためにセマフォやクリティカルセクションなどの排他処理を行う機構を使用した場合などで起こる。
グラフィックリソースとサウンドリソースがあり、スレッド1がグラフィックリソース、サウンドリソースの順で確保して、スレッド2がサウンドリソース、グラフィックリソースの順で確保していたら、デッドロックする可能性がある。
これは、スレッド1がグラフィックリソースを確保した後にスレッドが切り替わり、スレッド2がサウンドリソースを確保するとはまる。
この後、スレッド2はグラフィックリソースを確保しようとするが、既にスレッド1が確保しているので、確保できない。スレッドが切り替わり、スレッド1になってサウンドリソースを確保しようとしたら、スレッド2が既に確保しているので、確保できない。
お互い確保出来なくて処理が停まってしまう。
これを避けるためには、リソースの確保順が常に同じになるようにすればいい。

同期をとるためにイベントやメッセージを使っていてもデッドロックはよく起こる。
イベントを投げ合ってたりするとどこかで投げられない状態が発生し、そのイベントを待っているスレッドがずっと動けないままになることがある。

これらをシステマティックに排除できればいいのだが、シーケンス図や状態遷移図を描いてよく検討していても洩れることがある。

過去に書いたことがあるデザインは、mixi Alertのエントリにも書いたコマンドとキューを使う方法と1つのスレッドに他のスレッドを管理させる方法 ( サーバー&クライアント的な方法になる )。
これらは、最終的に1対1で考えられるので、考えやすい。
3つ以上のものが様々な状態を持って、相互に関連しているものを考えるのは難しい。
あれがこうなっている時に、これがこうなってて、残りがこうで…… というのを漏れなく考えていくのは難しい。

そんなこんなでマルチスレッドの設計を楽に出来ないかと考えていて、デザインパターンの本が出ていたのを思い出した。
Java言語で学ぶデザインパターン入門 マルチスレッド編と言うやつだ。

Javaなので買わなかったけど、他になさげだったので注文した。
レビューの評価は妙にいい。

投稿者 Takenori : 01:19 | トラックバック

2005年11月19日

ComicStudio 3D データコレクションのライセンス

以前問い合わせたと書いたComicStudio 3Dデータコレクション Vol.5 住宅・ビルディングの返事が着た。(問い合わせた翌日に届いていたが、少し予定が立てこんでいたので今書いてます)
結果は……

基本的にComicStudio 3Dデータコレクションシリーズに関しましては、個人様で使用される場合にはご使用可能です。
3Dデータコレクションを使用し、マンガ雑誌等に掲載されのは可能となります。
ただし、法人様等営利目的で2次利用は不可となっておりますので、どうぞご了承願います。

と言うことらしい。
個人は可で法人は不可?
元々はマンガを想定しているからこのような形なのだろうか?
不思議な気もするが、個人使用がOKならいいや。

投稿者 Takenori : 23:02 | トラックバック

2005年11月20日

オブジェクトの配置

テスト用のデータも手に入り、ライセンスも問題なさそうなので、テストのためにオブジェクトを配置したいわけだが手打ちは辛い。
数個のオブジェクトを適当に置くだけならいいけど、それなりに見栄えがするように置こうと思ったら何らかのツールが何らかのツールがないと辛いだろう。
だけど、わざわざ作るのもなぁと言うことでツールを考えてみる。

メジャーなのは次の4つだろうか?
Maya
3ds Max
SOFTIMAGE|XSI
LightWave 3D

フリーだとBlender (参考 : JP非公式HP窓の杜 ゼロからはじめる3D CG道場 ) かな。

価格的な理由や友達が使っていると言うこともあり、SOFTIMAGE|XSIの購入を考えるが……
何らかのツールを使う場合は、当然データ変換をする必要がある。
たぶん、その場合はFBXを使う。

うーん……
シーングラフで効率的に配置させたい場合や、独自のデータを持たせたい場合などは何らかのツールを作る必要があるし、フリーもしくは低価格なアプリケーションであった方が導入しやすいだろう。
よし、やっぱり作ろう。

投稿者 Takenori : 18:27 | トラックバック

2005年11月21日

配置ツールのGUIを作る

ツールはwxWidgetsで作ろうと思い、wxGladeでGUIを作った。
ある程度作ったところでXRCファイルを出力して、サンプルを真似てソースを書いてプロジェクトの設定で必要そうなところをコピー。
ビルドして実行。
出た出た。
GUIのデザインとソースコードがある程度分離されていていい感じだ。
ハンドラをひたすら書いていけば作れそうだ。

気を良くしてさくさく作っていたら、wxGladeが落ちた。
もう一度同じようにしたらまた落ちた。
どうやら再現性があるようだ。
そこで、XRCedを使ってみることにした。
が、wxGladeの方が使いやすいような。
慣れもあるだろうけど、wxGladeはダイアログのイメージを見ながらそこにWigetをぽこぽこ置いていくのに対して、XRCedはツリーに追加していく形。
Testで表示させながら追加していけば動的に追加されていくし、選択している場所に赤枠が出るのでそんなにわかりにくいと言うことはないが……
C++BuilderやVCのダイアログエディタなどのような感覚で追加できないのがどうももどかしい。
なんか、どっちもどっちだな。
ここにいろいろとあるが、商用のならもう少し使いやすいだろうか?
ま、とりあえずはwxGladeで行こう。
徐々にやばいケースがわかってくるだろう。

投稿者 Takenori : 01:18 | トラックバック

wxWidgetsで任意のイベントに応答する

スクロールや回転はメタセコイヤのように、ボタンを押しながらマウスを動かすスタイルにしようと思ったのだが、ボタンのイベントはクリックしかない。
EVT_LEFT_DOWNでイベントのハンドラを定義しても、ボタンの上では反応しない。
イベントテーブルでいろいろとやってみるが、どうやらイベントテーブルでは出来なさそうだ。
ソースを追ってみると、クリックにのみ反応するようになっている様子。
さて、どうしよう?

使用をやめることも検討したが、TreeViewなどのことを考えると、一からゴリゴリ書いていくのは辛い。
カスタムウィジェットか別ダイアログにして、そこの描画やイベントハンドラはすべて自分で処理するか。
別ダイアログにすると少し見栄えがなぁ。

カスタムウィジェットしかないかなと言う事で、wxWindowの説明を見てみる。
すると、PushEventHandlerと言うメソッドが!
これは、もしや独自のイベントハンドラを作って、ボタンに追加してやれば右ボタン押下イベントなどにも反応できるのでは?
さっそく、wxEvtHandlerを継承したクラスを作り、ProcessEventをオーバーライド。
wxEvent::GetEventTypeがwxEVT_LEFT_DOWNの時にtrueを返し、それ以外はfalseを返すように実装。
リソースを読み込んでフレームに設定した後、FindWindowByNameメソッドで特定のボタンを取得し、取得できたらPushEventHandlerで作ったハンドラを設定。
ビルドし実行してみると、wxEVT_LEFT_DOWNイベントを補足できた!
これでクリック以外のイベントにも応答出来そうだ。
後、PushEventHandlerをオーバーライドしなくても、wxEvtHandlerを継承したクラスにイベントテーブルを追加してやれば処理出来そうな気もする。
次はその辺りを調べよう。

投稿者 Takenori : 01:46 | トラックバック

2005年11月22日

シーンをいじるツール

見たい場所の操作には、ワールド座標系を操作するものとカメラを操作するものがある。
モデラが独立しているものはワールド座標系を操作し、統合系はカメラを操作するものが多いらしい。
カメラを動かすと、自分が動いているような感じなのに対して、ワールド座標系を動かすと、対象物が動いている感じになる。

机の上に模型が置いてあるとすると、自分が動きながら模型の配置をいじるのか、自分は止まったままで机を動かして見る位置を変え模型の配置をいじるのかと言ったところだろうか。
初めはトラを回していたのを引きずってワールド座標系を操作していた。
が、ふと気付いた。
シーンを操作するツールはカメラを操作するんじゃないか? と。
で、カメラを動かすようにしてみるが…… もうちょっと、こう、なんとかしたいって感じだった。

少し考えた後、両方出来るようにしてしまうことにした。
カメラが近づいている時にワールド座標系を回転させたりしたら、見づらいことになるかもしれないが、その辺りは慣れてくるだろう。

wxWigetsの方は、ボタンを押して動かした時の処理はすべて同じになるので、イベントハンドラテーブルを作る方が面倒な気がしたから、イベントハンドラテーブルはやめてまずは1個だけやりたい処理を書いた。
次は、前に作っていたDirect3Dのものと統合。
うまく動くかな。

投稿者 Takenori : 01:23 | トラックバック

2005年11月23日

Widgetへのアクセスをお手軽に

追記: コメントにも書きましたが、付属のwxrcを使って、
wxrc --extra-cpp-code --cpp-code frame.xrc
と言うようにするとヘッダーとソースコードが吐き出されます。
で、出力されたヘッダーに書かれているクラスを継承したものを使えばお手軽にアクセスできます。

このツールは最初に使ってみたものの、使い方が悪くバイナリが出力されて悩んでました。
で、以下の内容は無駄です。


XRCでリソースとソースコードが分離されて喜んでいたのだが、Widgetへのアクセスが面倒臭い。
wxWindow::FindWindowByName(wxT("WidgetName"), this);
ってな感じでWidgetを見付けてきて、それをキャストしてから使う。
リソースを変更して、WidgetNameがなくなったらFindWindowByNameではNULLが返ってくるので、それに対してメソッドを呼び出していたりしたらNULLアクセス例外などになってしまう。

記述の煩わしさに対してはXRCCTRLと言うマクロが準備されていて
XRCCTRL(dlg, "my_textctrl", wxTextCtrl)->SetValue(wxT("default value"));
とすれば、少し楽にアクセスできるようになっている。
が、wxTextCtrlなどとクラス名を指定したり、文字列を渡したりするのがどうも納得いかない。
XRCの方で名前もクラス名も指定済みなのに、また指定するのはいかがなものか。
また、文字列が散らばるのが嫌で、defineか、constメンバにした場合も、再度名前を定義しないといけない。
この辺りをどうにか解消できないかと考える。

求めているのはC++Builderのような使い勝手だ。
Widgetをフォームに置いたらメンバとして追加され、後はそのメンバにアクセスしてプロパティを設定したり、メソッドを読んだり出来る。
それぐらいのお手軽さが欲しい。

型名の問題も何とかしたいので、ソースコードとして何かを追加しなければならなそうだ。
メンバのようにアクセスしたいので、メンバに何かを追加するひつようもあるだろう。
で、そのメンバはポインタみたいなもの。
と言うことは、アロー演算子とキャスト演算子をオーバーロードし、型を扱うのでテンプレートを使い、Widgetを探すのに必要なIDを持つクラスがあれば事足りそうだ。
つまり、次のようなクラスがあればいい。

template <class T>
class GetWidgetPointer
{
    wxWindow *m_Owner;
    long m_ID;

    GetWidgetPointer();
    T *GetWidget() const
    {
        return static_cast<T*>( wxWindow::FindWindowById( m_ID, m_Owner ) );
    }
public:
    GetWidgetPointer( wxWindow *owner, long id ) : m_Owner(owner), m_ID(id) {}
    T *operator->() const { return GetWidget(); }
    operator T*() const { return GetWidget(); }
    long ID() { return m_ID; }
};

これを直接メンバに持ってもいいのだが、そうなるとまた名前を書くはめになる。
XRCからソースコードを作るツールを作った方が良さそうだ。
このツールが出力するソースコードは次のようなものになる。

class MyWidgets
{
    MyWidgets();
public:
    MyWidgets( wxWindow *owner ) :
        MyButton(owner,XRCID("MyButton")),
    {}
public:
    GetWidgetPointer<wxButton>    MyButton;
};

そして、このクラスを使う時は次のようにする。

#include "wx/frame.h"
#include "wx/wx.h"
#include "MyWidgets.h"
class MyFrame : public wxFrame
{
    MyWidgets    Widgets;
public:
    MyFrame( wxWindow* parent=(wxWindow *)NULL);
private:
    DECLARE_EVENT_TABLE()
};

// コンストラクタでオーナーのポインタを入れて初期化
MyFrame::MyFrame( wxWindow* parent)
: wxFrame(parent), Widgets(this)
{
// リソースファイルからwxFrameを作る処理
}

// 後は好きなところで
Widgets.MyButton->SetLabel(wxT("ボタン"));

上の例で、MyButtonはXRC内のボタンの名前。
型はXRC内で指定されている型になる。
Widgets.の部分がC++Builderにくらべて余計だが、まあ我慢できる範囲だろう。

XRCからこのようなソースコードを生成してくれるツールをここに置いた。
出力するクラス名は固定で、1つのリソースにしか対応していない。
メニューについても似たようなものが欲しくなると思うので、複数のフレームやダイアログに対応したものは、必要になった時に作ろうと思う。

実際にこのツールを使う場合は、出力されるソースコードに対してVCならカスタムビルドの設定を、makeを使うのなら依存関係をXRCに設定した方が良い。
そうすれば、XRCファイルを変更した時に自動的に再生成されるようになる。
Widgetの名前を変更したり、削除した場合に、そのWidgetへアクセスしているコードがあれば、コンパイルエラーになる。
なかなかいい感じではないだろうか。

投稿者 Takenori : 00:12 | コメント (2) | トラックバック

Direct3Dとくっつける

wxPanelを親として子ウィンドウを作り、そのウィンドウにDirect3Dの設定を行った。
それほど苦労せずにくっつけることが出来た。
画面イメージは次のような感じ。

画面イメージ

ウィンドウのサイズを変更しても、子ウィンドウの方へはイベントがこなかったので、wxPanelにカスタムイベントハンドラをくっつけ、wxEVT_SIZEイベントでDirect3Dの方のウィンドウのサイズを変更するようにした。
これで、Direct3Dで描画している領域もサイズが変わるようになった。

次は、SceneControlHandlerと言ったものを作り、このクラス経由でシーンのワールド座標とカメラを操作できるようにし、ボタンを押してカーソルを動かした時に表示が切り替わるようにする。
それが出来たら、各モデルを動かせるようにする。
徐々にそれっぽくなってきた。

投稿者 Takenori : 02:08 | トラックバック

2005年11月24日

イベントハンドラの共有は不可

同じイベントハンドラをPushEventHandlerで複数のボタンに設定し、終了する時にRemoveEventHandlerですべてのボタンのイベントハンドラを取り外すと、アクセス違反が発生した。
RemoveEventHandlerで1個だけ取り外すようにするとアクセス違反は発生しなくなった。
そこで、1つのボタンに対してのみPushEventHandlerでイベントハンドラを設定してみたが、1つのボタンに対してしか有効でなかった。

コードを追ってみると……
PushEventHandlerでは、引数で指定されたハンドラをハンドラリストの先頭にして、今まであったハンドラをその次に指定している。
ハンドラのリストはハンドラ自体がポインタを持った双方向リストだ。
って、同じハンドラを複数のボタンに設定したらダメじゃん。
ちなみに、RemoveEventHandlerでは指定されたハンドラの後のハンドラを前のハンドラとつないでいる。
つまり、複数に設定したら、他のボタンのハンドラがつながってしまう。
さらに、RemoveEventHandlerの引数のハンドラを同じにして何度もコールしてしまうと、ハンドラリストにNULLが設定されてしまう。
そのせいで、アクセス違反が発生していたようだ。

そこで、PushEventHandlerに渡す時にnewし、終了時はPopEventHandler(true)で削除するようにした。
でも、こうなるとハンドラ内でIDで処理を振り分けている部分をファンクターか何かにして、newする時に渡した方が効率が良さそうだ。
見た目としては、IDで処理を分けた方が、コードがそこに集中して見やすくはあるが。


とりあえず、各ボタンで視点の変更は出来るようになった。
次は各オブジェ(モデル)を移動させたり回転させたり出来るようにする処理だ。
オブジェのピックが入ったり、マニピュレータを表示したり、マニピュレータのピックがあったりと少々やることが多い。

投稿者 Takenori : 01:21 | トラックバック

Widget Editor on Visual Studio

XRCとwxrcでそこから出力されるコードによってある程度使いやすくはなったが、GUIのリソースエディタなどがもう少し何とかなって欲しい。
Visual Studioに統合できないものだろうか?
ActiveStateにはVisual Perlなどがあり、どうもこれはVisual Studioを拡張するもののようだ。
なら、Visual Studioを拡張する手段はあるのだろうと調べると、Visual Studio 環境の拡張と言うものがあった。
どうやらアドインの雛形はウィザードでお手軽に生成できるようだ。
ヘルプに従いウィザードを進め、ビルドしてみるとツールメニューからアドインが追加できるようになったが、何も出来ない。
まあ、何も作っていないので当たり前だが。

少しだけコードを追加してみた。
COMだ。
わからないことはない。
何とかなりそうだが……
いろいろと時間かかりそうな気はする。
がんばって作ってもなぁ、うーん。

投稿者 Takenori : 02:19 | トラックバック

2005年11月26日

格子を描く

Yが0の面に格子状の面を描こうと何気に書いたのだが……
落ちたり、フリーズしたりしまくる。
Meshの方は何ともないので原因は新たに書いた格子を描画する部分のはずだがよくわからず。

インデックスを使わないように書き換えてみたらちゃんと動いた。
インデックスバッファの扱いのどこかがまずいようだ。
ラインリストをインデックスで描くのがまずいのか? ヘルプにはポイントリストがダメって書いてあるだけ、ってCreateIndexBufferに渡す最初の引数はバイト数じゃないか。
インデックス数を渡していた……
直したらちゃんと動いた。

投稿者 Takenori : 02:14 | トラックバック

Widget化を考える

現在、Graphicsというクラスの中に、子ウィンドウ生成とDirectXの初期化を行う処理が入っている。
また、ウィンドウプロシージャもこのクラスが持っている。
今後、ウィンドウプロシージャにいろいろと処理を追加していくとしたら、Graphicsが肥大化してしまうし、分離した方がスマートだろう。
そこで、ウィンドウ関連の処理を別クラスにしようと思っていて気付いた。
Direct3Dを使って描画を行うwxWidget用のWidgetを作ればいいんじゃないか?と。
別スレッドになっている部分が少々気がかりだが、他のボタンなどのWidgetのようにSizerの上に配置したら、そこで手軽に3D描画が出来るとかなり汎用的になりそうだ。
3D以外にも2Dのもあれば、それを差し替えるだけで好きな方を楽に使えるようになるかもしれない。

Widgetにするとしたら、そのクラスからシーングラフのルートを取得できるようにすればいいだろうか?
後はいくつか設定を橋渡しすれば独立性を保てるかな。

具体的にどのように作るかは、似たようなWidgetにwxGLCanvasと言うものがあるので、これを参考にすれば何とかなりそうだ。
SaraではyaneSDK3rdを使っているので、描画はDirectDrawが使われている。
と言っても、ほとんどは自前で処理し、DirectDrawはフレームバッファのコピー関連とフルスクリーン周りしか使っていなかったはず。
なら、比較的楽にSDLに変更できるかな?
ま、そっちはそっちで試してみよう。

投稿者 Takenori : 23:51 | トラックバック

 
Total : Today : Yesterday :