忍者ブログ

Memeplexes

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

[PR]

×

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


植物 vs 動物 かんたんシミュレーション(ロトカ=ヴォルテラ方程式の解っぽい)

植物 vs 動物

植物と動物の簡単なシミュレーションを作ってみました。
緑が植物、赤が動物です。

シミュレーション画面をクリックすると一時停止、もう一度クリックすると再開します。


植物も動物も自分から動きまわることはせず、ぶつかり合うだけですが、それで十分です。
ぶつかったとき、捕食が起きます。
動物が植物からエネルギーを吸い取るのです。
動物と動物、植物と植物では何も起きません。
なお、エネルギーが空になった個体は消滅します。
ちなみに植物は何も起きなくともエネルギーを得ることができます。

さて、このシミュレーションを動かすと、動物と植物の数が増減を繰り返します。
これはロトカ=ヴォルテラの方程式の解にそっくりですね。
つまり、
植物が増えると、動物が増え、
動物が増えると、植物が減り、
植物が減ると動物が減り
動物が減ると植物が増える
をくりかえすのです。

パラメーターには次のようなものがあります:
  • Reproduction Cost : 繁殖すると失われるエネルギー(ただしそのあとさらにエネルギーの半分が子に奪われる)
  • Reproduction Threashold : 繁殖するのに必要なエネルギー。これだけエネルギーを持っていないと繁殖しない。別に繁殖するとこれが失われるわけではない。というのがReproduction Costとのちがい。
  • Plant Energy Supply : 植物に1フレーム間に与えられるエネルギー。
  • Animal Energy Consumption : 動物が1フレーム間に失うエネルギー。
  • Animal Energy Drain : 動物が植物と接触したときに吸い取るエネルギー。

おまけ
プロジェクトファイルです。

















拍手[0回]

PR


XNA4.0 複数のメッシュを一度のDrawで描画(ハードウェア・インスタンシング)

以前のこの記事のプログラムを、XNA4.0用に書きかえてみました。
たくさんの同じモデルを表示するときに役に立つ、ハードウェアインスタンシングです。

HardwareInstancing.fx
struct VertexPositionColor
{
	float4 Position : POSITION0;
	float4 Color : COLOR;
};

VertexPositionColor MyVertexShader(
	VertexPositionColor input,
	float3 position : POSITION1
	)
{
	input.Position.xyz += position;
	return input;
}

float4 MyPixelShader(float4 color : COLOR) : COLOR0
{
	return color;
}

technique HardwareInstancing
{
	pass Pass1
	{
		VertexShader = compile vs_3_0 MyVertexShader();
		PixelShader = compile ps_3_0 MyPixelShader();
	}
}




MyGame.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;



class MyGame : Game
{
    VertexPositionColor[] vertices = new VertexPositionColor[]{
        new VertexPositionColor(new Vector3(-0.1f, 0.1f, 0), Color.Blue),
        new VertexPositionColor(new Vector3(0.1f, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, -0.1f, 0), Color.Red)
    };

    Vector3[] instances = new Vector3[] {
        new Vector3(),
        new Vector3(0.1f, 0.1f, 0),
        new Vector3(0.2f, 0.2f, 0)
    };


    //Graphics Device Objects
    Effect effect;
    VertexBuffer triangleVertexBuffer;
    IndexBuffer indexBuffer;
    DynamicVertexBuffer instanceVertexBuffer;

    public MyGame()
    {
        new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void LoadContent()
    {
        effect = Content.Load<Effect>("HardwareInstancing");

        triangleVertexBuffer = new VertexBuffer(
            GraphicsDevice,
            VertexPositionColor.VertexDeclaration,
            vertices.Length,
            BufferUsage.WriteOnly
            );
        triangleVertexBuffer.SetData<VertexPositionColor>(vertices);


        var index = new int[] { 0, 1, 2 };
        indexBuffer = new IndexBuffer(
            GraphicsDevice,
            IndexElementSize.ThirtyTwoBits,
            index.Length, 
            BufferUsage.WriteOnly
            );
        indexBuffer.SetData<int>(index);


        instanceVertexBuffer = new DynamicVertexBuffer(
            GraphicsDevice, 
            new VertexDeclaration(
                new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 1)
            ),
            instances.Length,
            BufferUsage.WriteOnly);

        instanceVertexBuffer.SetData(instances);
    }

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

