!!!独り言日記 !!考える人と考えない人(2006/03/31) 最近の仕事では、内容が内容だけにやたらと考えないといけないことが多いです。 以前、ちょっと頼まれて作業を効率化するためのアプリ(ツール)を 作りました。いやはや、wxWidgets大活躍です。 要望を聞きだして形にするまで数日、ですが、アルゴリズムを考えないと いけない部分があって、それ用のコードを書いてたりしました。 で、思うのですが、若いうちに考えるクセをつけておかないと、 いざというときに小回りが利かなくなる・立ち往生してしまうことがあるのでは、とよく思ったりします。 私にプログラムの依頼が来る(特に緊急)場合は、「はじめっから このようにしておけばよかったんじゃないの?」「もうちょっと上流工程でつめるべきだったのでは?」といった内容をよく聞いたりします。 プログラムではあまり使わない言葉ですが、DTPとかでは交通整理の役目をする立場を「ディレクション」と呼んだりします。開発だったらプロジェクトマネージャになるでしょうか。この部分ですでに無駄なことを気づかずに進めている、というのが よく行き詰るプロジェクトの定番というか・・・、ようは計画性のなさが 原因というか(^_^;;。 で、計画を立てるときに「考えているかどうか」、これは非常に大事なことであると思います。意外とこれが出来ない人が多いかも。 これって、学生時代から常に頭を使うクセをつけておかないと、そもそも考えることが できなくなってしまうのではないか、と最近思ったりしてます。 プログラムも同じで、新しいことを常に考えてないと(妄想してないと)、いざ形にするときに何もできない、って人も多いのではないでしょうか? 形(サンプルとか雛形)があればできるんだけど、ゼロからはできない、とか。 これって、意外と第三者から見るとすぐ見抜けたりもしますよね。 ということで、今学生の方は、あえて苦労する(便利なことに頼らずに、 頭をひねってみる)ってのも 将来を長い目で考えると「修行」としていいかも、と思う今日この頃です。 宿題をこなすっていう無意味な作業なんかも、積み重ね積み重ねで 将来につながるのかもしれませんね。 で、私は私で、仕事にて変なアルゴリズムを考案するのに頭を使ってます(苦笑)。 おそらく理論をドキュメント化しておかないとソースを見たところで 誰もメンテできないので、まとめておかないと。 このへんって、なにか効率化できないかなぁ(ドキュメント書くのめんどくさい・・・)。 今は「空間の流れ(流体力学じゃないです)」を求めてごにょごにょする理論を 考えてるのですが・・・・。試しては検証、ダメだったら 新しい理論を推敲する、の繰り返しです。 しかし、若いうちにもうちと学を積んでおいたら、 もうちょっと楽だったかもしれないですね(汗)。 !!超力兵団(2006/03/30) ひさびさにゲームをしました。アトラス社の「デビルサマナー 葛葉ライドウ対超力兵団」です。 メガテンシリーズとしてはちょっと異質かな?実験的なバージョンのような気も(といっても、過去にペルソナ1とソウルハッカーズしかクリアしてないわけですが。このシリーズ、やりこんでいる人はほんとに詳しいですよね)。 で、土日とかにちょくちょくやってクリアしました。 うん、雰囲気がいい感じです。個人的にはこの時代でシリーズ化してほしいかも。 時代はFF12なのにちょっとそれてみたり(笑)。 FF12はぬるくないと聞いてますので、時間があればやりたいけど 短期間では難しそうだなぁ。 最近は3DCGきれい!なものよりも http://www.atlus.co.jp/cs/game/pstation2/persona3/ のようなもののほうが好きだったりする・・・。 しかし、遊びでゲームシステム作ってみたいもんですねぇ。 年々仕事以外のプログラムの時間が減ってるので、息抜きプログラムでも したいものです。 (が、最近の息抜きはもっぱら散歩。これはこれで健康でいいのかな(^_^;;) !!三角形の内分点での面積法則(2006/03/25) 最近、どうも歯が痛くて歯医者に見てもらってたのですが、 虫歯は見当たりません。で、かみ合わせの問題かも とのことで、以前の治療後で埋めてもらったところを再度調整してもらった りしました。これで、どうにかおさまりました。 ちょっとした部分でもメンテしてもらわないとなぁ、と感じました。 かみ合わせの場合は、歯が痛いといっても「どこが痛い」とか 原因を突き止めにくくて、あごや頭に痛みがきたりします。 虫歯は注意できるのですが、かみ合わせは(寝ているときの 歯ぎしりとか)無意識ですので対策は難しいですね。 さて、ひさびさに3Dのお話です。 [[交差判定|交差判定_3DCG]]で書いた三角形の交点情報UVですが、これについて 詳しく書いてみます。 {{ref_image img_20060325.png}} このUVって何(テクスチャのUVではないです)、 ということですが上記で言うとまず以下のような法則が成り立ちます。 W = 1.0 - (U + V) U + V + W = 1.0 これは、三角形の面積比を表します。 {{ref_image img_20060325_2.png}} 三角形全体の面積をSとした場合、2ベクトルE=(B-A)、F=(C-A)で作られる三角形の面積は S = sqrt(|E|^2・|F|^2 - (E・F)^2) * 0.5 であらわされます。 これは、三角形の3点が判明すれば計算可能です。 また、上図のような点Pが分かっていれば、U/V/Wの値は求まりますよね。 U = Uの面積 / 三角形全体の面積 V = Vの面積 / 三角形全体の面積 W = 1.0 - (U + V) です。 それと、三角形の頂点ABCとUVWの関係ですが、互いに対の位置にある、という 法則も見えますでしょうか。 Aの対辺BCを含む、△PBCの面積比をUとする。 Bの対辺ACを含む、△PACの面積比をVとする。 Cの対辺ABを含む、△PABの面積比をWとする。 このUVWが求まっていれば、逆に点Pの座標も逆算してくることができます。 P.x = Ax * u + Bx * v + Cx * w; P.y = Ay * u + By * v + Cy * w; P.z = Az * u + Bz * v + Cz * w; ここで求めた三角形の比率が求まれば、後は点Pでの法線を求めたりテクスチャ用UVを 求めたり、と芋ずる式にいろんなことができるようになります。 頂点ありきの補間関連はこれでいろいろ可能なはず。 逆に内分点上のテクスチャ用UVのみが判明している場合で頂点座標Pを求めたい、というときも 三角形頂点のテクスチャ用UVから(2次元の面積計算として)面積比UVを求めてくることが可能です。繰り返しテクスチャがある場合はアウトでしょうけど・・・ で、圧縮にも使えそうですね。 点Pを保持する場合があったとしても、点PのXYZ(float x 3 = 12バイト)を 持つ必要はなく、UVを65535(それぞれ2バイト)に格納するようにして、4バイトで 表現する、とすると単純に1/3圧縮です。 しかし、数学はいろいろ発見があって面白いなぁ。 !!続・Norton(2006/03/19) 3/19の昼くらいにLiveUpdateかけましたが、どうやら 直っているようです。 きちんとスキャン・メール受信も行われるようになってます。 !!Nortonがおかしい?(2006/03/18) Norton Internet Security 2006でLiveUpdateをかけたら、 3/18の段階でスキャン関連が実行されなくなりました(私がLiveUpdateを かけたのは3/17ですがその段階ですでにアウト)。 後、メールの送受信もなぜかシャットアウト(NISをOffにすると、 認証は通るけどメールをスキャンするところで止まりますね。 Nortonのアップデートミスかもと思いつつ放置です(^_^;;。 メールはしばらく見ることができないですが・・・・。 後、OSシャットダウンに異常に時間がかかってます。 幸い(?)というか、2chのセキュリティ板でも同じ症状の方が いるみたいですので様子見しときます。 直ったらまた報告しますね。 最近は、なかなか仕事のほうが立て込んでいて サイトを更新できてませんでした。 今まで(自分自身で)実験したことがないアルゴリズムを考えることが多いので、 沸騰気味です(苦笑)。 !!動いている物体の検出2(2006/03/08) 流行に乗ったのか花粉症でいろんなことに集中できないため、 鼻炎カプセルを購入。普段、薬に頼らないだけに劇的に効きますねぇ。 さて、以下の動いている物体の検出です。 根本にあるのは、「動いていない部分をいかに見つけるか」 ということにあるように思います。で、「影」対応が第一の問題として あがります。影があっても影を除去することができないかなぁ、 ということでHSVに変換してみたり、PhotoShopでフィルタ処理して 挙動を見たりしてました。 ただ、周囲の色(というか明度)の差分を取ると、 なんとな〜くですが、似通っている部分を検出できそうなので これが足がかりにできそうな気もします。 また、静止画では分からないけど動画になると 見えてくることもあります。 もしかしたら、まったくの予備知識がない人(赤ちゃん)が1フレームの画像を 生まれて初めて見た瞬間は、影とその他の検出は難しいのではないだろうか。 それどころか、遠近感を含めた奥行きや輪郭も検出できないのでは。 動きをしばらく眺めてみて、初めて「この部分は影かもしれない」と 検出することができる、と仮定して、動く物体のみを検出 してみようかと。 動いている物体付近を円で囲む、というのは 動く物体の輪郭にきっちり線を引くよりも簡単な気もしてきました。 (動いているところの分布を調べて、二分木構造で画面を 再帰的に分割して適当に囲ってしまえば・・・できないかな?) この手の分析は、「動いている画像」があってようやく生きてくるのかも しれません。 !!動いている物体の検出(2006/03/05) 以前、動いている人や 不審物を検出する防犯カメラシステムがテレビで紹介されていたことがあります。 空港に置かれた不審な荷物などを円で囲ってマーキングしてました。 あれいいなぁ、と思ってちょっとUSBカメラで できないか遊んでみました。 輪郭検出なら、SFでやるように動形状の周りを囲えないかと思ったのですが、 これはこれで技術がいりそうですね。 影ができたときの濃淡をどう処理するか、 カメラが動いたら検出をどうするのか、 太陽が動いた場合の挙動の吸収をどうするか、 アロハを着た人などを検出するとしたら背景と一部溶け込む部分がありそう、 などなどいろいろ課題はありそうです。 {{ref_image movie_test_20060305.jpg}} そのときのムービーキャプチャをswfにしたもの(967KB):{{ref movie_test_20060305.swf}} まじめにやるとすると結構実装時間がかかりそうです。 リアルタイムで行う必要がありますし。 逆に言うと研究し甲斐がありそうですね。 ただ、市販のUSBカメラでも防犯システムのような のは実現できるような気もします。 !!ひさびさに(2006/03/04) 秋葉原に行ってきました。 無謀にもNDS liteを探してたのですが、軒並み完売してました。 しかも、発売日の3/2にはすでに売れちゃってたみたいで「3/2に完売しました」 フダが貼ってる店ばかりでしたねぇ。えらい人気です。 後、舞-乙HiMEのオープニング曲のCDシングルを購入。 TVで見たときになかなか燃えるアニソンやん、と思ってましたので。 iPodに入れてエンドレスで繰り返し聞いてます(笑)。 CD買うのも久しぶりです。 2006/03/04現在でオリコンランキングでも15位ということで、 一般受けもよさそうですね。 燃える曲(萌えるじゃないよ)を求めるとなると、アニソンが やっぱり強いなぁと思ってしまう今日この頃です。 !!ランダムで領域を埋める(2006/03/02) 一次元または二次元以上の空間にて、 ランダムで点を打つことを考えます。 このとき、 for(int i = 0; i < 20 * 20; i++) { x = rand() % 20; y = rand() % 20; SetPixel(x, y, RGB(0, 0, 0)); } のように点を打って埋めようにも、rand()にて同じ位置に 再び点を打つ可能性があるため、効率が悪いです。 かといって、すでに点が打ってあるか調べて すでに 点が存在する(x, y)の場合は 再び点を打つ位置を探しに行く、 としても効率が悪いです。 実際はこれとは違う目的で 上記のような目的が 発生したわけですが、イメージが分かりにくいですので Flashで例を表してみました。 {{flash RandomAlign.swf,width=300,height=300}} ソース:{{ref RandomAlign.fla}} 青いブロックを次々にランダムな位置に表示していってます。 内部的にも、上に書いたソースみたいにランダムな位置で かぶって再計算が発生するということはありません。 実はこの手のはメガデモでも良く使われる(と思われる)やり方でして、 最終形態の整列された状態をくずしていくことで実現可能です。 一次元で言うと、以下のように初期化します。 int indexA[20 * 20]; int i, tmp; int iVal1, iVal2; int cou; cou = 20 * 20; // 昇順に配列の値を初期化 for(i = 0; i < cou; i++) indexA[i] = i; // 配列を入れ替える for(i = 0; i < cou; i++) { iVal1 = rand() % cou; iVal2 = rand() % cou; if(iVal1 != iVal2) { // 値を入れ替える tmp = indexA[iVal1]; indexA[iVal1] = indexA[iVal2]; indexA[iVal2] = tmp; } } これで、配列indexA内はバラバラに値が入ることになります。 for(i = 0; i < cou; i++) { // indexA[i] を表示 // ... } とすることでランダムに表示されますが、決して同じ値はでない、 というのが分かりますでしょうか? で、「これが何の役に立つの?」ということですが、 この手の考え方の切り替えはいろんなとこで役に立つのではないかなぁ、と 思ったりします。 実際、現在の仕事のプログラムでちょっと使ってたりします。 レンダラでも使えそうな気もなんとなく。 無駄をなくす、ということを考えるといろんな方向から ものを見る必要がありそうですね。