三角端。

Δ-sphere管理人三角区也による絵日記/ゲーム開発日記。コメントは右側のweb拍手からどぞー。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カメラベクトル

もう9月も半分が過ぎそうです。

最近は自分の専門では無い部分をすることになって発狂しそうになりながらすごしています。



ふと思ったんですけど、ゲームを作ったりしていてカメラの操作ってみなさんどうやっているんでしょう。
カメラって基本的にはカメラ位置(position)、上方向ベクトル(head)、視点(lookat)を設定します。
scri_369.jpg
でもこれって意外と使いにくいんですよね・・・

上ベクトルは固定だとしても、カメラを動かすためにばらばらの2変数を操作しないといけない。
キャラクターを追いかけるにしても視点も位置も動かさないといけない。
それがカメラだけ動いて視点の変わらないレールカメラなら使いやすいのかもしれませんが、
ゲームでそんなカメラを使うことは非常に稀だと思います。

実際には内部でlookatとpositionから視線ベクトルを出して、
視線ベクトル、上ベクトル、横ベクトル(視軸と上の外積)の3ベクトルとカメラ位置情報positionで表現されます。

自分は次の変数でカメラを管理することが多いです。
・視点位置(pos)
・回転角(rot)
・カメラ距離(length)

基準ベクトル(0,0,length)を作ってrotの回転をかけます。
これで視線ベクトルを算出します。
視点はposで、視線ベクトルをposだけ移動させたものがカメラ位置になります。
ついでに上ベクトルも回転させてもいいと思います。
scri_369b.jpg

回転角はクオータニオンでもいいんですが、
そんな複雑なことはしないなら、仰角(X軸)、平面上の回転(Y軸)の2回転で表現してもわかりやすいと思います。
スポンサーサイト

C#って

C#って機能が最初から色々あって便利ですね。

だけど、便利だけどなんかモヤモヤ。

バイナリの入出力がしにくい。
BinaryStream?いやそんなことよりも構造体をmemcpyさせろよと思ってしまいます。

例のデータベース生成ツールができてきて、
ゲームへの受け渡しのためのバイナリフォーマットを作っていたんですよ。
memcpyがないのでいちいち変数をWriteしていきました。
もうこれだけでめんどくせえ・・・って思ってしまってやる気がそがれていきます。

要素をひとつひとつWriteして、ようやく終わったところでテスト、失敗。
何が悪いんでしょうねえ・・・どうやらWrite(string)が悪い模様。
どうも日本語を出力したときにバッファのサイズが安定しない。
どうやらUTF-8になる模様。
でも、マウスオーバーしたときに表示されるヘルプにはUnicodeうんたら。

バイナリサイズの計算がめんどくさいのでUnicodeにしたいんですが、
string.ToArray(),stringToCharArray()を使ってもUTF-8で出力されるみたいで・・・
でも、マウスオーバーしたときに表示されるヘルプにはUnicodeうんたら。

どうしたもんかなと色々調べているとBinaryWriterのコンストラクタにエンコード指定がありましたよ・・・

せめてヘルプくらい正しくして欲しいですね・・・
あとコンストラクタじゃなくて、Write関数自体にエンコード指定があったらなと思いました。



C#でもmemcpyっぽいことはできます。
が、色々手順がめんどいのでC++みたいにサクッとはいかないですねえ・・・
これに関しては安全性の面から仕方の無いことかもしれませんが。

データベース作成ツール データ整形

前回の続き。

マサカツヅクトハオモッテイナカッタヨ

データベースの値の整形のお話。

screen_254.jpg

こんな数値データの表を作ったとします。
データ型は整数です。
そのときにユーザーが小数を入力したらどうなるでしょう。
データとしては整数を持たなければいけないのに小数がデータになってしまいます。
あるいは数値以外の文字列を入力したときデータは文字列になってしまいます。

そのために小数→整数に変換したり、不正データである文字列であればキャンセルしたりという動作が必要になります。

ユーザーが入力を決定したときにCellParsingイベントが発生します。
このCellParsingイベントでユーザー入力データを正しいデータに整形することができます。
この引数(DataGridViewCellParsingEventArgs e)のe.Valueを書き換えたらできるんじゃねという安易な考えのもと、

if(e.Value.GetType() != typeof(int)){
 e.Value = 0;
}

