忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


かんたんXNA その3 2D画像の表示

このページは古いです
最新版はこちら

前回はウィンドウの背景を塗りつぶしました。
しかしこれだけでは華がありません。
もう少しましにしましょう。

今回は1×1の画像(Texture2D)を作り、それを表示することにします。
これは簡単なようですが、かなり複雑になります。

まず、2Dの描画を行うには、2D描画を全てカプセル化しているSpriteBatchクラスを使います。
このクラスはTexture2Dを表示するSpriteBatch.Drawメソッドや、ここでは扱いませんが、文字列を表示するDrawStringメソッドを持っています。
 

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

 

class MyGame : Microsoft.Xna.Framework.Game {     GraphicsDeviceManager graphics;     SpriteBatch spriteBatch;     Texture2D texture;

    public MyGame()     {         graphics = new GraphicsDeviceManager(this);     }

    protected override void LoadGraphicsContent(bool loadAllContent)     {         if (loadAllContent)         {             spriteBatch = new SpriteBatch(graphics.GraphicsDevice);

            //create 1 x 1 texture.             texture = new Texture2D(                 graphics.GraphicsDevice,                 1,  //Width                 1,  //Height                 0,  //numberLevels                 ResourceUsage.None,                 SurfaceFormat.Color                 );             texture.SetData<Color>(new Color[]{Color.Black});         }     }

    protected override void Draw(GameTime gameTime)     {         graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();         spriteBatch.Draw(texture, new Rectangle(0, 0, 100, 100), Color.White);         spriteBatch.End();     }

} static class Program {     static void Main()     {         using (MyGame game = new MyGame())         {             game.Run();         }     } }

xnaSimplestTexture.JPG ※左上に、黒い1x1のTexture2Dを、 100x100に拡大して描画しています。 む、むずかしい・・・ このプログラムは、(0, 0)の位置に100x100の黒い画像を表示しています。 たったこれだけなのにこんなに複雑なコードを書かなければいけないとは異常です。 しかしこれでもまだマシな方なのです。 より多くのことをできるフレームワークは、少々難しくなっても仕方がありません。 愚痴を言うのはやめて建設的な話をしましょう。 前回と比べて新しく出てきたのが、LoadGraphicsContentメソッドです。 これは、グラフィックスを表すデータ (例えば今回のようにTexture2Dだったり、あるいは3Dのモデルだったりです) をロードすべきときに自動的に呼ばれます。 注意すべきなのは、これは一度だけ呼ばれるとは限らないことです。 ゲームの間、グラフィックスデバイスがロスト (使えなくなってしまうこと。フルスクリーンにしたり、 そうなっているとき他のウィンドウがアクティブになったり、 スクリーンセーバーを起動したりしたときです) したり、リセット(ロストから復元)したときにも呼ばれます。 このメソッドの中で、SpriteBatchのコンストラクタを呼んでいます。 引数にGraphicsDeviceがあるのは、SpriteBatchがGraphicsDeviceを カプセル化しているからでしょう。(多分) その後Texture2Dのインスタンスをを作成しています。 コンストラクタは複雑すぎて頭痛がしてきますが、 つまりは1×1のTexture2Dを作っているということです。 その後、その1×1のマスを黒で埋めています。 1×1の黒いTexture2Dができあがったというわけです。 もちろん、サイズを変えてもうちょっとカラフルにすることもできます。             texture = new Texture2D(                 graphics.GraphicsDevice,                 3,  //Width                 1,  //Height                 0,  //numberLevels                 ResourceUsage.None,                 SurfaceFormat.Color                 );             texture.SetData<Color>(                 new Color[]{Color.Navy, Color.White, Color.Red}                 ); xnaSimplestTextureTricolor.JPG MyGame.Drawメソッドに目を転じましょう。 背景をCornflowerBlueで塗りつぶした後、 左上に100×100に拡大したTexture2Dを描画しています。 そのとき、頭と後ろにSpriteBatch.Beginメソッドと SpriteBatch.Endメソッドを呼んでやる必要があります。 呼ばなければ例外が発生し強制終了です。 これは、2D画像を表示するときだけではなくて、文字を表示するときも同じです。 ちなみに、もちろん、BeginとEndの間にDrawメソッドは何回呼んでもかまいません。         spriteBatch.Begin();         spriteBatch.Draw(texture, new Rectangle(0, 0, 100, 100), Color.White);         spriteBatch.Draw(texture, new Rectangle(200, 200, 80, 80), Color.White);         spriteBatch.End(); xnaSimplestTexture2.JPG(※2回呼べばとうぜん2つの四角が表示されます) さて、今回のこの方法はあまりスマートではありません。 画像はなるべく外部のファイルにしておきたいものです。 次回はその方法について扱います。

 

拍手[0回]

PR

かんたんXNA その2 背景のクリア

前回では、ウィンドウが全く描画を行っていませんでした。
そのため、他のウィンドウに隠されると跡が残ってたいへん見苦しいものでした。

これではいけません!

このような跡はすぐに消せるようにならなければなりません。
それが出来るようになったのが、以下のコードです:

using Microsoft.Xna.Framework;

class MyGame : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;

    public MyGame()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.White);
    }