        GraphicsDevice.SetVertexBuffers(
            new VertexBufferBinding(triangleVertexBuffer, 0, 0),
            new VertexBufferBinding(instanceVertexBuffer, 0, 1)
            );
        GraphicsDevice.Indices = indexBuffer;

        instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);

        foreach (var pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();

            GraphicsDevice.DrawInstancedPrimitives(
                PrimitiveType.TriangleList,
                0,
                0,
                vertices.Length, 
                0,
                vertices.Length / 3,
                instances.Length
                );
        }
    }
}

xna4.0HardwareInstancing.jpg

拍手[1回]


XNAアプリケーションが0x4000001fを出して終了する問題(The program '~~: Managed (v4.0.30319)' has exited with code 1073741855 (0x4000001f).)

XNAアプリケーションをVisual Studio 2012で作っていた所、不可解な問題に直面しました。
いきなりアプリケーションが終了するのです。
しかも例外が発生していないようです。
F5を押して動かしているのに例外の場所に飛ばないのです。

出力をみてみると、

The program '[12012] ~~.vshost.exe: Managed (v4.0.30319)' has exited with code 1073741855 (0x4000001f).

とあります。

わけがわかりません。
検索してみたところWin32 x86エミュレーションサブシステムで使われる何かの例外のステータスコードのようですが…

結局2010で同じコードを書いたら動きました。
何だったのでしょう…??

拍手[1回]


タイムマシンの正しい使い方・および宇宙の物理法則の書き換え方

はじめに

この記事は4月1日用の記事だったのですが、早めに公開します。
エイプリルフール用と言っても、私は大真面目でこれを書いています。
実際のところこれの実現可能性は塵理論に匹敵するはずです!

この記事のテーマはタイムマシンです。
タイムマシンの手に入れ方とその効率的な運用方法についてです。

「タイムマシンなんてどうやって作るの?
ワームホールを使うの?
でもどうやってワームホールを作るのさ?」
と思われる方もいるでしょう。
いえいえ、タイムマシンを使うのにタイムマシンを作る必要はないのです。
すでに多くの人に知られているように、「未来からタイムマシンを現在に送ってもらう」という方法があるのです。
この記事ではそれを実際に行うにための具体的方法を紹介します。

「タイムマシンの正しい使い方?
そんなの過去を変えて好き勝手に歴史を書き換えることに決まってるじゃん!」

と思われる方もいるでしょう。
すでに知られているように、タイムマシンで単純に過去を変えることは難しいのです。
過去に戻って、少年時代の自分のおじいさんを殺すとどうなるでしょう?
答えは「そもそも殺せない。殺せないからこそ今の自分がいる」です。
このため過去を変えて現在の状態を変えることは一見不可能のように見えます。
しかしそれにもかかわらず、歴史の改ざんと同じ事をすることは十分に可能です。
バック・トゥ・ザ・フューチャー1のマーティーがそれ(ドクを死から救った)を行なっているではありませんか!
しかしこのマーティー方式は限界があるのです。
この記事ではより強力で一般的な方法を紹介します。

そして最後にタイムマシンを用いて、宇宙の物理法則を書き換える方法を示したいと想います。
上記2つはよく知られている方法の改良ですが、この方法はあまり知られていないでしょう。
イメージとしてはグレッグ・イーガンのSF小説、ルミナスに似ているかも知れません。
物理法則は検証され真であった時に初めて…というわけです。
別の見方をすれば、タイムマシンを応用して自分のいる宇宙を他の自分にとって都合のいい宇宙に接続するのです。

では見て行きましょう!

タイムマシンの正しい手に入れ方

みなさんは子供の頃こんな事を思ったありませんか?
「未来から猫型ロボットがやってきてぼくをたすけてくれないかな・・・。
そうだ!
来てくれるなら明日がいい!
明日の日付をいつまでも覚えておいて、自分の子供、孫、子々孫々にも覚えてもらっておくんだ!
そしていつかタイムマシンが技術的に可能になったときにその日付に猫型ロボットと一緒に送ってもらえばいいんだ!」

しかし次の日になっても猫型ロボットはやって来ません。
大人になるにつれこんな妄想はしなくなるものです。