というコードを書きました。
結論から言うとこれだけではまったく反映されません。
文字列データを入力したとき、0が代入される・・・デバッガで1行ごと実行しても代入されるんですが表示上は入力した文字列がそのまま表示されます。
どうやらe.ParsingAppliedをtrueにしないとこの関数内の変更は反映されないようで・・・

んでe.ParsingAppliedをtrueにしてみたら今度は止まる止まる。
スタックトレースも内部的に処理されているような場所でとまっているしなんだこれ・・・
色々調べていたらこのe.Valueには必要な型というのがあるらしくその型にしないといけないっぽいのです。
e.DesiredTypeを見てみたらdecimalだったので、
e.Value = 0 を
e.Value = 0m
にしたらうまく動くようになりました。

int→decimal変換くらい勝手にしてくれてもいいと思うんだ・・・ うん

データベース作成ツール

画像コンバートツールをある程度作り終えました。
結局PNGやDDSでゲーム側まで流したほうがいいんじゃないかというのが素直な感想。
また実際に使うときに考えます。





次はデータベースツールです。
それは、まあ、アイテムとかの性能とかのリストを作るためのツールです。
エクセルとかでつくってもいいんですが・・・
エクセルを持っていないのでそれだけのためだけに買うのはちょっと・・・ということで作ることにしました。
簡単なのだとカンマ区切りテキスト(CSV)とかでも表現できるんですが、規模が大きくなると大変なので・・・
あと、CSVだとカンマの扱いとかダブルクオーテーションとか例外処理が必要だったり、
エクセルの代わりに入れているOpenOfficeの表計算ツールがCSVを扱いにくいとかいろいろ不満な点があったりしてます。

GUIツールを作るのはC#を使うのが楽だという噂を聞いたのでVisualC#2010EEをインストール。
DataGridViewなるパーツでそれっぽいことができそうだったんで、適当に作ってみたのが下の画像。
screen_253.jpg

ここまでは簡単だったんですが、ここからが大変でした。
DataGridViewのデータの変更とか整形とかがよくわからんマンになっちゃいまして・・・(苦笑
VirtualModeにしていない場合はデータを作るのは簡単だけど、データの整形とかはできないので却下。

VirtualModeの場合はデータを自分で作らないといけないということで・・・
アプリケーションが表示列を要求するとき、CellValueNeededイベントで表示データを設定する。
ユーザーが編集を終えたとき、CellValuePushedイベントで内部データに反映させる。

ただ、DataGridViewには上の画像の最終行のように新規に追加するための行というものがあります。
その新規行をクリックしたりすると、その行が普通の行になり、新しく新規行が生成されます。

なので内部データのレコード数+1の行があるという状況になっています。
もちろん新規行でも表示文字列が必要なのでCellValueNeededイベントが発生します。
それを例外処理してデフォルト値を返却しておきました。
クリックしてデータが確定した瞬間に発生するイベントがあれば楽なんですけどねえ・・・
まあAddRowイベントを捕まえて内部データにも新規行フラグを付けておいてもいいのかもしれませんが・・・


長くなってきたんでデータ整形の話はまた次回気が向けば。

signedの罠

例大祭お疲れ様でした。1週間前の話ですが。

新しい出会いとかもありましてたくさんやる気をいただいた気がします。




画像データを独自フォーマットで出力するツールを作っています。
pngをそのまま読み込ませたほうが圧縮効率とかがいいとか思わなくも無いですが・・・

途中なぜか正しく値が取れなくなってしまいました。
char型の変数をint型の変数に代入したら値がおかしくなってしまって・・・

ビットマップの解析部分をこんな感じにしてたんですね

color = 0xFF000000;
color |= src[pixel_ofs + 0];
color |= src[pixel_ofs + 1] << 8;
color |= src[pixel_ofs + 2] << 16;

どれかの値が0xFFのときになぜか最終出力colorが0xFFFFFFFFになるという・・・
デバッガでメモリの内容を見ても正しいのになぜなんだ!

原因はsrc型がsigned char*でcolorがsigned intだったからでした。
signed charでの0xFFをsigned int型に代入すると
0xFF=-1と解釈されるので、
intに-1を代入すると0xFFFFFFFFとなってしまうというのが理由でした。

やっぱり色計算とかはunsignedでしないとだめね・・・

ちなみに・・・
unsignedだと0xFF=255なので、
intは255となり0x000000FFとして正しく値が送られます。

なんという凡ミス・・・
次のページ

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。