    static void Main()
    {
        using (MyGame game = new MyGame())
        {
            game.Run();
        }
    }
}
xnaSimplestClearable.JPG

このプログラムは、一秒間に60回背景を白で塗りつぶしています。
それをやっているのがDrawメソッドですが、こいつは一秒間に大体60回呼ばれるのです。

これだけひんぱんに背景を消しているので、もう他のウィンドウに隠されても大丈夫です。

さて、注目すべきは一秒間に60回塗りつぶしているという部分です。
普通のプログラム、WindowsFormsなどでは、他のウィンドウに隠れたときなど、描画すべきときにしか描画しませんでした。
しかし、XNAではそのようにはしません。
狂ったように、何も変化が無くても、とりあえず60回描画します
ゲームプログラミングとは、そのようなものだということです。

もう少し細かいところに注目してみましょう。
このプログラムでは、まずMicrosoft.Xna.Framework.GraphicsDeviceManagerのインスタンスを作成しています。
これは、ゲームのウィンドウのサイズやフルスクリーン、それと描画全般を行うGraphicsDeviceを管理するマネージャーです。
(管理(マネージ)するマネージャーとは変な表現ですが、まぁ大目に見てください)

重要なのはこのクラスというよりも、そのプロパティからアクセスできる、GraphicsDeviceです。
このGraphicsDeviceは役割としてはちょうどWin32でいうHDCやWindowsFormsやJavaのGraphicsクラスのようなものです。
つまり、描画はこれを通じて行うのです。
点を表示するにも、線を表示するにも、2D画像を表示するにも、3Dのモデルを表示するにもこのGraphicsDeviceが必要です。
(もっとも、2Dの場合はカプセル化されていて、描画の時には意識する必要はありませんが)

このプログラムではGraphicsDevice.Clearを使って、ウィンドウのクライアント領域を白で塗りつぶしています。
もちろん色は別に白でなくてもかまいません。
でもでも黒でもかまいませんが、Xnaの多くのサンプルでは、空の色に似ているからでしょうか、Color.CornflowerBlueを使っています。
多数決の原則(?)により、次回からはColor.CornflowerBlueを使うことにします。

 

拍手[0回]


かんたんXNA その1 ウィンドウの表示

※このページは古いです。
最新版はこちら

XNAを簡単なレベルから少しずつ整理していこうと思います。
まずは一番簡単なプログラムから。
class MyGame : Microsoft.Xna.Framework.Game
{
    static void Main()
    {
        using (MyGame game = new MyGame())
        {
            game.Run();
        }
    }
}

これはおそらくXNAの最も簡単なプログラムで、
Gameクラス(を継承したMyGameクラス)のオブジェクトを作り、Runメソッドを呼んでいます。
実行すると(ゲームの)ウィンドウが表示されるだけです。

xnaSimplest.JPG

しかし、このままでは何も描画していないので他のウィンドウで覆い隠すとこんな風に跡が残ってしまいます。

xnaSimplestCovered.JPG

※ちなみに(どうでもいいことですが)、このウィンドウのタイトルはMyGameとなっていますが、これはクラスの名前ではなくて実行ファイルの名前に関係しているようです。
というのも、このコードをコンパイルして出来たプログラムは"MyGame.exe"だったのですが、この名前を"Game.exe"に変更するとタイトルはGameになったからです。

ただ、これはコマンドラインから普通にコンパイルした場合の話で、VisualC#を使った場合には、AssemblyInfo.csのAssemblyTitleがタイトルを表しているようです。

拍手[0回]


ヤラセ・ドキュメンタリー!

テレビ番組にはウソがつきものです。

そしてそれは内容が正確であるべき
科学ドキュメンタリーであっても例外ではありません。
残念なことに、たいてい変な演出や脚色がまじってしまうものです。


昨日、それを実感させることがありました。
十数年前(1990年くらい?)にあったNHKの
チンパンジーが石を道具として使うところを
はじめてテレビに捉えたドキュメンタリーを見たのですが、
珍しい体験として、そのドキュメンタリーを作る現場に立ち会った人が
合間合間に解説してくれたのです。

といってもNHKの方ではなくて、その番組が追っていた
3人の霊長類を研究していたグループ(?)の一人だったのですが。threeChimpResearchers.JPG
(もう少し詳しく言うと、一人は京都大学の杉山幸丸教授で、
後の二人は当時大学院生でした。
ぼくが話を聞いたのは当時大学院生だった人です)