しかしこの願いはもう少しまじめに考えてみる必要があるでしょう。
実のところこの願いはそれなりに成就する可能性が高いのです。
なんといっても子々孫々がきちんとあなたの思い描いたとおりに行動してくれていれば、この宇宙が個人所有のタイムマシンの存在を許す限り、間違いなく明日タイムマシンが送られてくるからです。

しかしではなぜタイムマシンが来なかったのでしょう?

  1. そもそもタイムマシンは実現不可能だった。
  2. 「明日の日付」を誰かが伝え忘れた。あるいは子孫が途絶えた。
  3. 未来人にとってタイムマシンを過去に送るのが面倒だったから。惜しくなったから。金銭的問題。法的問題。等々。


これくらいでしょう。
まず1に関してはもうどうしようもありません。
深刻な問題ですが、考えるだけ無駄です。

問題は2と3です。
特に2番は実に有り得そうな話です。
上のような決心をした人が「明日の日付」を今も覚えているかというとそうではないでしょう。
上で「ああ、確かにこんな事子供時代、眠る前にベッドの上で思い描いたことあるよ」と思った人も、自分が「いつ」思い描いたのか正確に覚えてはいないでしょう。
たいてい、たかだか数日覚えていて、その後それを忘れるといった感じではないでしょうか。
つまり子孫に伝えるどころか自分が生きている段階ですら、「明日の日付」は忘れられてしまいそうだということです。
当事者である自分が覚えられないのに、直接関係ない子孫に覚えていられるわけがありません。
仮に何かに日付を記録したとしても、数世代後にはくだらないジョークとして処理されることでしょう。
これが問題点の一つです。

3はどうでしょう?
一見有り得そうです。
たとえばタイムマシンを作るのにどれほどの費用がかかるでしょうか?
もしかするとアポロ計画並の金額が必要になるかもしれません。
そして誰が、誉れあるアームストロングの役割を何処の馬の骨ともしれない過去の凡人に与えようとするでしょうか?
しかしよく考えるとこれはあまり問題でないということがわかります。
タイムマシンに高額な費用がかかる段階でにこれを行う必要はないのです。
もっと技術が進み、タイムマシンが自家用車ほどの価格に下がった時に過去に送ればいいのです。

もっとも、タイムマシンが一般に普及しないという可能性もあります。
昔の人は原子力自動車なるものを夢想しました。
しかし今の価値観ではこれは現実的でないということになっていると思います。
個人所有の原子炉が現実的でないのなら個人所有のタイムマシンも現実的でないという未来はありえそうです。
国や国連がタイムマシンを管理していて、あなたの子孫が独断であなたへのプレゼントにタイムマシンを送るなんてことが不可能なのかも知れません。

さて2と3を一緒に解決する方法はたしかにあります。
それはカルト宗教です。
カルト宗教と聞いて身構える方もいらっしゃるでしょう。
しかしどんな宗教だって初めはカルトみたいなものです。
タイムマシンを入手するという崇高な目的のためならカルトを利用することにためらいを感じていてはいけません。

タイムマシンが手に入ったら「約束の日」へとタイムマシンを送るということにします。
そうすれば見返りに自分は天国へと導かれることにするのです(そこら辺の見返りは適当で構いません)。
そしてカルトを始めた世代の人達は、カルトを信じる見返りとしてタイムマシンの使用権を得るのです(順番で揉める必要はありません。タイムマシンのいいところの一つは同じ時代に複数存在できるという点です)。
このカルトを信じる人達は、自分たちの周りの人にこのタイムマシン信仰を広めます。
そして信者の数が一定数を超えた時、タイムマシンが未来から送られてくるという未来が確定するのです!

大切なのは信者の数と信仰心です。
なぜなら信者の数が増え、信仰心が篤くなるほど、未来でタイムマシンが過去に送られる可能性が高くなるからです。
信者が一人ならば、子供が寝る前にベッドでする決心と変わりません。
未来で「へえーこんな事考えたご先祖様もいたんだ。でもまぁご先祖様なんてたくさんいるしその一人に特別に送ってあげる義理なんて無いしねぇ~」と思われてしまうでしょう。
しかし信者数≒世界人口、信仰心MAXとなったら?
完全に思考は統制され過去にタイムマシンを送るということに疑問を持つことは許されなくなるでしょう。
途中で「タイムマシンを約束の日に送る」という使命が忘れられることもなく、国家や世界レベルでタイムマシンを過去に送るプロジェクトが進むでしょう。

(実際には信者の数が世界人口と等しくなる必要はないでしょう。
どこかに閾値が存在するはずです(7割か8割か…先進国での信者の割合も重要でしょう)。
ともかく、タイムマシンを手に入れるためには、たくさんのタイムマシン教の信者が必要なのです!!)

さて問題は「約束の日」をいつにするのかということです。
あまり近すぎてはいけません。
タイムマシン教の信者がたくさん確保できた後が望ましいのです。
信者の数が一人しかいない状態で「約束の日は明日です」といってもタイムマシン召喚に失敗するでしょう。

私はタイムマシン召喚の日=約束の日として2045年を提案します。(日と言ってるのに年じゃないか!というツッコミがきそうです。とりあえず1月1日くらいにしておきましょう)
2045年はある人達によれば、コンピュータと人間が融合し、人間が不老不死を手に入れる時です!!
技術的特異点(シンギュラリティ)というやつですね。
本来2045年とタイムマシンには直接的な関係は何らないのですが、嬉しいことは一度に来たほうがわかりやすいですからね。
というか、タイムマシンを送る側からすれば、タイムマシンを送る先の時間はわかりやすいほうがいいのです。
時代と時代の節目となるかもしれない2045年にするのは、理にかなったことです。

2045年は激動の年になるでしょう。
2045年に、全てのタイムマシン教の信者にタイムマシンが与えられるのです。
どうでしょう、あなたもタイムマシン教信者になってみたいと思いませんか!!!?

正しい過去の変え方

ここまではタイムマシンの手に入れ方を解説しました。
ここからはタイムマシンを使ってどのようにして過去を変えるかを解説します。

タイムマシンで過去を変える物語はたくさんあります。
しかし実のところ過去の改変はそんなに簡単ではありません。
というか、正攻法では不可能です。

たとえばタイムマシンを使って「テロリストに撃たれたドクを救おう」としたとします。
どうなるでしょうか?
答えは
「いずれにせよ撃たれる。
なぜなら撃たれなければそもそも「救おう」と思うことすらしないから。
救おうと考えている時点ですでに撃たれることは決定している。」
です。
したがって親殺しのパラドックスというのは実はそもそも起きないのです。
過去は変えられません。
宇宙が過去改変を禁じているのです。
ロックされているのです。

しかし過去を変えるのと事実上同じ事をすることはできます。
ドクに警告して防弾チョッキを着せればいいのです。
そうすれば一見ドクは撃たれて死んだように見えます。
マーティーはそれを受けて過去でドクに置き手紙を残します。
ドクはテープで破った手紙を貼り付け、防弾チョッキを着ることになるでしょう。
ドクは過去に戻る前のマーティーにとっては死んでいる(ように見える)のですが、過去に戻った後のマーティーにとっては死んでいないのです。

これは素晴らしいことです。
過去を変えても親殺しのパラドックスなど起きません!
要は過去に戻る前の自分自身を騙せばいいのです。
しかし・・・もしドクが殺された時に頭がふっとばされたりしていたらどうでしょうか?
マーティーがどんな手紙を出していても、ドクを救えないでしょう。

ではもう少しパワフルな方法を考えます。
ドクの体が粉微塵になっていたとしても救える方法です。
そのために「騙す」とはどういうことか考えてみましょう。

騙すとは、「事実と異なった記憶を持たせる」、ということだというふうに考えましょう。
記憶・・・記憶?
そうです。
過去の改竄は記憶の改竄から始まるのです。

次のような方法で過去の改竄は可能です。
「まずタイムマシンで一万年後に飛び記憶の改竄装置を手に入れる。
その後タイムマシンでドクが撃たれる前の自分を拉致し、「ドクが撃ち殺された」記憶を植えこむ。
その後ドクを殺しに来る前のテロリストの車に爆弾を仕込んで皆殺しにする。
ドクは殺されなかったが、ドクが撃ち殺されたと思い込んだ過去の自分はタイムマシンでドクを救う旅にでる。
Happy End!!」