さて、そのドキュメンタリーというのは
チンパンジーが石を使って植物の実を割るのを
NHKが初めてカメラに収めたものだそうで、
大体全部で一時間くらいのものでした。

まず杉山教授と二人の大学院生、
そしてNHKのスタッフ達は西アフリカのギニア共和国へ向かいました。
(杉山教授はそれまでに何回もそこを訪れていたそうです)
ギニアはフランスから独立する際にけんかをしてしまい
援助を打ち切られインフラがメチャクチャになり、
つまりチンパンジーのいるところまで移動するのに苦労します。
ギニアの中では主に車(フランスと仲直りしたときに寄付してもらったタクシー)を使って移動するのですが
移動の途中で橋のかかっていない川があったりして
そこではいかだの上に車を乗っけて移動します。

そして実際、テレビにはそのいかだの場面が映るのですが
そこで元大学院生の人がビデオを一時停止してこう言います:
「じつはこれ、帰りのなんです」
つまり、帰りに川を渡ったシーンを
あたかも行きのシーンであるかのように編集したということです。
番組はまだ始まったばかりだというのに、幸先の良すぎるスタートです

そして一行はチンパンジーのいるらしいところに着きます。
チンパンジーが住めるだけ大きい森が近くにあるところで、
現地の人が市場を開いています。
そして教授が車の中から、シャツに土ぼこりをつけて、
いかにも「長い間車の中で窮屈だったー」というかんじで出てくるのですが
そこでも元大学院生の人が一時停止してこう言います:
「じつはこれ、別の日なんです」
つまり・・・教授が車の中から出てきたシーンは
到着した日に撮ったものではないということです。
到着してから日がたったときに
タイミングを見計らって撮ったものなのだそうです。

「タイミングを見計らって」というのはどういうことかというと、
実は市場は毎日やっているのではなくて決まったときにしかやっていなくて、
そのにぎやかな日を選んで撮影をしたということです。
教授は演技をしていたわけですね。
ちなみにシャツについていた土ぼこりは撮影前にみんなで協力してわざと付けたそうです。
憎いことをやってくれます!

到着した後、3人とスタッフ達は森へ入ります。
3人はトランシーバーで互いに連絡を取り合いながら
森の中へ別々に入っていきます。
チンパンジーは森の中で簡単に見つけられるわけではないので
別行動は当たり前、とくにおかしくは無いシーンに思えたのですが、
元大学院生の人の一時停止です。

そのシーンはヤ・・・演出だったそうです。

NHKに頼まれて3人とも演技をしていたのだそうです。
そういわれると心なしか、「こちら***、こちら***、チンパンジーは・・・」
というセリフがウソくさく聞こえます。
まぁチンパンジーの生態についてウソをついているわけではないので
深刻な問題というわけでは・・・ないでしょう。

しばらくすると教授がチンパンジーのいた痕跡を見つけます。
しょうがに似た植物がかじられて捨ててあったのです。
さすが教授!
しかし本当は、これを見つけたのは元大学院生の、今解説をしてくれている人だったのです。
まぁたしかに・・・(当時は)無名の大学院生が見つけたという風に撮るのよりも
教授が見つけたということにする方が華があるに違いありません。
NHKはその点をよく心得ているということですね。

さて、そのしょうがに似た植物を教授はまじまじと見つめます。
何をするのかと思えばパクリと食べました。
チンパンジーと間接キスをするなんて・・・!
それとも齧られていないところを食べたのか!?
いずれにせよ、病原体と不必要に接触することになるはずです。
そのような危険を冒してまで、チンパンジーの生態に迫ろうとする
教授の研究者魂には頭が上がりません。
・・・と思っていたら、これは演・・・出なのだそうです。
よくよく考えてみるとこれは当たり前で、
何度も研究で来ているところでわざわざチンパンジーの
食べ物の味を確認する必要は無いというわけです。
(気になるのなら一番最初に来たときに確認しているはずですからね)

その後番組はチンパンジーの生態を追っていきます。
ここから先はぼくの時系列の記憶が怪しくなるので
おもしろい(とぼくが感じた)ところを表にして書いておきます。
(順番は入れ替わっているかもしれません)

 番組で放送された内容  その真相
 チンパンジーの一人(匹?)が枝をへし折って一行に投げつけてきます。(チンパンジーは腕の力が力が人間の5倍はあるので、直径5センチはある、かなり太い枝でした。)
しかし運良く誰にも当たらずにその枝は地面に落ちます。
 投げつけてくるところまでは本物ですが、その枝が地面に落ちるところはスタッフが投げなおして撮りました。
よくよく考えてみるとこれは当たり前で、いきなり枝が投げられたのにそれが地面に落ちるシーンをカメラで上手く撮るのは難しいわけです。
 チンパンジーが木の上にいて動き回っているシーンが続きます。  そのシーンはツギハギでした。別の時に撮ったものをつなぎ合わせたものだったのです。
よくよく落ち着いて観察すればそれはわかることで、木の葉っぱの種類が全然違います。
 教授がチンパンジーが枝と葉っぱで作ったベッド(地上から20メートルくらい!)に座ってどんな具合か確かめます。  スタッフからたのまれてやったそうです。
これもやはり当たり前で、今まで何度も来ているわけですから、わざわざ確かめるまでも無いということです。
 森と森を分ける、木の生えていない道のようなところ(といっても舗装されているわけではないですし、幅も数メートル程度です)をチンパンジー達がたくさん横切ります。  別の日に取ったやつをつなぎ合わせています。そのため、同じ個体が何度も横切ったりしています。

他にも、チンパンジーのある習性(たぶん、肉食のことだったと思う)
をテレビカメラに収めるために、
わざとそれがおきやすいような状況(獲物を人間の方で用意して・・・だったと思う)
を作ったりもしたそうです。
教授はこれじゃあインチキじゃないかと渋ったそうですが、
プロデューサーの理屈では
これはチンパンジーの実際の行動なのでokなのだそうです。
そうかもしれません。
しかし、やはり何か腑に落ちないところがあります。


そして最後に、チンパンジー達の石を使った木の実割りを撮って終わりでした。


教訓

このことから何が学べるでしょうか?
「これだからメディアは信用できない。」、
「こんなに簡単にだまされるなんて大衆はバカだ。ほんの少し注意すれば見破れるのに」
というのもひとつの考え方です。

しかしここでは別の見方をしてみようと思います。
もしかすると人がこうやってだまされるのは
ある意味仕方の無いことなのかもしれません。
ぼくが言っているのは、だからあきらめろとかそういうことではなく、
これはもしかすると人間の「フレーム問題」なのかもしれないということです。

この番組のイカサ・・・演出は注意深く見れば、
あるいは考えれば、見破れるものがほとんどです。
しかし、大半の人はそれを見破れません。
なぜでしょう?
これはおそらく人間はそのように出来ていないからです。
あらかじめ情報を与えられない限り、
こういったドキュメンタリーを「注意深く見たり、考えたり」しないのです。

もし、人間が見聞き体験すること全てに対して「注意深く」なれば、
それにはかなり副作用があるはずです。
「注意深く」なることにはもちろん利点もありますが、同時にコストもあります。
あることに「注意深く」なれば必然的にほかの事が考えられなくなり、
それが重大なことだったとすれば、
そしてそれが緊急のものだったとすれば、
物事はに悪い方向に進みます。

それ以外にも「注意深く」なることそのもののコストもあるでしょう。
人間の脳はかなりエネルギーの消費の激しい臓器だからです。
どのようなことに対しても「注意深く」なれば採算が合わなくなります。
そのため、おそらく人間は限られたものに対してのみ「注意深く」なると思われます。
(この「限られたもの」とは具体的にどのようなものかはわかりませんが、
おそらく「現在自分が扱っているものに概念的に近いもの」といったところでしょう。)

これが何を意味しているかというと、
単に「物を見聞きするときはもっと注意深く!」と人に言うだけでは、
逆効果になりかねないということです。
コストが利益を上回る危険性があります。
というか、まず確実に上回るでしょう。
そして現在の人工知能の研究がぶち当たっている壁と同じものに
行く先を阻まれることになるのです。
そうなれば忠告された人は、
なんだか上手くいっていないことに本能的に気付き
(おそらくこの機能は「飽きる」という感情によって実装されています)、
やがてやめてしまうでしょう。

ただ単に「見聞きしたものを疑え」というだけでは上手くいかないはずです。
ここには人間の能力の限界があるのかもしれないのです。

拍手[0回]


Java OpenGL(JOGL)インストール

Javaで3Dをやる手段の一つにJava OpenGL(JOGL)があります。
先日インストールしたので方法をメモしておきます。

インストールはここ(joglのサイト)から

ページの下の方にCurrently nightly buildというのがあり、そこにいろんなプラットフォーム用のファイルがあるのでそこから適切なやつをダウンロードします。
普通のWindowsなら
"jogl-*.*.*-pre-********-windows-i586.zip"
というやつでいいでしょう。

展開すると中にlibディレクトリがあり、dllやjarファイルが入っています。

gluegen-rt.dll,
 jogl.dll,
 jogl_awt.dll,
 jogl_cg.dll,

 gluegen-rt.jar, 
jogl.jar

dllファイルをJavaのbinディレクトリに、
jarファイルをlib\extディレクトリの中に入れるとインストールは完了するようです。

拍手[3回]