そうです。
この方法を使えばいかなる規模の過去の改変も可能です。
たとえドクが体をバラバラにふっとばされていたとしても、そういう記憶を過去の自分にインストールするだけで、この宇宙は過去改変がアンロックされた状態になります。
やりたい放題になるのです。
ようは自分が生きてきた宇宙を偽りのものにするだけでいいのです。
これからあなたが生きる宇宙はあなたが創造するのです。

正しい物理法則の書き換え方

ここまではタイムマシンの手に入れ方、過去の改変の仕方を解説しました。
ここでは宇宙の物理法則を書き換える方法を示したいと思います。

といってもこれは「過去の改竄の仕方」の応用のようなものです。
過去を改ざんする要領で物理法則を改ざんしていきます。

たとえば恒星間宇宙旅行をしたいため、光速の壁を破りたいとします。
しかしそれは相対性理論によって禁じられています。
残念です。
そこで空中にへのへのもへじを描くと(実際にはもう少し低レベルの、簡単には起こり得ない条件にしたほうがいいでしょう)半径100m以内で光速の壁を破れるということにしましょう。
タイムマシンを使ってこのような物理法則をこの宇宙に固定させるにはどうすればいいでしょうか?

まず私たちの知っている物理法則をもつ宇宙を、改ざんされた物理法則を持つ宇宙に接続します。
何を言っているのか意味不明ですが、こういうことです。
「光速の壁を破れない」という物理法則を導き出すありとあらゆる実験の結果を全て「正しい過去の改変の仕方」によってウソにします。
これで相対性理論は無効になりました。
でもそのままだと私たちの世界に支障が出そうです。
そこである条件でのみ光速の壁を破れるという法則を作ることにします。
具体的には「ある条件でのみ光速の壁を破れる」かどうかをチェックする実験を行います。
もしその結果が真ならそのまま。
もし結果が偽であったなら、その実験結果を「正しい過去の改変の仕方」によってウソにします。
これを何回も行うと、私達がデザインした物理法則が宇宙に定着します。

(この話を聞いてノーベル賞受賞者ミリカンの話を持ちだして反論したくなる方もいらっしゃるでしょう。
ミリカンは実験で好きな実験結果を選択して答えを導き出しました。(この言い方は少し語弊があります。実際にはミリカンはほんの少し選択しただけです)
結果として正しい答えは導けたのですが、別にミリカンが物理法則を創りだしたわけではありません。
「この「正しい物理法則の書き換え方」もミリカンの方法と同じでように、物理法則を新たに作り出すわけではないのでは?」という疑念はもっともなものです。
しかし違います。
実際にはこの2つは違うのです。
「正しい物理法則の書き換え方」では、自分の求めたい物理法則に違反するようなものを「無視する」のではなく、「なかったことにしてしまう」のです。)

ここでは光速の壁を破るよう物理法則を書き換えましたが、実際にはいかなる物理法則も書き換え可能だということがわかると思います。
そうです。
あなたは神になれるのです!!

おわりに

この記事ではタイムマシンの正しい使い方について述べました。

タイムマシンを手に入れるためには未来からタイムマシンを送ってもらいます。
子孫に「タイムマシンが完成したら約束の日に送ってね」と伝えるのです。
そのために全人類が一丸となってタイムマシン教を始めましょう。
メッセージを確実に子孫に伝えるのです。

タイムマシンで過去を改変するのは一筋縄では行きません。
過去は変えられないからです。
変えようと思っても確実に失敗します。
しかし過去を変えたのと同じ結果を出すことはできます。
消したい過去の記憶をそれ以前の過去の自分に植え付けると、自由自在に過去を決めることができます。

タイムマシンを利用すると宇宙の物理法則を書き換えることもできます。
物理法則は実験から決まります(語弊がありますが)。
お好みの物理法則を導き出す実験のみ本当に起きたことにしてしまえばいいのです。
あなたは物理法則を作り出せます。

タイムマシン教を作れば、あなたは神になれるということがわかると思います。
タイムマシン教信者の間で誰が神になるかいい争う必要はありません。
実のところ宇宙をたくさん作りそれぞれの宇宙でそれぞれが神になることが出来るのです。
さあ、あなたもタイムマシン教の信者になってみませんか!!?

拍手[7回]