<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>ひにけにXNA : XNA フレームワーク</title><link>http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx</link><description>Tags: XNA フレームワーク</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>XNA Game Studio 3.1のSoundEffect変更点</title><link>http://blogs.msdn.com/ito/archive/2009/06/30/soundeffect-3-1.aspx</link><pubDate>Wed, 01 Jul 2009 02:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9810143</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ito/comments/9810143.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9810143</wfw:commentRss><description>&lt;H3&gt;XNA Game Studio 3.1のSoundEffect&lt;/H3&gt;
&lt;P&gt;ゲームで使用する効果音を簡単に再生するためにXNA Game Studio 3.0で導入されたSoundEffect機能がありますが、この機能は以下の二つのシナリオを実現するようにデザインされました。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;簡易再生(Fire &amp;amp; forget)&lt;/STRONG&gt;: プログラムは単にPlayメソッドを呼ぶだけ。後は効果音が鳴り終わった後に自動的にメモリ開放処理をしてくれる機能&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;生成と設定(Create &amp;amp; configure):&lt;/STRONG&gt; 効果音を鳴らしている間に、音量、再生ピッチ、パンなどのさまざまなパラメーターを自由に設定できる機能。細かい設定ができる代わりに、プログラム側で再生中のインスタンスの保持、管理をする必要がある&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;この二つのシナリオを実現する為に、XNA GS 3.0では&lt;STRONG&gt;SoundEffect.Play&lt;/STRONG&gt;、&lt;STRONG&gt;SoundEffect.Play3D&lt;/STRONG&gt;メソッドは&lt;STRONG&gt;SoundEffectInstance&lt;/STRONG&gt;オブジェクトを返すようになっていました。再生中に設定を変更したい場合は、このインスタンスに対して処理をします。簡易再生させたい場合はインスタンスを保持しないでおきます。この場合、次にガーベージコレクション(GC)が発生した時に再生が終了したインスタンスを破棄するようになっていました。&lt;/P&gt;
&lt;P&gt;この方法には以下の二つの問題がありました。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Play/Play3Dメソッドには、プログラムが簡易再生をしたいのか、細かい設定をしたいのかを知る術がないので常にSoundEffectInstanceを生成していました。これは簡易再生をしている場合に常に不必要なメモリ確保が起きていることになります。&lt;/LI&gt;
&lt;LI&gt;確保されたSoundEffectInstanceはGCが発生された時に再生が終了しているインスタンスを自動的に破棄されるようになっています。GCがいつ発生するかはゲームがどのようにメモリを確保するかによって左右されます。GCの不必要な発生はゲームのパフォーマンスに影響するので、極力GC発生を抑えるようにプログラミングするのが望ましいのですが、GC発生数が少ないと、SoundEffectinstanceを開放する機会が減るのことになるので、最終的には同時再生できる効果音の上限に達してしまいます。&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;XNA GS 3.1では、この二つのシナリオを明確に分けることで、この問題を解決しました。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;SoundEffect.Playメソッドは簡易再生専用のメソッドとなり、SoundEffectInstanceではなく、bool値を返すようになりました。このbool値は単純に再生が成功したかを示します。これで不必要なメモリ確保がなくなりました。また、このメソッドを使った場合はループ再生ができないようになっています。&lt;/LI&gt;
&lt;LI&gt;生成と設定のシナリオ用に&lt;STRONG&gt;SoundEffect.CreateInstance&lt;/STRONG&gt;メソッドが追加されました。このメソッドはSoundEffectInstanceを返すので、このオブジェクトを介して音量、ピッチ、パンなどを設定することができます。&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;SoundEffect.Play3Dメソッドは無くなりました。3Dサウンドを再生する場合は、SoundEffect.CreateInsntaceメソッドを使い、&lt;STRONG&gt;SoundEffectInstance.Apply3D&lt;/STRONG&gt;メソッドを使用します。3Dサウンドは簡易再生することができません。&lt;/P&gt;
&lt;P&gt;また、XNA GS 3.0では再生数が上限に達したときに更に効果音を再生しようとするとInstancedPlayLimitException例外が発生しました。XNA GS 3.1でもCreateInstanceメソッドを使った場合には同じように例外が発生しますが、簡易再生の場合は例外を発生せずに単にbool値を返すようになっています。ですから、簡易再生時にいちいちtry～catchブロックを書く必要がなくなりました。&lt;/P&gt;
&lt;P&gt;原文: &lt;BR&gt;&lt;A title=http://blogs.msdn.com/shawnhar/archive/2009/06/12/soundeffect-changes-in-xna-game-studio-3-1.aspx href="http://blogs.msdn.com/shawnhar/archive/2009/06/12/soundeffect-changes-in-xna-game-studio-3-1.aspx" mce_href="http://blogs.msdn.com/shawnhar/archive/2009/06/12/soundeffect-changes-in-xna-game-studio-3-1.aspx"&gt;http://blogs.msdn.com/shawnhar/archive/2009/06/12/soundeffect-changes-in-xna-game-studio-3-1.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9810143" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category><category domain="http://blogs.msdn.com/ito/archive/tags/_AA30FC30C730A330AA30_/default.aspx">オーディオ</category></item><item><title>アバターを使おう その３:喜怒哀楽</title><link>http://blogs.msdn.com/ito/archive/2009/06/29/avatar-3.aspx</link><pubDate>Tue, 30 Jun 2009 09:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9809327</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ito/comments/9809327.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9809327</wfw:commentRss><description>&lt;P&gt;警告:画像が沢山あるので、重いかも。&lt;/P&gt;
&lt;H3&gt;アバターの表情(Expression)を自由に設定する&lt;/H3&gt;
&lt;P&gt;AvatarRenderer.Drawメソッドにはアバターのボーンと表情を指定することができます。基本アニメーションを使っている場合はAvatarAnimation.Expressionを指定しますが、ボーンと同じく、AvatarExpressionも自由に作ることができるので、アバターの表情を自由に変えることができます。&lt;/P&gt;
&lt;P&gt;AvatarExpressionには以下のプロパティがあります。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;LeftEye (左目) &lt;/LI&gt;
&lt;LI&gt;LeftEyebrow (左眉) &lt;/LI&gt;
&lt;LI&gt;Mouth (口) &lt;/LI&gt;
&lt;LI&gt;RightEye (右目) &lt;/LI&gt;
&lt;LI&gt;RightEyebrow (右眉) &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;LeftEye、RightEyeにはAvatarEye列挙型、LeftEyebrow、RightEyebrowにはAvatarEyebrow列挙型、MouthにはAvatarMouth列挙型を設定することができます。&lt;/P&gt;
&lt;P&gt;左右の目や眉に独立した値を設定できるので、ウィンクさせるといったことも可能です。眉と目、そして口のパターンと合わせると約６万９千通りの表情を設定することができます。これだけの数があるので、喜怒哀楽といった基本的な表情の他にも多彩な表情を表現することができるようになっています。&lt;/P&gt;
&lt;P&gt;以下はそれぞれの列挙型の値と、その説明です。&lt;/P&gt;
&lt;H3&gt;AvatarEyebrow列挙型&lt;/H3&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=400&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;
&lt;P align=center&gt;値&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;
&lt;P align=center&gt;説明&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;Angry&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;怒り、眉を吊り上げる&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;Confused&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;困惑、眉を曲げる&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;Neutral&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;自然な眉のかたち&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;Raised&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;眉をあげる。驚いたときなどに使える&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=81&gt;Sad&lt;/TD&gt;
&lt;TD vAlign=top width=319&gt;悲しみ、眉がさがる。眠たい表情にも使える&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H3&gt;AvatarEye列挙型&lt;/H3&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=477&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;
&lt;P align=center&gt;値&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;
&lt;P align=center&gt;説明&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Angry&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;怒り、目がつりあがっている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Blink&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;まばたき、目を閉じている状態&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Confused&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;困惑、より目、または見上げている感じ&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Happy&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;ハッピー、目が大きくひらき、目尻が下がっている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Laughing&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;笑い、目を細めている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;LookDown&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;下を見る&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;LookLeft&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;左を見る&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;LookRight&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;右を見る&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;LookUp&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;上を見る&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Neutral&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;自然な目の形&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Sad&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;悲しみ、目尻が下がる&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Shocked&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;驚き、目が点になる&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Sleeping&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;眠り、目を閉じている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=100&gt;Yawning&lt;/TD&gt;
&lt;TD vAlign=top width=375&gt;あくび、眠そうな目&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H3&gt;AvatarMouth列挙型&lt;/H3&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=651&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;
&lt;P align=center&gt;値&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;
&lt;P align=center&gt;説明&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Angry&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;怒り、歯をくいしばってる感じ&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Confused&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;困惑、口がゆがめている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Happy&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;ハッピー、口の両端が上がっている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Laughing&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;笑い&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Neutral&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;自然体、すこし口が開いている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticAi&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のAの発音、日本語の「あ」と「え」の中間&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticDth&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のDまたはThの発音、唇を歯で軽く噛んで発音、日本語では使われない&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticEe&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のEの発音、日本語では「い」の発音&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticFv&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のF、Vの発音、下唇を噛んで発音、日本語では使われない&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticL&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のLの発音、舌のを歯のうらに当てて発音、日本語の「れ」に近い&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticO&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のOの発音、日本語では「お」の発音&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;PhoneticW&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;リップシンク用、英語のWの最後の部分の発音、日本語では「う」の発音&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Sad&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;悲しみ、口の両端が下がっている&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Shocked&lt;/TD&gt;
&lt;TD vAlign=top width=542&gt;驚き、「あ」と口をあけて驚いている&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H3&gt;百聞は１スクショにすぎず&lt;/H3&gt;
&lt;P&gt;前回の基本アニメーションと同じく、男性、女性アバターにいろいろな表情を設定したものを画像にしてみました。&lt;/P&gt;
&lt;P&gt;まずは、眉、目、口で共通するものが多い表情パターンです。&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=536&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=282&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-72_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-72_2.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=myxbox-72 border=0 alt=myxbox-72 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-72_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-72_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;自然な表情(Neutral) &lt;BR&gt;&lt;/STRONG&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Neutral &lt;BR&gt;Mouth.Neutral&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=252&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-74_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-74_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-74 border=0 alt=myxbox-74 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-74_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-74_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;怒り(Angry)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Angry &lt;BR&gt;Eye.Angry &lt;BR&gt;Mouth.Angry&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=282&gt;
&lt;P align=center mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-75_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-75_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-75 border=0 alt=myxbox-75 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-75_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-75_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P align=center&gt;&lt;STRONG&gt;困惑(Confused)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Confused &lt;BR&gt;Eye.Confused &lt;BR&gt;Mouth.Confused&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=252&gt;
&lt;P align=center&gt;&lt;STRONG&gt;&lt;STRONG&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-76_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-76_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-76 border=0 alt=myxbox-76 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-76_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-76_thumb.png"&gt;&lt;/A&gt;&lt;/STRONG&gt;笑い(Laughing) &lt;BR&gt;&lt;/STRONG&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Laughing &lt;BR&gt;Mouth.Laughing&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=282&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-78_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-78_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-78 border=0 alt=myxbox-78 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-78_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-78_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center&gt;&lt;STRONG&gt;ハッピー(Happy)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Happy &lt;BR&gt;Mouth.Happy&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=252&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-73_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-73_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-73 border=0 alt=myxbox-73 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-73_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-73_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center&gt;&lt;STRONG&gt;悲しみ(Sad)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Sad &lt;BR&gt;Eye.Sad &lt;BR&gt;Mouth.Sad &lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=282&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-77_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-77_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-77 border=0 alt=myxbox-77 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-77_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-77_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P align=center&gt;&lt;STRONG&gt;驚き(Shocked)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Raised &lt;BR&gt;Eye.Shocked &lt;BR&gt;Mouth.Shocked&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=252&gt;
&lt;P align=center mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;つづいて、目特有の表情パターンです。上下左右を見るというパターンがあるので、画面内の物を目で追うといったこともできます。&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=541&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=278&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-85_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-85_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-85 border=0 alt=myxbox-85 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-85_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-85_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;まばたき(Blink)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Blink &lt;BR&gt;Mouth.Neutral &lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=261&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-79_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-79_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-79 border=0 alt=myxbox-79 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-79_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-79_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P align=center&gt;&lt;STRONG&gt;あくび(Yawning)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Yawning &lt;BR&gt;Mouth.Shocked&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=278&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-80_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-80_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-80 border=0 alt=myxbox-80 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-80_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-80_thumb.png"&gt;&lt;/A&gt; &lt;BR&gt;&lt;STRONG&gt;ねむり(Sleeping)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.Sleeping &lt;BR&gt;Mouth.Happy&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=261&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-81_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-81_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-81 border=0 alt=myxbox-81 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-81_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-81_thumb.png"&gt;&lt;/A&gt; &lt;BR&gt;&lt;STRONG&gt;上を見る(LookUp)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.LookUp &lt;BR&gt;Mouth.Neutral&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=278&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-82_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-82_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-82 border=0 alt=myxbox-82 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-82_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-82_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;BR&gt;下を見る(LookDown)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.LookDown &lt;BR&gt;Mouth.Neutral&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=261&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-83_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-83_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-83 border=0 alt=myxbox-83 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-83_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-83_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;左を見る(LookLeft)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.LookLeft &lt;BR&gt;Mouth.Neutral&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=278&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-84_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-84_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-84 border=0 alt=myxbox-84 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-84_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-84_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;BR&gt;右を見る(LookRight)&lt;/STRONG&gt; &lt;BR&gt;Eyebrow.Neutral &lt;BR&gt;Eye.LookRight &lt;BR&gt;Mouth.Neutral&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=261&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;最後に口特有の表情パターンです。表情パターンというよりも、リップシンク用のデータです。プレイヤーが操る以外のアバターには自由に喋らせることができるので、その時に使うパターンです。&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=532&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=274&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-87 border=0 alt=myxbox-87 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_thumb.png"&gt;&lt;/A&gt; &lt;BR&gt;&lt;STRONG&gt;PhoneticAi&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=256&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-92_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-92_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-92 border=0 alt=myxbox-92 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-92_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-92_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;BR&gt;PhoneticDth&lt;/STRONG&gt; &lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=274&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-88 border=0 alt=myxbox-88 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_thumb.png"&gt;&lt;/A&gt; &lt;BR&gt;&lt;STRONG&gt;PhoneticEe&lt;/STRONG&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=256&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-89_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-89_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-89 border=0 alt=myxbox-89 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-89_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-89_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;BR&gt;PhoneticFv&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=274&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-86 border=0 alt=myxbox-86 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_thumb.png"&gt;&lt;/A&gt; &lt;BR&gt;&lt;STRONG&gt;PhoneticO&lt;/STRONG&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=256&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-91_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-91_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-91 border=0 alt=myxbox-91 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-91_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-91_thumb.png"&gt;&lt;/A&gt;&amp;nbsp; &lt;STRONG&gt;PhoneticL&lt;/STRONG&gt; &lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=274&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=myxbox-90 border=0 alt=myxbox-90 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_thumb.png"&gt;&lt;/A&gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&lt;STRONG&gt;PhoneticW&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=256&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;リップシンク用のデータはもともと欧米向けのデータなので、日本語を喋らせるときには近い口の形を流用することになります。以下は日本語で「あいうえお」の口の形に近いものを順に並べてみました。&lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=522&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=257&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-93_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-93_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-93 border=0 alt=myxbox-93 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-93_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-93_thumb.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;STRONG&gt;あ (Shocked)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=263&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-88 border=0 alt=myxbox-88 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-88_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;い (PhoneticEe)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=257&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-90 border=0 alt=myxbox-90 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-90_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;う (PhoneticW)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=263&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-87 border=0 alt=myxbox-87 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-87_thumb.png"&gt;&lt;/A&gt;&lt;STRONG&gt;え (PhoneticAi)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=257&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=myxbox-86 border=0 alt=myxbox-86 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_thumb.png" width=240 height=135 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/d2a7980504e7_13929/myxbox-86_thumb.png"&gt;&lt;/A&gt; 
&lt;P align=center&gt;&lt;STRONG&gt;お (PhoneticO)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=263&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9809327" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/Xbox360/default.aspx">Xbox360</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>アバターを使おう その2:基本アニメーション</title><link>http://blogs.msdn.com/ito/archive/2009/06/25/avatar-02.aspx</link><pubDate>Fri, 26 Jun 2009 04:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9804574</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ito/comments/9804574.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9804574</wfw:commentRss><description>&lt;H3&gt;アバターの基本アニメーション&lt;/H3&gt;
&lt;P&gt;AvatarAnimationを生成するときに指定する&lt;STRONG&gt;AvatarAnimationPreset&lt;/STRONG&gt;列挙型には31種類の基本アニメーションが宣言されています。内訳として、11種類の男女共通のアニメーションと、性別毎に違うアニメーションが10種類となっています。&lt;/P&gt;
&lt;P&gt;男性アバター向けのアニメーションはMaleで始まり、女性アバター向けのアニメーションはFemaleで始まるようになっています。通常はAvatarDescription.BodyTypeによって性別ごとにアニメーションを切り替えて使用しますが、アニメーションは性別に関係なく使えるので、意図的に男性アバターに女性アバターのアニメーションを再生させるということもできます。&lt;/P&gt;
&lt;H3&gt;男女共通のアニメーション&lt;/H3&gt;
&lt;P&gt;以下は男女共通アニメーション名と、その説明です。 &lt;/P&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=677&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;
&lt;P align=center&gt;アニメーション名&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;
&lt;P align=center&gt;説明&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand0&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;基本姿勢アニメーション、身体的アニメーションは殆どなく、瞬きする程度。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand1&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;基本姿勢アニメーションに加えて、数秒間軽く上を見上げる動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand2&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;基本姿勢アニメーションに加えて、左、上方向に顔を向ける動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand3&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;基本姿勢アニメーションに加えて、左右を見渡した後に軽く首をかしげる動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand4&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;軽く右足を上げて、つま先を見つめる。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand5&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;両手を広げて、前後に振る。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand6&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;足元を見回す動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Stand7&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;頭を左右に傾けた後に、首を回す動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Clap&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;笑顔で拍手する。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Wave&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;笑顔で手を振る。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Celebrate&lt;/TD&gt;
&lt;TD vAlign=top width=572&gt;喜びの動作。アバター生成画面でアバターを選択したときにするアニメーションと同じもの。&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H3&gt;性別によって違うアニメーション&lt;/H3&gt;
&lt;P&gt;以下は性別によって異なるアニメーションをまとめた表です。殆どのアニメーションはMaleLaugh、FemaleLaughといった感じで同じタイプのアニメーションが用意されています。例外としてはMaleIdleCheckHand,FemaleIdleCheckNails,MaleIdleStretch,FemaleIdelFixShoeの四つのアニメーションがあります。&lt;/P&gt;
&lt;P&gt;同じタイプのアニメーションでも、例えば笑うアニメーションの場合、男性はひざを叩いて笑う動作をするのに対して、女性は手を前にかざして笑うといった違いがあります。 &lt;/P&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=679&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;
&lt;P align=center&gt;男性用アニメーション名&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;
&lt;P align=center&gt;女性用アニメーション名&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;
&lt;P align=center&gt;説明&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleIdleCheckHand&lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleIdleCheckNails &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;男性は肩を軽くまわした後に自分の手を見つめる動作。 &lt;BR&gt;女性は爪を見つめる動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleIdleLookAround &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleIdleLookAround &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;あたりを見回す動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;FemaleIdleShiftWeight &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;MaleIdleShiftWeight &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;重心を左右の足に移動する動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleIdleStretch &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleIdleFixShoe&lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;男性はストレッチ動作、女性は靴の様子を見る動作。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleAngry &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleAngry &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;怒る。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleConfused &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleConfused &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;困惑。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleLaugh &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleLaugh &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;大笑い。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleCry &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleCry &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;泣く。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleSurprised &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleShocked &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;驚き。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=141&gt;MaleYawn &lt;/TD&gt;
&lt;TD vAlign=top width=156&gt;FemaleYawn &lt;/TD&gt;
&lt;TD vAlign=top width=380&gt;あくび。男性は手を口に当ててあくび。女性は手を広げてあくび。&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;百聞は一動画にしかずということで、全ての基本アニメーションを再生した動画を作ってみました。男性、女性アバターを並べて、それぞれのアニメーションを二回再生するようになっています。 &lt;/P&gt;
&lt;DIV align=center&gt;
&lt;OBJECT width=560 height=340&gt;&lt;PARAM NAME="movie" VALUE="http://www.youtube.com/v/gguyGGX_ls0&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;PARAM NAME="allowFullScreen" VALUE="true"&gt;&lt;PARAM NAME="allowscriptaccess" VALUE="always"&gt;
&lt;embed src="http://www.youtube.com/v/gguyGGX_ls0&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" mce_src="http://www.youtube.com/v/gguyGGX_ls0&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/OBJECT&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9804574" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/Xbox360/default.aspx">Xbox360</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B230FC30E0308B957A76_/default.aspx">ゲーム開発</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>アバターを使おう その1:アバターを表示する</title><link>http://blogs.msdn.com/ito/archive/2009/06/23/avatar-01.aspx</link><pubDate>Wed, 24 Jun 2009 05:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9800657</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9800657.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9800657</wfw:commentRss><description>&lt;H3&gt;アバターをゲーム画面内に表示する&lt;/H3&gt;
&lt;P&gt;アバターをゲームt画面内に表示するには以下の三つのクラスが重要な役割を果たします。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;AvatarDescription &lt;/LI&gt;
&lt;LI&gt;AvatarAnimation(必ずしも必要ではない) &lt;/LI&gt;
&lt;LI&gt;AvatarRenderer &lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;AvatarDescription&lt;/H3&gt;
&lt;P&gt;&lt;STRONG&gt;AvatarDescription&lt;/STRONG&gt;はアバターの性別、容姿、服装といった情報を保持しています。AvatarDescriptionのプロパティには男性(Male)、女性(Female)を表すBodyType、メートル単位の身長を表すHeightがあります。AvatarDescriptionを得るには以下の三つの方法があります。&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;SignedInGamer.Avatarからゲーマータグのアバター情報を取得する &lt;/LI&gt;
&lt;LI&gt;AvatarDescription.CreateRandomメソッドを使ってランダムにアバターを生成する &lt;/LI&gt;
&lt;LI&gt;AvatarDescription(byte[] data)コンストラクタを使って生成する &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;1はゲーマータグに関連付けられたらアバター情報をSignedInGamer.AvatarからAvatarDescriptionを取得して使う方法で、自分のアバターをゲーム内で使う方法です。&lt;/P&gt;
&lt;P&gt;2の手法は、自分のアバター以外をゲーム内で使ったり、複数の違った体形のアバターを自分のゲーム内で表示しても問題がないようにテスト目的として使う方法です。&lt;/P&gt;
&lt;P&gt;3の方法は、アバター情報をネットワークを介して転送する時に使用します。実際にはByte[]型である&lt;STRONG&gt;AvatarDesciprion.Description&lt;/STRONG&gt;プロパティの情報をネットワークを介して転送し、転送されたデータをAvatarDescription(byte[])コンストラクタに渡すことで同じアバターを生成することができます。&lt;/P&gt;
&lt;P&gt;また、2の方法ではランダムにアバターを生成しますが、ゲームの雰囲気にあったアバターを自由に作りたいという時があります。この場合、ダッシュボード上で仮のゲーマープロファイルを生成、好きなアバターを編集します。そして、作ったアバターでサインインした状態でXNA Game Studioを起動、デバッガ上で該当するアバターのAvatarDescription.Descriptionプロパティの値を保存しておくことで自分の好きなタイプのアバターをゲーム内で使うことができます。&lt;/P&gt;
&lt;H3&gt;AvatarAnimation&lt;/H3&gt;
&lt;P&gt;XNA GS 3.1ではアバター用に31種類のアニメーションが用意されています。このアニメーションを再生する為に使うのが&lt;STRONG&gt;AvatarAnimation&lt;/STRONG&gt;クラスです。AvatarAnimationクラスには現在のアニメーション再生位置、ボーン情報、表情(Expression)などの情報などが含まれます。AvatarAnimationクラスは&lt;STRONG&gt;AvatarAnimationPreset&lt;/STRONG&gt;列挙型を指定して生成、通常は&lt;STRONG&gt;AvatarAnimation.Update&lt;/STRONG&gt;メソッドを使用してアニメーション再生をすることができます。&lt;/P&gt;
&lt;P&gt;また、&lt;STRONG&gt;AvatarAnimation.CurrentPosition&lt;/STRONG&gt;プロパティは現在のアニメーション再生位置を取得することに使いますが、任意の再生位置を設定することで自由にアニメーションすることもできます。&lt;/P&gt;
&lt;H3&gt;AvatarRenderer&lt;/H3&gt;
&lt;P&gt;アバターをゲーム画面に描画するには&lt;STRONG&gt;AvatarRenderer&lt;/STRONG&gt;クラスを使用します。AvatarRendererクラスはBasicEffectクラスとや同じように描画するアバターのWorld、View、Projection行列や、環境光源(AmbientLightColor)や平行光源(LightDirection, LightColor)を指定することができます。BasicEffectと違うところは描画するときにアバターのボーン情報や表情を指定できることです。通常はAvatarAnimationの&lt;STRONG&gt;BoneTransforms&lt;/STRONG&gt;、&lt;STRONG&gt;Expresssion&lt;/STRONG&gt;プロパティを指定します。&lt;/P&gt;
&lt;P&gt;また、指定するボーン情報は&lt;STRONG&gt;IList&amp;lt;Matrix&amp;gt;&lt;/STRONG&gt;型なので、自分で作った自由なアニメーションを設定することができます。アバターのボーン数は71あり、これ以外の数のボーンを指定すると例外が発生することに気をつけてください。カスタムアニメーションサンプルは近日中にクリエーターズ・クラブのサイトで公開予定です。&lt;/P&gt;
&lt;H3&gt;サンプルコード&lt;/H3&gt;
&lt;P&gt;アバターはGamerServicesを利用するので、アバター機能を使うときにはGamerServiceComponentを追加するのを忘れないようにしましょう。忘れた場合はGamerService機能を初期化することを促す例外が発生します。&lt;/P&gt;&lt;PRE class=code&gt;Components.Add(&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;GamerServicesComponent&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;));&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;次にアバターを使うのに必要なオブジェクトを生成します。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// アバター情報をランダムに生成する
&lt;/SPAN&gt;avatarDescription = &lt;SPAN style="COLOR: #2b91af"&gt;AvatarDescription&lt;/SPAN&gt;.CreateRandom();

&lt;SPAN style="COLOR: green"&gt;// アバターアニメーションの生成
&lt;/SPAN&gt;avatarAnimation = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AvatarAnimation&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AvatarAnimationPreset&lt;/SPAN&gt;.Celebrate);

&lt;SPAN style="COLOR: green"&gt;// アバター描画用のオブジェクトの生成
&lt;/SPAN&gt;avatarRenderer = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AvatarRenderer&lt;/SPAN&gt;(avatarDescription);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;次にゲームのアップデート内でアニメーションを以下のようにして更新します。&lt;/P&gt;&lt;PRE class=code&gt;avatarAnimation.Update(gameTime.ElapsedGameTime, &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;);&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;最後にAvatarRendererにアバターを描画するのに必要な行列を設定し、ボーンと表情を指定することでアバターをゲーム画面内に描画することができます。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// アバター描画に必要な行列の設定
&lt;/SPAN&gt;avatarRenderer.World = &lt;SPAN style="COLOR: #2b91af"&gt;Matrix&lt;/SPAN&gt;.CreateRotationY(&lt;SPAN style="COLOR: #2b91af"&gt;MathHelper&lt;/SPAN&gt;.ToRadians(180.0f));
avatarRenderer.Projection = 
    &lt;SPAN style="COLOR: #2b91af"&gt;Matrix&lt;/SPAN&gt;.CreatePerspectiveFieldOfView(&lt;SPAN style="COLOR: #2b91af"&gt;MathHelper&lt;/SPAN&gt;.ToRadians(30.0f),
    GraphicsDevice.Viewport.AspectRatio,
    1, 1000);
avatarRenderer.View = &lt;SPAN style="COLOR: #2b91af"&gt;Matrix&lt;/SPAN&gt;.CreateLookAt(
    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Vector3&lt;/SPAN&gt;(0, 1, 4),
    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Vector3&lt;/SPAN&gt;(0, 0.7f, 0),
    &lt;SPAN style="COLOR: #2b91af"&gt;Vector3&lt;/SPAN&gt;.Up);

&lt;SPAN style="COLOR: green"&gt;// ボーンと表情を指定してアバターを描画する
&lt;/SPAN&gt;avatarRenderer.Draw(avatarAnimation.BoneTransforms, avatarAnimation.Expression);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;上記のコードを実行すると、以下のようにアバターが画面に表示されます。このコードではランダムにアバターを作っているので実行するたびに違うアバターが表示されます。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/avatar01_1159B/itoxe1-78_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/avatar01_1159B/itoxe1-78_2.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=itoxe1-78 border=0 alt=itoxe1-78 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/avatar01_1159B/itoxe1-78_thumb.png" width=644 height=364 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/avatar01_1159B/itoxe1-78_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;H3&gt;アバターを使う上での注意点&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;GamerServiceComponentを追加するのを忘れないこと &lt;/LI&gt;
&lt;LI&gt;現状でアバターはXbox 360上でのみ動作するようになっています。ただし、アバター関連のコードをWindows上で走らせても例外が発生することなく動作します。 &lt;/LI&gt;
&lt;LI&gt;ゲーム内で使用するときには、背の高いのから低いのまで、痩せ型から太り気味といったさまざまなタイプのアバターが存在居るということに気をつける必要があります。例えば、アバターを矩形内に表示させたい時に身長の低いアバター向けに調整してしまうと、背の高いアバターを表示させると頭の上が途切れてしまうという問題があります。 &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;参考URL:&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/dejohn/archive/2009/05/08/avatar-api-preview-for-xna-game-studio-3-1.aspx href="http://blogs.msdn.com/dejohn/archive/2009/05/08/avatar-api-preview-for-xna-game-studio-3-1.aspx" mce_href="http://blogs.msdn.com/dejohn/archive/2009/05/08/avatar-api-preview-for-xna-game-studio-3-1.aspx"&gt;http://blogs.msdn.com/dejohn/archive/2009/05/08/avatar-api-preview-for-xna-game-studio-3-1.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/dejohn/archive/2009/05/11/what-to-do-while-an-avatar-loads.aspx href="http://blogs.msdn.com/dejohn/archive/2009/05/11/what-to-do-while-an-avatar-loads.aspx" mce_href="http://blogs.msdn.com/dejohn/archive/2009/05/11/what-to-do-while-an-avatar-loads.aspx"&gt;http://blogs.msdn.com/dejohn/archive/2009/05/11/what-to-do-while-an-avatar-loads.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/dejohn/archive/2009/05/18/lights-camera-avatar.aspx href="http://blogs.msdn.com/dejohn/archive/2009/05/18/lights-camera-avatar.aspx" mce_href="http://blogs.msdn.com/dejohn/archive/2009/05/18/lights-camera-avatar.aspx"&gt;http://blogs.msdn.com/dejohn/archive/2009/05/18/lights-camera-avatar.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/dejohn/archive/2009/05/20/avatardescription-isvalid-when-why-the-description-returned-is-invalid.aspx href="http://blogs.msdn.com/dejohn/archive/2009/05/20/avatardescription-isvalid-when-why-the-description-returned-is-invalid.aspx" mce_href="http://blogs.msdn.com/dejohn/archive/2009/05/20/avatardescription-isvalid-when-why-the-description-returned-is-invalid.aspx"&gt;http://blogs.msdn.com/dejohn/archive/2009/05/20/avatardescription-isvalid-when-why-the-description-returned-is-invalid.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/dejohn/archive/2009/05/28/avatardescription-description.aspx href="http://blogs.msdn.com/dejohn/archive/2009/05/28/avatardescription-description.aspx" mce_href="http://blogs.msdn.com/dejohn/archive/2009/05/28/avatardescription-description.aspx"&gt;http://blogs.msdn.com/dejohn/archive/2009/05/28/avatardescription-description.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9800657" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>自動XNBファイルシリアライズ</title><link>http://blogs.msdn.com/ito/archive/2009/06/15/automatic-xnb-serialization.aspx</link><pubDate>Tue, 16 Jun 2009 05:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9757683</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/ito/comments/9757683.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9757683</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;コンテントタイプライター/リーダーを書くのは面倒&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;XNA Game Studioのコンテント・パイプラインでのデータの流れは下図のようになっています。オフラインプロセスは開発しているVisual Studio上でビルドしたときにWindows上で処理されるプロセスで、オフラインプロセスはWindows、Xbox 360、Zune上でゲームを実行したときに処理されるプロセスです。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/automaticXNBserialization_D3C8/cp-001_1.png" target="_blank" mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/automaticXNBserialization_D3C8/cp-001_1.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="cp-001" border="0" alt="cp-001" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/automaticXNBserialization_D3C8/cp-001_thumb_1.png" width="552" height="772" mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/automaticXNBserialization_D3C8/cp-001_thumb_1.png" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;元からサポートされているデータをそのまま扱う場合には良いのですが、カスタムデータを扱う場合に書かないといけないのが、ContentTypeWrite/ContentTypeReaderでした。特に面倒だったのが、読み込みと書き込みという対称的な処理をするのにContentTypeWriterはオフラインプロセス側、ContentTypeReaderはオンラインプロセス側と別々の場所で書かないといけないことでした。&lt;/p&gt;  &lt;p&gt;この面倒臭さを解決する為に、XNA GS 3.1では自動XNBシリアライズ機能が追加されました。この機能を使うことで、多くの場面でContentTypeWriter/ContentTypeReaderを書く必要がなくなりました。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;自動XNBシリアライズ機能の使い方&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;自動XNBシリアライズは.Netのリフレクション機能を使って実装されています。ContentTypeWriter/ContentTypeReaderが指定されていない場合、自動XNAシリアライズが発生し、以下のルールに沿って動作します。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;公開(public)メンバー、プロパティがシリアライズの対象になる &lt;/li&gt;    &lt;li&gt;シリアライズしたくないメンバーがある場合は、&lt;strong&gt;[ContentSerializerIgnore]&lt;/strong&gt;属性を指定することで、シリアライズしないように指定できる &lt;/li&gt;    &lt;li&gt;private, protected, internalなどの非公開メンバーをシリアライズしたい場合は&lt;strong&gt;[ContentSerializer]&lt;/strong&gt;属性を指定する &lt;/li&gt;    &lt;li&gt;シリアライズしたいデータ構造が再帰的な参照を含む場合は&lt;strong&gt;[ContentSerializer(SharedResource = true)]&lt;/strong&gt;を指定する &lt;/li&gt;    &lt;li&gt;コンテント・パイプライン内とランタイム時の型が違う場合、&lt;strong&gt;[ContentSerializerRuntimeType(“タイプ名”)]&lt;/strong&gt;を指定する &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;シンプルな例&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;例えば以下のようなデータをゲームで扱うとします。ゲームとコンテント・パイプラインで共有するデータなので、ゲームプロジェクトの他に共有するデータを入れるためのプロジェクトを作る必要があります。例えばMyDataTypesという名前のプロジェクトです。&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ねこクラス
&lt;/span&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Neko
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public string &lt;/span&gt;Name;     &lt;span style="color: green"&gt;// 名前
    &lt;/span&gt;&lt;span style="color: blue"&gt;public float &lt;/span&gt;Weight;    &lt;span style="color: green"&gt;// 体重
    &lt;/span&gt;&lt;span style="color: blue"&gt;public int &lt;/span&gt;Tails;       &lt;span style="color: green"&gt;// 尻尾の数
&lt;/span&gt;}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;このデータをコンテント・パイプライン内に読み込むために以下のようなXMLファイル、cats.xmlを書きます。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;XnaContent&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Asset &lt;/span&gt;&lt;span style="color: red"&gt;Type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;MyDataTypes.Neko[]&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Item&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;たま&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Weight&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;8&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Weight&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Item&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Item&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;ねこまた&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Weight&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;12&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Weight&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;2&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Item&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Asset&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;XnaContent&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;作ったXMLファイルをコンテントとして追加した後に、そのデータを読み込むコードをゲーム側のコード(LoadContentメソッド内など)に以下のコードを追加します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Neko&lt;/span&gt;[] cats = Content.Load&amp;lt;&lt;span style="color: #2b91af"&gt;Neko[]&lt;/span&gt;&amp;gt;(&lt;span style="color: #a31515"&gt;&amp;quot;cats&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;後は、F5を押すだけで変数catsには必要なデータが読み込まれます。3.0以前のようにContentTypeReader/ContentTypeReaderを書かなくても良いので、データ構造の宣言、データファイルの生成、読み込み部分のコードをゲーム内に追加という単純な作業でカスタムデータをゲーム内で読み込むことができます。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;オフラインとランタイムで型が違う場合&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/ito/archive/2009/06/12/content-pipeline-types-31.aspx" target="_blank" mce_href="http://blogs.msdn.com/ito/archive/2009/06/12/content-pipeline-types-31.aspx"&gt;XNA GS 3.1のコンテント・パイプライン内で使われる型&lt;/a&gt;の図を見ると、コンテント・パイプライン内ではTexture2DContentだけど、ゲーム内ではTexture2Dのように、オフライン時とランタイム時では型が異なるケースがあります。例えば、ゲーム内では以下のデータ構造にしたい場合があるとします。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ねこクラス
&lt;/span&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Neko
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public string &lt;/span&gt;Name;         &lt;span style="color: green"&gt;// 名前
    &lt;/span&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Texture2D &lt;/span&gt;Texture;   &lt;span style="color: green"&gt;// テクスチャ
&lt;/span&gt;}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;この場合、Textureはコンテント・パイプライン内で使う型がTexture2DContentとなるので、以下のようにContentSerializerRuntimeType属性を使ってランタイム時の型を指定します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ねこコンテント
&lt;/span&gt;[&lt;span style="color: #2b91af"&gt;ContentSerializerRuntimeType&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;MyGame.Neko, MyGame&amp;quot;&lt;/span&gt;)]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NekoContent
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public string &lt;/span&gt;Name;         &lt;span style="color: green"&gt;// 名前
    &lt;/span&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Texture2DContent &lt;/span&gt;Texture;   &lt;span style="color: green"&gt;// テクスチャ
&lt;/span&gt;}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;パフォーマンス&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;以上のように自動XNBシリアライズ機能は非常に便利な機能ですが、前述のようにデータの書き込みと読み込み時にリフレクション機能を使用するのでContentTypeWriter/ContentTypeReaderに比べると不必要なメモリ確保や、ボクシングなどが発生し、処理時間も多く掛かるので理論的にはロード時間が以前より長くなります。&lt;/p&gt;

&lt;p&gt;ですが、現実的にはカスタムデータの多くがゲーム内のパラメーターなど、他のコンテントに比べると数は少ないものなので、ロード時間が長くなるといっても無視できる範囲のことが多いと思われます。&lt;/p&gt;

&lt;p&gt;ただし、カスタムデータを数百、数千の配列で持つようなケースでは極端にロード時間が長くなる場合もあります。その場合は、今までどおりContentTypeWriter/ContentTypeReaderを使うことによってリフレクションによる速度低下を防ぐことができます。便利さを優先するには自動XNBシリアライズ、速度を優先するならContentTypeWriter/ContentTypeReaderといった感じに上手に使い分けましょう。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;サンプル・コード&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;自動XNBシリアライズ機能を使って&lt;a href="http://blogs.msdn.com/ito/archive/2007/05/02/content-pipeline-part3.aspx" target="_blank" mce_href="http://blogs.msdn.com/ito/archive/2007/05/02/content-pipeline-part3.aspx"&gt;コンテント・パイプラインの紹介の時&lt;/a&gt;に作った日本語表示のサンプルを3.1用に書き換えてみました。元のサンプルと比べると、共有するデータ型を記述するプロジェクト自体を書く必要がなくなり、ContentTypeWriter/ContentTypeReaderを書く必要が無くなったのでシンプルになっています。&lt;/p&gt;

&lt;p&gt;&lt;a title="http://higeneko.net/hinikeni/sample/TextMessageSample31.zip" href="http://higeneko.net/hinikeni/sample/TextMessageSample31.zip" mce_href="http://higeneko.net/hinikeni/sample/TextMessageSample31.zip"&gt;http://higeneko.net/hinikeni/sample/TextMessageSample31.zip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;元ネタ:&lt;a title="http://blogs.msdn.com/shawnhar/archive/2009/03/25/automatic-xnb-serialization-in-xna-game-studio-3-1.aspx" href="http://blogs.msdn.com/shawnhar/archive/2009/03/25/automatic-xnb-serialization-in-xna-game-studio-3-1.aspx" mce_href="http://blogs.msdn.com/shawnhar/archive/2009/03/25/automatic-xnb-serialization-in-xna-game-studio-3-1.aspx"&gt;http://blogs.msdn.com/shawnhar/archive/2009/03/25/automatic-xnb-serialization-in-xna-game-studio-3-1.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9757683" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B330F330C630F330C830FB30D130A430D730E930A430F330_/default.aspx">コンテント・パイプライン</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>AppWeek</title><link>http://blogs.msdn.com/ito/archive/2009/06/15/appweek.aspx</link><pubDate>Tue, 16 Jun 2009 04:12:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9757359</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9757359.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9757359</wfw:commentRss><description>&lt;p&gt; XNAプラットフォーム＆ツールチームの主な作業はXNA Game Studioを作ることですが、リリースの直前には、実際に作ったものに問題がないか、また使いやすいかを確認するために開発中のフレームワークを使って実際にゲームを作ってみるAppWeekというものがあります。&lt;/p&gt;  &lt;p&gt;XNA GSE 1.0の頃に作られた物の中には&lt;a href="http://creators.xna.com/en-US/minigame/catapult" target="_blank"&gt;Catapult&lt;/a&gt;、&lt;a href="http://creators.xna.com/en-US/minigame/minjie" target="_blank"&gt;Minji&lt;/a&gt;といったサンプルとして公開されているものもあります。XNA GS 3.0の時は忙しすぎてAppWeekをする暇がなかったのですが、今回のXNA GS 3.1ではAppWeekがありました。&lt;/p&gt;  &lt;p&gt;今回のAppWeekは４日間という短期間でしたが15個のゲームが作られました。特に3.1で追加された機能のテストを兼ねているので今回はアバターとビデオを使ったゲームが殆どでした。&lt;/p&gt;  &lt;p&gt;Shawn Hargreaves氏は&lt;a href="http://creators.xna.com/en-US" target="_blank"&gt;Creators Club Onlineサイト&lt;/a&gt;にあるサンプルコードを組み合わせて作った&lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/06/12/appweek.aspx" target="_blank"&gt;「Super Avatar Sample Smashup EXTREME! ‘Capture the Cat’ edition」&lt;/a&gt;を作りました。このゲームではフィールド内の相手陣地のねこを自陣までつれてくるのが勝利の条件で、一匹のねこをめぐって宇宙船やら、戦車を使った争奪戦を繰り広げるネットワーク対応のゲームでした。&lt;/p&gt;  &lt;p&gt;Brandon Bloom氏の作った&lt;a href="http://blog.brandonbloom.name/2009/06/appweek.html" target="_blank"&gt;「Avatar Boxing」&lt;/a&gt;は、アバターを使ったボクシングゲームでした。アバターの各ボーンを自由に変更することで任意のアニメーションを設定で機能を使ったものでした。ちなみにこのゲームを作るときには&lt;strong&gt;BoundingSphere.Transform&lt;/strong&gt;がサポートするのは平行移動のみの行列でしたが、それでは不便ということで3.1では平行移動、回転、スケールの行列もサポートするようになりました。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;私も３日間だけ時間が取れたので、アバターを使ったゲームを作ってみました。タイトルは「Columns Flash」、落ちものパズルゲームにアバターを組み合わせたものです。今回は贅沢にすべてのブロックを3Dにしてみました。&lt;/p&gt;  &lt;p&gt;ブロックを消すと、下のスクリーンショットのようにアバターが拍手するアニメーションしたり、&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-71_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-71" border="0" alt="itoxe1-71" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-71_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;コンボゲージが溜まったときにYボタンを押すと、下のスクリーンショットのようにコンボアタックを発動して対戦相手に対していじわる攻撃を繰り出すことができます。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-69_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-69" border="0" alt="itoxe1-69" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-69_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;こちらはLv1コンボアタックの「ゆさぶり」で、相手のボード全体がふらふらと揺れてプレイししづらくなります。もちろん、アバターも困った顔をしています。3Dで描画しているので、コンボアタックも3Dならではの攻撃になっています。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-70_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-70" border="0" alt="itoxe1-70" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-70_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;こちらは、Lv2コンボアタックの「ちぢこまり」です。ボードが小さくなるだけなのですが、この攻撃をされた対戦相手は画面が良く見えなくなるので、モニタの前に張り付く姿が笑えます。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-73_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-73" border="0" alt="itoxe1-73" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-73_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;で、こちらはLv3コンボアタックの「ひっくりがえし」です。ボードが180度回転して、ブロックの上下が逆さまになります。この手のゲームでは連鎖のタネをばら撒くのが勝つコツですが、そういった計画を文字通りひっくりがえしてしまう攻撃です。アバターも驚いた表情をします。 &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-76_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-76" border="0" alt="itoxe1-76" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-76_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;対戦が白熱してくると、やられたらやり返すという場面が増えてくるので、二人同時にコンボアタック発動して下のように派手な画面になることもしばしばあります。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-74_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-74" border="0" alt="itoxe1-74" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-74_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;そして、ゲームオーバーになると、下の画面のように負けたほうのブロックが飛び散り、勝ったプレイヤーのアバターは喜びのアニメーション、負けた方はうなだれたアニメーションをするようになっています。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-75_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-75" border="0" alt="itoxe1-75" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/appweek_DC24/itoxe1-75_thumb.png" width="644" height="364" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;このゲームではアバターの基本描画と、基本アニメーションセットしか使っていませんが、それでも自分のアバターがそのままゲーム内でさまざまなリアクションをするというのは楽しいものでした。また、今回のゲームは絵も含めてフルスクラッチ(背景の写真はハイキングへ行ったときに撮った写真)で制作しましたが、３日間という短期間でここまでのゲームを作ることができるという、C#を使った開発効率の高さにはいまだに感心させられます。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9757359" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/_397DCB4E_/default.aspx">紹介</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B230FC30E0308B957A76_/default.aspx">ゲーム開発</category></item><item><title>XNA GS 3.1のコンテント・パイプラインで使われる型</title><link>http://blogs.msdn.com/ito/archive/2009/06/12/content-pipeline-types-31.aspx</link><pubDate>Sat, 13 Jun 2009 05:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9741379</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ito/comments/9741379.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9741379</wfw:commentRss><description>&lt;P&gt;以前、&lt;A href="http://blogs.msdn.com/shawnhar/default.aspx" target=_blank mce_href="http://blogs.msdn.com/shawnhar/default.aspx"&gt;Shawn Hargreaves氏のブログ&lt;/A&gt;でXNA GS 2.0のコンテント・パイプライン内でデータが変換される過程図が紹介されました。&lt;/P&gt;
&lt;P&gt;&lt;A title=http://blogs.msdn.com/shawnhar/archive/2007/10/10/content-pipeline-types.aspx href="http://blogs.msdn.com/shawnhar/archive/2007/10/10/content-pipeline-types.aspx" mce_href="http://blogs.msdn.com/shawnhar/archive/2007/10/10/content-pipeline-types.aspx"&gt;http://blogs.msdn.com/shawnhar/archive/2007/10/10/content-pipeline-types.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;XNA GS 3.1がリリースされたので、それに合わせて元の図を翻訳し、SoundEffect、Video等の新しい型を追加した図を作ってみました。アセットファイルがどのようにインポートされ、プロセッサで処理され、ContentTypeWriterからXNBファイルとして書き出されるまに使われる型情報を網羅しているので、カスタムインポータや、カスタムプロセッサを作るときに役立つと思います。&lt;/P&gt;
&lt;P&gt;左側の水色の部分はコンテント・パイプライン内で処理される部分で、右側の黄色い部分はゲーム実行時に処理される部分です。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/contentpipelinetypes31_1120B/ContentPipelineTypes_4.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/contentpipelinetypes31_1120B/ContentPipelineTypes_4.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=ContentPipelineTypes border=0 alt=ContentPipelineTypes src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/contentpipelinetypes31_1120B/ContentPipelineTypes_thumb_1.png" width=1247 height=1288 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/contentpipelinetypes31_1120B/ContentPipelineTypes_thumb_1.png"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9741379" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B330F330C630F330C830FB30D130A430D730E930A430F330_/default.aspx">コンテント・パイプライン</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>動画再生</title><link>http://blogs.msdn.com/ito/archive/2009/06/11/video-playback.aspx</link><pubDate>Thu, 11 Jun 2009 23:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9727601</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9727601.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9727601</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;かんたん動画再生機能&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;XNA GS 3.1で動画を再生するには以下のステップを踏みます。 &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;再生したい動画をコンテントとして追加する &lt;/LI&gt;
&lt;LI&gt;Video情報をContent.Load&amp;lt;Video&amp;gt;で読み込む &lt;/LI&gt;
&lt;LI&gt;VideoPlayerクラスを使って再生 &lt;/LI&gt;
&lt;LI&gt;VideoPlayer.GetTexture()メソッドを使って現在のフレームのテクスチャを取得し描画する &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;変数宣言&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;動画再生するには、Videoクラスと、VideoPlayerクラスを使います。Videoクラスには再生する動画ファイル情報、動画のサイズやフレームレートなどの情報を含んでいます。VidoPlayerクラスは実際に動画再生するためのクラスで、このクラスを介して動画の再生、停止、一時停止、ループ再生の設定、現フレームをテクスチャとして取得することができます。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// 再生する動画
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Video &lt;/SPAN&gt;video;

&lt;SPAN style="COLOR: green"&gt;// 動画再生用のプレイヤーインスタンス
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;VideoPlayer &lt;/SPAN&gt;videoPlayer = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;VideoPlayer&lt;/SPAN&gt;();&lt;/PRE&gt;
&lt;P&gt;&lt;STRONG&gt;動画情報の読み込みと再生&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;動画情報の読み込みは他のアセットと同様、コンテントマネージャーを介して行います。読み込んだ動画情報をビデオプレーヤーに渡すことで動画再生をすることができます。&lt;/P&gt;
&lt;P&gt;Xbox 360の上で、デコーディングなどの動画再生処理は別スレッドで行われているのでゲームのメインスレッドへの影響は最小限になっています。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// 動画情報の読み込み
&lt;/SPAN&gt;video = Content.Load&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Video&lt;/SPAN&gt;&amp;gt;(&lt;SPAN style="COLOR: #a31515"&gt;"bear"&lt;/SPAN&gt;);

&lt;SPAN style="COLOR: green"&gt;// ループ再生の設定
&lt;/SPAN&gt;videoPlayer.IsLooped = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;

&lt;SPAN style="COLOR: green"&gt;// 指定のビデオを再生する
&lt;/SPAN&gt;videoPlayer.Play(video);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;再生フレームの取得&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;動画の音声部分は自動的に再生されますが、画像部分を表示するにはビデオプレイヤーから現在のフレームをテクスチャとして取得し、SpriteBatch等を使って描画します。GetTextureを呼ぶタイミングは動画のfpsに関係なくいつでも取得することができます。&lt;/P&gt;
&lt;P&gt;XNA GS 3.1の動画再生では常に実時間に合わせて動画再生を行うように実装されています。例えば高解像度の動画を性能の低いPC上で再生した場合は動画のフレームレートは落ちるけど、時間的には正しい動画再生をするようになっています。&lt;/P&gt;
&lt;P&gt;取得するテクスチャは別スレッドでデコードされた時間的に最も近い動画フレームです。ですから、30fpsの動画を60fpsで動作しているゲーム内で取得した場合は、2フレームが同じ動画フレームを取得することになり、逆に60fpsの動画があった場合、30fpsで動作しているゲーム内で動画フレームを取得した場合は動画データのフレームがスキップすることになります。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// 現在の再生フレームをテクスチャとして取得
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Texture2D &lt;/SPAN&gt;texture = videoPlayer.GetTexture();

&lt;SPAN style="COLOR: green"&gt;// 取得したテクスチャを使って描画
&lt;/SPAN&gt;spriteBatch.Begin();
spriteBatch.Draw( texture, pos, &lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;.White);
spriteBatch.End();&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;以下は、Windowsについてくるbear動画をXNA GS 3.1上で再生したものです。10行以下のコードで簡単に動画を再生できるようになっています。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-59_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-59_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=itoxe1-59 border=0 alt=itoxe1-59 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-59_thumb.png" width=644 height=364 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-59_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;また、再生フレームはテクスチャとして使えるので、取得したテクスチャを3Dモデルに適応することもできます。下の図を見て複数の動画が再生していると気づいた人もいると思いますが、VideoPlayerのインスタンスは複数作ることができ、それぞれに別々の動画を再生することもできます。ただし、それぞれの動画をデコード処理するのに時間が掛かるので、複数のHD動画再生するにはかなりのCPUパワーを必要とすることに注意してください。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-60_2.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-60_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title=itoxe1-60 border=0 alt=itoxe1-60 src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-60_thumb.png" width=644 height=364 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/videoplayback_FD61/itoxe1-60_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;STRONG&gt;再生フォーマット&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;XNA GS 3.1で再生できる動画の条件として以下があります。&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;DRM(デジタル著作権管理)が施された動画は再生できない &lt;/LI&gt;
&lt;LI&gt;WMV-9 “Main”プロファイル、VC-1エンコードされたもの &lt;/LI&gt;
&lt;LI&gt;CBR(固定ビットレート) &lt;/LI&gt;
&lt;LI&gt;音声トラックがあること &lt;/LI&gt;
&lt;LI&gt;音声トラックはWMAエンコード、1パスCBR &lt;/LI&gt;
&lt;LI&gt;XNA GSがサポートする最大ビットレートは以下の通り &lt;/LI&gt;&lt;/OL&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=573&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=102&gt;プロファイル&lt;/TD&gt;
&lt;TD vAlign=top width=103&gt;レベル&lt;/TD&gt;
&lt;TD vAlign=top width=130&gt;最大ビットレート&lt;/TD&gt;
&lt;TD vAlign=top width=236&gt;解像度とフレームレート&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;Main&lt;/TD&gt;
&lt;TD vAlign=top width=105&gt;Low&lt;/TD&gt;
&lt;TD vAlign=top width=130&gt;2 Mbps&lt;/TD&gt;
&lt;TD vAlign=top width=234&gt;320 x 240 @ 24Hz (QVGA)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=107&gt;Medium&lt;/TD&gt;
&lt;TD vAlign=top width=129&gt;10 Mbps&lt;/TD&gt;
&lt;TD vAlign=top width=233&gt;720 x 480 @ 30Hz (480p) &lt;BR&gt;720 x 576 @ 25Hz (576p)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=103&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=108&gt;High&lt;/TD&gt;
&lt;TD vAlign=top width=129&gt;20 Mbps&lt;/TD&gt;
&lt;TD vAlign=top width=233&gt;1280 x 720 @ 30Hz (720p)&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9727601" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+3.1/default.aspx">XNA 3.1</category></item><item><title>vFetchでスキンアニメーション</title><link>http://blogs.msdn.com/ito/archive/2009/05/10/more-bones-10.aspx</link><pubDate>Mon, 11 May 2009 05:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9601289</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9601289.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9601289</wfw:commentRss><description>&lt;p&gt;2009/06/25 追記: XNA GS 3.1用のサンプルを &lt;a href="http://higeneko.net/hinikeni/sample/xna31/vFetchSkinningSample.zip"&gt;http://higeneko.net/hinikeni/sample/xna31/vFetchSkinningSample.zip&lt;/a&gt;にアップしました。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;vFetchでスキンアニメーション&lt;/strong&gt;&lt;strong&gt;、その3:&lt;strong&gt;vFetchでスキンアニメーション&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;スキンアニメーションで使えるボーン数を増やそうシリーズの記事も１０回目となる今回で終わりです。今回はvFetchを使ったスキンアニメーションの実装例を紹介します。&lt;/p&gt;  &lt;p&gt;XNA Game Studio 3.0で動作するサンプルを用意しました。基本的に&lt;a href="http://creators.xna.com/en-US/sample/skinnedmodel" mce_href="http://creators.xna.com/en-US/sample/skinnedmodel"&gt;Skinned Model&lt;/a&gt;サンプルと同じ使い方ですが、今回のサンプルはXbox 360上でのみ動作することに注意してください。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://higeneko.net/hinikeni/sample/vFetchSkinningSample.zip" mce_href="http://higeneko.net/hinikeni/sample/vFetchSkinningSample.zip"&gt;http://higeneko.net/hinikeni/sample/vFetchSkinningSample.zip&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160; また、今回のサンプルは&lt;a href="http://blogs.msdn.com/ito/archive/2009/05/05/more-bones-05.aspx" target="_blank" mce_href="http://blogs.msdn.com/ito/archive/2009/05/05/more-bones-05.aspx"&gt;クォータニオンでスキンアニメーションサンプル&lt;/a&gt;に以下の変更を加えたものになっています。 &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;BoneVertexの実装 &lt;/li&gt;    &lt;li&gt;AnimationPlayerの変更 &lt;/li&gt;    &lt;li&gt;モデルの頂点宣言の変更 &lt;/li&gt;    &lt;li&gt;ボーン格納用頂点バッファの生成 &lt;/li&gt;    &lt;li&gt;シェーダーの変更 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;BoneVertexの実装&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;ボーン情報を頂点バッファへ格納するためのBoneVertex構造体を作ります。この構造体には実際のデータの他に頂点要素宣言と、ストライド情報が含まれています。&lt;/p&gt;  &lt;p&gt;この宣言の仕方は独自の頂点データを宣言する基本的な手法です。StructLayoutアトリビュートを使って構造体のメンバーがコンパイラーによって並び替えが起こらないようにし、静的なVertexElements配列と、構造体のバイトサイズを返すSizeInBytesを宣言します。&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
/// &lt;/span&gt;&lt;span style="color: green"&gt;ボーン格納用の頂点構造体
&lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
&lt;/span&gt;[&lt;span style="color: #2b91af"&gt;StructLayout&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;LayoutKind&lt;/span&gt;.Sequential)]
&lt;span style="color: blue"&gt;public struct &lt;/span&gt;&lt;span style="color: #2b91af"&gt;BoneVertex
&lt;/span&gt;{
    &lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;回転部分(クォータニオン) 
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;Rotation;

    &lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;平行移動部分
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;Translation;

    &lt;span style="color: blue"&gt;public &lt;/span&gt;BoneVertex( &lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;rotation, &lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;translation )
    {
        Rotation = rotation;
        Translation = translation;
    }

    &lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;頂点宣言
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VertexElement&lt;/span&gt;[] VertexElements = {
        &lt;span style="color: green"&gt;// Rotation (16バイト)
        &lt;/span&gt;&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VertexElement&lt;/span&gt;(1, 0, &lt;span style="color: #2b91af"&gt;VertexElementFormat&lt;/span&gt;.Vector4,
                                &lt;span style="color: #2b91af"&gt;VertexElementMethod&lt;/span&gt;.Default,
                                &lt;span style="color: #2b91af"&gt;VertexElementUsage&lt;/span&gt;.TextureCoordinate, 1),
        &lt;span style="color: green"&gt;// Traslation (12バイト)
        &lt;/span&gt;&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VertexElement&lt;/span&gt;(1,16, &lt;span style="color: #2b91af"&gt;VertexElementFormat&lt;/span&gt;.Vector3,
                                &lt;span style="color: #2b91af"&gt;VertexElementMethod&lt;/span&gt;.Default,
                                &lt;span style="color: #2b91af"&gt;VertexElementUsage&lt;/span&gt;.TextureCoordinate, 2),
    };

    &lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;ストライドの取得
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;public static int &lt;/span&gt;SizeInBytes
    {
        &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.SizeOf( &lt;span style="color: blue"&gt;typeof&lt;/span&gt;( &lt;span style="color: #2b91af"&gt;BoneVertex &lt;/span&gt;) ); }
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;AnimationPlayerの変更&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;クォータニオンによるスキンアニメーションサンプルからの変更点としては、SkinRoataions、SkinTranslationsをSkinTransformsに変換、GetSkinTransformsメソッドはBoneVertex配列を返すように変更します。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;モデルの頂点宣言の変更&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ボーン情報を頂点ストリームに格納するので、頂点宣言を変更する必要があります。元となる頂点宣言に指定した頂点要素を追加するExtendVertexDeclarationメソッドを持つRenderHelperクラスを作ります。&lt;/p&gt;

&lt;p&gt;ModelMeshPart.VertexDecralationは読み込み専用のプロパティなので、変更した頂点宣言はModelMeshPart.Tagプロパティに格納します。 &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// モデルのMeshPartのVertexDeclarationにvFetch用の頂点宣言を
// 追加してMeshPart.Tagに格納する
&lt;/span&gt;&lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;ModelMesh &lt;/span&gt;mesh &lt;span style="color: blue"&gt;in &lt;/span&gt;currentModel.Meshes )
{
    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;ModelMeshPart &lt;/span&gt;meshPart &lt;span style="color: blue"&gt;in &lt;/span&gt;mesh.MeshParts )
    {
        meshPart.Tag = &lt;span style="color: #2b91af"&gt;RenderHelper&lt;/span&gt;.ExtendVertexDeclaration(
                meshPart.VertexDeclaration, &lt;span style="color: #2b91af"&gt;BoneVertex&lt;/span&gt;.VertexElements );
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;ボーン格納用頂点バッファの生成&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;続いてボーン情報を格納するための頂点バッファを生成します。これも&lt;a href="http://blogs.msdn.com/ito/archive/2009/05/07/more-bones-07.aspx" target="_blank" mce_href="http://blogs.msdn.com/ito/archive/2009/05/07/more-bones-07.aspx"&gt;「頂点テクスチャでスキンアニメーション」&lt;/a&gt;の時と同じように、連続してデータを書き込むためのWritableVertexBufferというクラスを作って使用します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ボーン情報を書き込むための頂点バッファの生成
&lt;/span&gt;boneVB = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WritableVertexBuffer&lt;/span&gt;( GraphicsDevice,
        animationPlayer.GetSkinTransforms().Length * &lt;span style="color: #2b91af"&gt;BoneVertex&lt;/span&gt;.SizeInBytes, 2 );&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;こうして生成した頂点バッファに以下のようにしてボーン情報を書き込み、ストリーム1として設定します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ボーンの情報を頂点ストリームに書き込む
&lt;/span&gt;boneVB.Flip();
&lt;span style="color: blue"&gt;int &lt;/span&gt;offset = boneVB.SetData&amp;lt;&lt;span style="color: #2b91af"&gt;BoneVertex&lt;/span&gt;&amp;gt;( animationPlayer.GetSkinTransforms() );

gd.Vertices[1].SetSource( boneVB.VertexBuffer, offset, &lt;span style="color: #2b91af"&gt;BoneVertex&lt;/span&gt;.SizeInBytes );&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;実際の描画ですが、ModelMeshPart.Tagに格納した頂点データを使うので、単純にModelMesh.Drawメソッドを呼ばずに、個々のModelMeshPartを描画する必要があります。 &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;ModelMesh &lt;/span&gt;mesh &lt;span style="color: blue"&gt;in &lt;/span&gt;currentModel.Meshes )
{
    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;Effect &lt;/span&gt;effect &lt;span style="color: blue"&gt;in &lt;/span&gt;mesh.Effects )
    {
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;World&amp;quot;&lt;/span&gt;].SetValue( world );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;View&amp;quot;&lt;/span&gt;].SetValue( view );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;Projection&amp;quot;&lt;/span&gt;].SetValue( projection );
    }

    &lt;span style="color: green"&gt;// 
    &lt;/span&gt;gd.Indices = mesh.IndexBuffer;
    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;ModelMeshPart &lt;/span&gt;meshPart &lt;span style="color: blue"&gt;in &lt;/span&gt;mesh.MeshParts )
    {
        &lt;span style="color: green"&gt;// ボーン情報の頂点要素を追加した頂点宣言を使う
        &lt;/span&gt;gd.VertexDeclaration = meshPart.Tag &lt;span style="color: blue"&gt;as &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VertexDeclaration&lt;/span&gt;;

        gd.Vertices[0].SetSource( mesh.VertexBuffer,
                            meshPart.StreamOffset, meshPart.VertexStride );

        &lt;span style="color: #2b91af"&gt;Effect &lt;/span&gt;effect = meshPart.Effect;
        effect.Begin();
        effect.CurrentTechnique.Passes[0].Begin();

        gd.DrawIndexedPrimitives( &lt;span style="color: #2b91af"&gt;PrimitiveType&lt;/span&gt;.TriangleList, meshPart.BaseVertex,
                                0, meshPart.NumVertices, meshPart.StartIndex,
                                meshPart.PrimitiveCount );

        effect.CurrentTechnique.Passes[0].End();
        effect.End();
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;シェーダーの変更 &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;シェーダーの変更点は、vfetch命令を使って自前で頂点データをフェッチし、boneIndicesを使ってボーン情報をフェッチするだけです。後はクォータニオンを使ったスキンアニメーションと同じ処理をします。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;//-----------------------------------------------------------------------------
// 頂点シェーダー
//=============================================================================
&lt;/span&gt;&lt;span style="color: blue"&gt;VS_OUTPUT &lt;/span&gt;&lt;span style="color: maroon"&gt;VertexShader&lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;index : INDEX)
{
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;position;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;normal;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;texCoord;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;boneIndices;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;boneWeights;

    &lt;span style="color: green"&gt;// vfetchはアセンブリ命令なのでasmブロックを使う必要がある
    &lt;/span&gt;asm
    {
        &lt;span style="color: green"&gt;// 頂点データのフェッチ
        &lt;/span&gt;vfetch position,        index, position0
        vfetch normal,            index, normal0
        vfetch texCoord,        index, texcoord0
        vfetch boneIndices,        index, blendindices
        vfetch boneWeights,        index, blendweight
    };
    
    &lt;span style="color: green"&gt;// ボーン情報のフェッチ
    &lt;/span&gt;&lt;span style="color: blue"&gt;float4 &lt;/span&gt;q1, q2, q3, q4;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;t1, t2, t3, t4;
    
    asm
    {
        vfetch q1,    boneIndices.x, texcoord1
        vfetch q2,    boneIndices.y, texcoord1
        vfetch q3,    boneIndices.z, texcoord1
        vfetch q4,    boneIndices.w, texcoord1
        
        vfetch t1,    boneIndices.x, texcoord2
        vfetch t2,    boneIndices.y, texcoord2
        vfetch t3,    boneIndices.z, texcoord2
        vfetch t4,    boneIndices.w, texcoord2
    };&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;vfetchを使った開発&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;vfetch命令はXbox 360上でしか使うことができないので、いきなりシェーダー全体をvfetchを使って書いてしまうと、うまく動作しなかったときにvfetchの仕方が悪いのか、シェーダー内の処理自体にバグがあるのかを特定するのが難しくなります。&lt;/p&gt;

&lt;p&gt;ですから、vfetchを使ったシェーダーコードを書く場合、実際にvfetch命令を使ったシェーダーを書く前にWindows上で動作するシェーダーを書き、シェーダーが問題無く動作するのを確認してから、vfetchを使ったものに書き換えるようにすると良いでしょう。ここで問題が起きた場合はvfetch部分が原因だと特定できるので、時間の節約になります。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9601289" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/Xbox360/default.aspx">Xbox360</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item><item><title>vFetchの使い方</title><link>http://blogs.msdn.com/ito/archive/2009/05/09/more-bones-09.aspx</link><pubDate>Sun, 10 May 2009 05:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9599911</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9599911.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9599911</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;vFetchでスキンアニメーション、その２:vFetchの使い方&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Fetchを使ったスキンアニメーションの実装例を紹介する前にvfetchの基本的な使い方を紹介します。&lt;/P&gt;
&lt;P&gt;例えば、以下のシェーダーコードのように頂点位置、色を使用する頂点シェーダーがあるとします。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;VS_OUTPUT &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;VertexShader&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;float4 &lt;/SPAN&gt;position: &lt;SPAN style="COLOR: navy"&gt;POSITION&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;float4 &lt;/SPAN&gt;color : &lt;SPAN style="COLOR: navy"&gt;COLOR &lt;/SPAN&gt;)
{
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;上のコードと同じ動作をするコードはvFetchを使って以下のように書くことができます。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// INDEXセマンティクスを使ってインデックス値を取得する
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;VS_OUTPUT &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;VertexShader&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;index : INDEX)
{
    &lt;SPAN style="COLOR: blue"&gt;float4 &lt;/SPAN&gt;pos;    &lt;SPAN style="COLOR: green"&gt;// フェッチしたデータを格納するための変数、float4のみ指定できる
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;float4 &lt;/SPAN&gt;col;

    &lt;SPAN style="COLOR: green"&gt;// vfetchはアセンブリ命令なのでasmブロックを使う必要がある
    &lt;/SPAN&gt;asm
    {
        vfetch pos, index, position        &lt;SPAN style="COLOR: green"&gt;// positionのフェッチ
         &lt;/SPAN&gt;vfetch col, index, color        &lt;SPAN style="COLOR: green"&gt;// colorのフェッチ
    &lt;/SPAN&gt;};
    &lt;/PRE&gt;
&lt;P&gt;最初にインデックスバッファから読み込んだインデックス値を取得するためにINDEXセマンティクスを使います。次にフェッチしたデータを格納する為の変数を宣言します。この変数はfloat4型でないといけません。それ以外の型を指定するとコンパイルエラーになります。&lt;/P&gt;
&lt;P&gt;次にvfetch命令を使って頂点データをフェッチします。vfetchはアセンブリ命令なのでasmブロック内に書く必要があります。vfetchの書式は以下の様になっています。今までは読みやすいようにvFetchと書いてきましたが、実際の命令は全て小文字のvfetchになります。&lt;/P&gt;
&lt;P&gt;vfetch &lt;STRONG&gt;取得したデータを格納する変数名&lt;/STRONG&gt;, &lt;STRONG&gt;頂点インデックス&lt;/STRONG&gt;, &lt;STRONG&gt;セマンティクス&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;ここではインデックスバッファから取得した頂点インデックスを使用していますが、任意のインデックスを指定することができます。このことを利用して、&lt;A href="http://blogs.msdn.com/ito/archive/2008/12/12/gamefest-japan-2008-demo.aspx" target=_blank mce_href="http://blogs.msdn.com/ito/archive/2008/12/12/gamefest-japan-2008-demo.aspx"&gt;GameFest Japan 2009のデモ&lt;/A&gt;では、index内に元の頂点インデックスとインスタンスのインデックスの２つの情報を&lt;A href="http://blogs.msdn.com/ito/archive/2008/02/08/network-arithmetic-encoding.aspx" target=_blank mce_href="http://blogs.msdn.com/ito/archive/2008/02/08/network-arithmetic-encoding.aspx"&gt;算術符号化圧縮&lt;/A&gt;を使って格納し、シェーダー内で展開、頂点データとインスタンス用のデータをvFetchを使って取得しています。&lt;/P&gt;
&lt;P&gt;vfetchに指定するセマンティクスはシェーダーで指定する入力セマンティクスの小文字となっています。大文字が混ざっているとコンパイルエラーになります。また、texcoord&lt;STRONG&gt;0&lt;/STRONG&gt;, texcoord&lt;STRONG&gt;1&lt;/STRONG&gt;のようにセマンティクスの後に数字を指定することもできます。下の表は入力セマンティクスとvFetchで指定するセマンティクスの対応表です。&lt;/P&gt;
&lt;TABLE border=2 cellSpacing=0 cellPadding=2 width=458&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;
&lt;P align=center&gt;&lt;STRONG&gt;入力セマンティクス&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;
&lt;P align=center&gt;&lt;STRONG&gt;vFetchセマンティクス&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;
&lt;P align=center&gt;&lt;STRONG&gt;説明&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;BINORMAL&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;binormal&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;バイノーマル(従法線)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;BLENDINDICES&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;blendindices&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;ブレンドインデックス&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;BLENDWIEHGTS&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;blendweight&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;ブレンドの重み&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;COLOR&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;color&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;カラー&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;NORMAL&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;normal&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;法線&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;POSITION&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;position&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;頂点位置&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;PSIZE&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;psize&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;ポイントサイズ&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;TANGENT&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;tangent&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;タンジェント(接線)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=144&gt;TEXCOORD&lt;/TD&gt;
&lt;TD vAlign=top width=149&gt;texcoord&lt;/TD&gt;
&lt;TD vAlign=top width=163&gt;テクスチャ座標&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;まとめると&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;頂点インデックスはINDEXセマンティクスを使って取得する &lt;/LI&gt;
&lt;LI&gt;フェッチしたデータを格納する変数の型はfloat4にする &lt;/LI&gt;
&lt;LI&gt;vfetchはasmブロック内に記述する &lt;/LI&gt;
&lt;LI&gt;vfetchのセマンティクスは入力セマンティクスの小文字になっている &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;と、なります。&lt;/P&gt;
&lt;P&gt;次回は、このvFetchを使ったスキンアニメーションの実装例を紹介します。&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9599911" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/Xbox360/default.aspx">Xbox360</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item><item><title>vFetchってなに？</title><link>http://blogs.msdn.com/ito/archive/2009/05/08/more-bones-08.aspx</link><pubDate>Sat, 09 May 2009 05:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9598402</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9598402.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9598402</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;vFetchでスキンアニメーション、その１:vFetchってなに？&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Xbox 360のGPUはDirect X 9.0とDirect X 10の中間であると言われることがありますが、vFetchはその特徴を示すひとつの機能です。vFetchはシェーダー内で使えるアセンブリ命令で、Vertex Fetchの略、つまり頂点データをフェッチをするための命令です。&lt;/P&gt;
&lt;P&gt;vFetchを使うことで頂点数の増減こそできませんが、Direct X 10で追加されたジオメトリシェーダーを使った&lt;A href="http://developer.download.nvidia.com/SDK/10/direct3d/samples.html#Fur" target=_blank mce_href="http://developer.download.nvidia.com/SDK/10/direct3d/samples.html#Fur"&gt;ファーシェーダー&lt;/A&gt;のように隣接する頂点データをフェッチしてフィンポリゴンをリアルタイムに生成したりすることもできます。&lt;/P&gt;
&lt;P&gt;自由に頂点をフェッチできるというのが最大の利点ですが、弱点もあります。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Windows上では使えない &lt;/LI&gt;
&lt;LI&gt;アセンブリ命令なので、頂点フェッチの最適化などを自前でする必要がある &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;vFetchはWindows上では使うことができないので、Windows/Xbox 360両対応のゲームを製作する場合にはそれぞれのプラットフォーム別に違う手法を実装する必要があります。&lt;/P&gt;
&lt;P&gt;vFetch命令はメモリアクセス命令でもあるので、使用する場所を間違えると大きなパフォーマンスロスになってしまいます。通常はシェーダーコンパイラーが最適化してくれるのですが、明示的にvFetchを使うときには注意が必要です。vFetchを最適な状態で使用していないと40%程のパフォーマンスロスになってしまった、という経験が私自身ありました。&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;GPUはどうやって頂点データを読んでいるのか？&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;vFetchの使い方を知るには、GPUがどのように頂点データを読み込んでいるのかを知っておくと理解しやすいと思います。&lt;/P&gt;
&lt;P&gt;頂点シェーダー内で頂点データを読み込むには以下の三つの情報が不可欠です。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;シェーダー内の入力セマンティクス &lt;/LI&gt;
&lt;LI&gt;頂点宣言(VertexDeclaration) &lt;/LI&gt;
&lt;LI&gt;頂点ストリーム &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;シェーダー内の入力セマンティクス指定は以下のコードように&lt;STRONG&gt;「変数名 : セマンティクス名」&lt;/STRONG&gt;となります。この宣言によって、以下の例では、position変数にはPOSITIONセマンティクス、normal変数にはNORMALセマンティクスをといった感じに、任意の変数に指定したセマンティクスを割り当てています。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;VS_OUTPUT &lt;/SPAN&gt;&lt;SPAN style="COLOR: maroon"&gt;VertexShader&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;float4 &lt;/SPAN&gt;position : &lt;SPAN style="COLOR: navy"&gt;POSITION&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;float3 &lt;/SPAN&gt;normal : &lt;SPAN style="COLOR: navy"&gt;NORMAL&lt;/SPAN&gt;)
{
    &lt;SPAN style="COLOR: green"&gt;// ...

&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;次に、頂点宣言では複数の頂点要素(VertexElement)を指定することで、セマンティクスとメモリレイアウトとの関連付けをします。セマンティクスは&lt;A href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.graphics.vertexelementusage.aspx" target=_blank mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.graphics.vertexelementusage.aspx"&gt;VertexElementUsage&lt;/A&gt;で表されます。頂点宣言によって、任意のセマンティクスがどのストリームのどのメモリアドレスからどんなフォーマットで読み込むのかを指定します。&lt;/P&gt;
&lt;P&gt;下の頂点要素の宣言は&lt;STRONG&gt;「POSITIONはストリーム番号0番、頂点データの12バイト目からVector3フォーマットで格納されている」&lt;/STRONG&gt;という意味になります。&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;VertexElement&lt;/SPAN&gt;(0, 12, &lt;SPAN style="COLOR: #2b91af"&gt;VertexElementFormat&lt;/SPAN&gt;.Vector3,
                        &lt;SPAN style="COLOR: #2b91af"&gt;VertexElementMethod&lt;/SPAN&gt;.Default,
                        &lt;SPAN style="COLOR: #2b91af"&gt;VertexElementUsage&lt;/SPAN&gt;.Position, 0),&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;そして、最後に頂点ストリームの設定です。頂点ストリームの設定は&lt;A href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.graphics.vertexstream.setsource.aspx" target=_blank mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.graphics.vertexstream.setsource.aspx"&gt;VertexStream.SetSource&lt;/A&gt;メソッドで行います。以下のコードの意味は&lt;STRONG&gt;「ストリーム0番はメッシュの頂点バッファの100バイト目から始まり、ストライドサイズは64バイト」&lt;/STRONG&gt;という意味です。通常、ストライドサイズはひとつの頂点データと同じサイズですが、別のサイズでも問題ありません。例えば頂点サイズは20バイトだけど、他にも頂点データ以外のデータが入っているのでストライドサイズは48バイトなんていう指定の仕方もできます。&lt;/P&gt;&lt;PRE class=code&gt;GraphicsDevice.Vertices[0].SetSource( mesh.VertexBuffer, 100, 64 );&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;ストリームと頂点宣言の関係をまとめると以下の図のようになります。&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=stream border=0 alt=stream src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones08_117F5/stream_3.png" width=604 height=483 mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones08_117F5/stream_3.png"&gt; &lt;/P&gt;
&lt;P&gt;頂点バッファには頂点という名前がついているので、GPUが読み込める頂点データ形式だけを格納するべきものだと思われがちですが、GPUからすると頂点バッファは単なるメモリの塊に過ぎないので上図のように、GPUで読み込むべきPosition, Normal, Color以外にGPUが呼ぶ必要がないSpeedがあっても全く問題ありません。GPUが気にするのはストリーム情報と頂点宣言だけです。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/ito/archive/2008/12/12/gamefest-japan-2008-demo.aspx" target=_blank mce_href="http://blogs.msdn.com/ito/archive/2008/12/12/gamefest-japan-2008-demo.aspx"&gt;GameFest Japan 2008のデモ&lt;/A&gt;では、このことを利用してゲームオブジェクトのリストをそのまんま頂点バッファに設定して使用することでCPU側の無駄なコピー処理を省くDirect Mapping(私が勝手に命名)は、この仕組みを利用しています。&lt;/P&gt;
&lt;P&gt;ただし、ストライドの最大サイズは256バイトなので、大きなデータ構造を指定できないことに注意してください。&lt;/P&gt;
&lt;P&gt;GPUはシェーダー内のセマンティクス、頂点宣言、そしてストリームの情報を元に以下のように頂点データを読み込んでいます。ここではDrawIndexedPrimitiveを使い、頂点シェーダー内でposition変数の値を取得するまでの過程を説明します。&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;インデックスバッファから頂点インデックスを取得 &lt;/LI&gt;
&lt;LI&gt;POSITIONセマンティクスに該当する頂点要素の情報を見つける &lt;/LI&gt;
&lt;LI&gt;頂点アドレスの計算 
&lt;UL&gt;
&lt;LI&gt;頂点アドレス = 頂点バッファのアドレス + ストリームオフセット + ストライド × 頂点インデックス &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;頂点要素のメモリアドレスの計算 
&lt;UL&gt;
&lt;LI&gt;頂点要素アドレス = 頂点アドレス + 頂点要素のオフセット &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;頂点要素のメモリアドレスから指定されたフォーマット形式でデータをposition変数に読み込む &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;以上のステップは普段はGPUで自動的に行われているのですが、この過程の1と2の部分をシェーダー内でやってしまおうというのがvFetch命令です。&lt;/P&gt;
&lt;P&gt;次回に続く&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9598402" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/Xbox360/default.aspx">Xbox360</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item><item><title>頂点テクスチャでスキンアニメーション</title><link>http://blogs.msdn.com/ito/archive/2009/05/07/more-bones-07.aspx</link><pubDate>Fri, 08 May 2009 05:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9595632</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ito/comments/9595632.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9595632</wfw:commentRss><description>&lt;p&gt;2009/06/25 追記: XNA GS 3.1用のサンプルを &lt;a href="http://higeneko.net/hinikeni/sample/xna31/TexSkinningSample.zip"&gt;http://higeneko.net/hinikeni/sample/xna31/TexSkinningSample.zip&lt;/a&gt;にアップしました。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;頂点テクスチャでスキンアニメーション、その2:頂点テクスチャでスキンアニメーション&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;今回は頂点テクスチャを使ったスキンアニメーションの実装方法を紹介します。&lt;/p&gt;  &lt;p&gt;XNA Game Studio 3.0で動作するサンプルを用意しました。基本的に&lt;a href="http://creators.xna.com/en-US/sample/skinnedmodel" target="_blank"&gt;Skinned Model&lt;/a&gt;サンプルと同じ使い方です。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://higeneko.net/hinikeni/sample/TexSkinningSample.zip" mce_href="http://higeneko.net/hinikeni/sample/TexSkinningSample.zip"&gt;http://higeneko.net/hinikeni/sample/TexSkinningSample.zip&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;今回のサンプルは前々回の&lt;a href="http://blogs.msdn.com/ito/archive/2009/05/05/more-bones-05.aspx" target="_blank"&gt;「クォータニオンでスキンアニメーション」&lt;/a&gt;のサンプルプログラムに以下の変更を加えたものです。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;AnimationPlayerの変更 &lt;/li&gt;    &lt;li&gt;頂点テクスチャの生成 &lt;/li&gt;    &lt;li&gt;シェーダーの変更 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;頂点テクスチャフォーマットを決める&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;まずは、頂点テクスチャにどのようにボーンデータを格納するか決めます。ボーンの回転部分のクォータニオンはVector4と同じフォーマットなのでSurfaceFormat.Vector4が使えます。平行移動にはVector3を使っていますが、頂点テクスチャのフォーマットにはVector3が無いのでちょっともったいないですがSurfaceFormat.Vector4を使用します。&lt;/p&gt;  &lt;p&gt;今回のサンプルでは、回転部分と平行移動部分を2つの頂点テクスチャに別々に格納しています。ひとつのテクセルにひとつのボーン情報を格納しているので、頂点テクスチャのサイズは横がボーン数、縦が1となっています。 &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="tex-bone" border="0" alt="tex-bone" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones07_F45C/tex-bone_3.png" width="600" height="160" mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones07_F45C/tex-bone_3.png" /&gt;&lt;/p&gt;  &lt;p&gt;頂点テクスチャのサンプラーは4つしかないので、2つの頂点テクスチャを使うのが厳しい場合は以下のように、2つのテクセルにひとつのボーン情報をまとめて格納するといいでしょう。この場合、頂点テクスチャのサイズは横がボーン数×2、縦が1となります。&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="tex-bone-02" border="0" alt="tex-bone-02" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones07_F45C/tex-bone-02_3.png" width="600" height="67" mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones07_F45C/tex-bone-02_3.png" /&gt;&lt;/p&gt;  &lt;p&gt;頂点テクスチャが使うメモリサイズを節約するという観点では前者の回転部分と平行移動部分を別々の頂点テクスチャで持つほうが有利です。これはクォータニオンの4要素の値の範囲は-1～+1なので、SurfaceFormat.Vector4の代わりにSurfaceFormat.HalfVector4やSurfaceFormat.NormalizedShort4を使うことでメモリ使用量を半分にすることができるからです。また、通常のキャラクターアニメーションでは平行移動部分も大きな値を使用しないのでSurfaceFormat.HalfVector4を使って更にメモリ使用量を減らすこともできるでしょう。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AnimationPlayerの変更 &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;機能的には前々回のサンプルとまったく同じなのですが、頂点テクスチャへの格納フォーマットがVector4に変わったので、それに合わせてSkinTranslationsの型もVector3[]からVector4[]に変更します。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;頂点テクスチャの生成&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;まずは、使用する頂点テクスチャ(ボーン用の頂点テクスチャなので、ボーンテクスチャと呼びます)の宣言をします。フレーム毎にボーン情報をボーンテクスチャへ書き込むわけですが、&lt;a href="http://blogs.msdn.com/ito/archive/2009/03/25/how-gpus-works-01.aspx" target="_blank"&gt;「GPUはいつ描画するのか？」&lt;/a&gt;で解説したように、同じテクスチャに続けて書き込むとGPUの処理とバッティングしてしまうということに注意が必要です。&lt;/p&gt;  &lt;p&gt;そこで、それぞれ複数の頂点テクスチャを生成して切り替えながら使う必要があります。この実装は非常に単純でTexture2Dの配列と、現在使用するテクスチャのインデックスを用意するだけでいいのですが、使用する頂点テクスチャが増えてくると余計な変数が増えてきて、コードの可読性が低くなり、ミスも起きやすくなってしまいます。そういった理由から、ここでは複数のテクスチャを切り替える機能をもったFlipTexture2Dというクラスを作ります。&lt;/p&gt;  &lt;p&gt;FlipTexture2DクラスはTexture2Dと同様のコンストラクタを持ち、内部で複数のテクスチャを作り、Flipメソッドで使うテクスチャを切り替え、Textureプロパティで現在のテクスチャを返すようになっています。&lt;/p&gt;  &lt;pre class="code"&gt;    &lt;span style="color: green"&gt;// ボーン情報を格納するテクスチャ
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FlipTexture2D &lt;/span&gt;rotationTexture;      &lt;span style="color: green"&gt;// ボーンの回転部分を格納するテクスチャ
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FlipTexture2D &lt;/span&gt;translationTexture;   &lt;span style="color: green"&gt;// ボーンの平行移動部分を格納するテクスチャ

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;ボーンテクスチャの生成は前述のように、横がボーン数、縦が1のサイズのテクスチャを作ります。ここでTextureUsageを&lt;strong&gt;TextureUsage.Linear&lt;/strong&gt;を指定していることに注意してください。通常のテクスチャはピクセルシェーダー内でフェッチされることを前提としており、その用途に適しているTextureUsage.Tilingを使用するようになっています。TextureUsage.Noneを設定しても、テクスチャサイズがタイリングに適している場合は自動的にタイリングを使うようになっています。&lt;/p&gt;

&lt;p&gt;通常のレンダリング時には極力タイリングを使うべきですが、SetDataを呼び出したときに通常のフォーマットからタイリングフォーマットへの変換がCPUによって行われます。&lt;/p&gt;

&lt;p&gt;今回はボーンテクスチャとして使用するので、タイリングを使う必要がないこと、SetData時にタイリングフォーマット変換に掛かる時間を節約したいという二点の理由から、TextureUsage.Linearを指定します。 &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 頂点テクスチャの生成
&lt;/span&gt;&lt;span style="color: blue"&gt;int &lt;/span&gt;width = animationPlayer.GetSkinRotations().Length;
&lt;span style="color: blue"&gt;int &lt;/span&gt;height = 1;

rotationTexture = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FlipTexture2D&lt;/span&gt;( GraphicsDevice, width, height, 1,
                        &lt;span style="color: #2b91af"&gt;TextureUsage&lt;/span&gt;.Linear, &lt;span style="color: #2b91af"&gt;SurfaceFormat&lt;/span&gt;.Vector4 );

translationTexture = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FlipTexture2D&lt;/span&gt;( GraphicsDevice, width, height, 1,
                        &lt;span style="color: #2b91af"&gt;TextureUsage&lt;/span&gt;.Linear, &lt;span style="color: #2b91af"&gt;SurfaceFormat&lt;/span&gt;.Vector4 );&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;こうして作ったボーンテクスチャにanimationPlayerで生成したSkinRotationsとSkinTranslationsをSetData&amp;lt;T&amp;gt;を使って書き込みます。ここではFlipTexture2D.Flipメソッドを呼び出すことで書き込むテクスチャを切り替えてから書き出します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ボーンのクォータニオンと平行移動部分を取得し頂点テクスチャに書き込み
&lt;/span&gt;rotationTexture.Flip();
translationTexture.Flip();

rotationTexture.Texture.SetData&amp;lt;&lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;&amp;gt;( animationPlayer.GetSkinRotations() );
translationTexture.Texture.SetData&amp;lt;&lt;span style="color: #2b91af"&gt;Vector4&lt;/span&gt;&amp;gt;( animationPlayer.GetSkinTraslations() );&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;頂点シェーダー内で頂点テクスチャをフェッチする場合に指定するのはテクスチャ座標なので、ボーン番号からテクスチャ座標に変換するために必要な&lt;strong&gt;textureSize&lt;/strong&gt;を設定します。&lt;/p&gt;

&lt;p&gt;実際の描画コードは以下のようになっています、通常の描画コードにrotationTexture、traslationTexture、そしてtextureSizeを設定するコードが追加しただけです。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Vector2 &lt;/span&gt;textureSize = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Vector2&lt;/span&gt;( rotationTexture.Texture.Width,
                                    rotationTexture.Texture.Height );

&lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;ModelMesh &lt;/span&gt;mesh &lt;span style="color: blue"&gt;in &lt;/span&gt;currentModel.Meshes )
{
    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;( &lt;span style="color: #2b91af"&gt;Effect &lt;/span&gt;effect &lt;span style="color: blue"&gt;in &lt;/span&gt;mesh.Effects )
    {
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;BoneRotationTexture&amp;quot;&lt;/span&gt;].SetValue(
                                            rotationTexture.Texture );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;BoneTranslationTexture&amp;quot;&lt;/span&gt;].SetValue(
                                            translationTexture.Texture );

        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;BoneTextureSize&amp;quot;&lt;/span&gt;].SetValue( textureSize );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;World&amp;quot;&lt;/span&gt;].SetValue( world );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;View&amp;quot;&lt;/span&gt;].SetValue( view );
        effect.Parameters[&lt;span style="color: #a31515"&gt;&amp;quot;Projection&amp;quot;&lt;/span&gt;].SetValue( projection );
    }

    mesh.Draw();
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;シェーダーの変更&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;シェーダー内での頂点テクスチャの宣言は通常のテクスチャと殆ど変わりありませんが、殆どのGPUでは浮動小数点テクスチャのバイリニアフィルタリングが利かないのと、正しいフィルター設定しないとフェッチができないものが多いので、ここではポイントサンプリング、ミップマップなし、テクスチャのアドレッシングをクランプに設定しています。&lt;/p&gt;

&lt;p&gt;また、このコードでは&lt;strong&gt;register(vs, s0)&lt;/strong&gt;というレジスタ宣言をして明示的に頂点テクスチャを任意のサンプラーに割り当てています。この宣言は必ずしも必要はありませんが、複数のエフェクトで同じ定数を共有したい場合にsharedを指定すると、コンパイラはサンプラーが通常のテクスチャなのか頂点テクスチャなのかを判断することができなってしまうので、registerを使って指定する必要があります。 &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;//-----------------------------------------------------------------------------
// 頂点テクスチャ用の定数レジスタ宣言
//=============================================================================
&lt;/span&gt;&lt;span style="color: blue"&gt;float2 &lt;/span&gt;BoneTextureSize;    &lt;span style="color: green"&gt;// ボーン用頂点テクスチャのサイズ

// ボーン用頂点テクスチャサンプラー宣言
&lt;/span&gt;&lt;span style="color: blue"&gt;texture &lt;/span&gt;BoneRotationTexture;

&lt;span style="color: blue"&gt;sampler &lt;/span&gt;BoneRotationSampler : &lt;span style="color: blue"&gt;register&lt;/span&gt;(vs,s0) = &lt;span style="color: blue"&gt;sampler_state
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;Texture &lt;/span&gt;= (BoneRotationTexture);
    &lt;span style="color: green"&gt;// 殆どのGPUでは以下のようなステート設定にしないと
    // 頂点テクスチャのフェッチがうまくいかない
    &lt;/span&gt;&lt;span style="color: blue"&gt;MinFilter &lt;/span&gt;= Point;
    &lt;span style="color: blue"&gt;MagFilter &lt;/span&gt;= Point;
    &lt;span style="color: blue"&gt;MipFilter &lt;/span&gt;= &lt;span style="color: navy"&gt;None&lt;/span&gt;;
    &lt;span style="color: blue"&gt;AddressU &lt;/span&gt;= Clamp;
    &lt;span style="color: blue"&gt;AddressV &lt;/span&gt;= Clamp;
};

&lt;span style="color: blue"&gt;texture &lt;/span&gt;BoneTranslationTexture;

&lt;span style="color: blue"&gt;sampler &lt;/span&gt;BoneTranslationSampler : &lt;span style="color: blue"&gt;register&lt;/span&gt;(vs,s1) = &lt;span style="color: blue"&gt;sampler_state
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;Texture &lt;/span&gt;= (BoneTranslationTexture);
    &lt;span style="color: green"&gt;// 殆どのGPUでは以下のようなステート設定にしないと
    // 頂点テクスチャのフェッチがうまくいかない
    &lt;/span&gt;&lt;span style="color: blue"&gt;MinFilter &lt;/span&gt;= Point;
    &lt;span style="color: blue"&gt;MagFilter &lt;/span&gt;= Point;
    &lt;span style="color: blue"&gt;MipFilter &lt;/span&gt;= &lt;span style="color: navy"&gt;None&lt;/span&gt;;
    &lt;span style="color: blue"&gt;AddressU &lt;/span&gt;= Clamp;
    &lt;span style="color: blue"&gt;AddressV &lt;/span&gt;= Clamp;
};&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;続いてボーン情報をボーンテクスチャからフェッチします。頂点テクスチャのフェッチには&lt;strong&gt;tex2Dlod&lt;/strong&gt;を使います。tex2Dlodにはfloat4値を渡し、x,y,zにはテクスチャ座標のu,v,wを、wにはミップマップレベルを指定します。ピクセルシェーダー内でおなじみのtex2Dが頂点シェーダー内で使えない理由はピクセルシェーダー内ではハードウェアが自動的にミップマップレベルを計算してくれますが、頂点シェーダー内ではミップマップレベルを自動的に計算することができないからです。ですから、tex2Dlodを使用してミップマップレベルを指定する必要があります。&lt;/p&gt;

&lt;p&gt;4つのボーンインデックスから計算したテクスチャ座標を使ってそれぞれのボーン情報をフェッチして、&lt;a href="http://blogs.msdn.com/ito/archive/2009/05/05/more-bones-05.aspx" target="_blank"&gt;前々回のサンプル&lt;/a&gt;で作ったCreateTransformFromQuaternionTransformsメソッドを使ってskinTransformを計算します。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;//-----------------------------------------------------------------------------
// 頂点テクスチャからボーン情報のフェッチ
//=============================================================================
&lt;/span&gt;&lt;span style="color: blue"&gt;float4x4 &lt;/span&gt;CreateTransformFromBoneTexture( &lt;span style="color: blue"&gt;float4 &lt;/span&gt;boneIndices, &lt;span style="color: blue"&gt;float4 &lt;/span&gt;boneWeights )
{
    &lt;span style="color: blue"&gt;float2 &lt;/span&gt;uv = 1.0f / BoneTextureSize;
    uv.y *= 0.5f;
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;texCoord0 = &lt;span style="color: blue"&gt;float4&lt;/span&gt;( ( 0.5f + boneIndices.x ) * uv.x, uv.y, 0, 1 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;texCoord1 = &lt;span style="color: blue"&gt;float4&lt;/span&gt;( ( 0.5f + boneIndices.y ) * uv.x, uv.y, 0, 1 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;texCoord2 = &lt;span style="color: blue"&gt;float4&lt;/span&gt;( ( 0.5f + boneIndices.z ) * uv.x, uv.y, 0, 1 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;texCoord3 = &lt;span style="color: blue"&gt;float4&lt;/span&gt;( ( 0.5f + boneIndices.w ) * uv.x, uv.y, 0, 1 );

    &lt;span style="color: green"&gt;// 回転部分のフェッチ
    &lt;/span&gt;&lt;span style="color: blue"&gt;float4 &lt;/span&gt;q1 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneRotationSampler, texCoord0 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;q2 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneRotationSampler, texCoord1 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;q3 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneRotationSampler, texCoord2 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;q4 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneRotationSampler, texCoord3 );

    &lt;span style="color: green"&gt;// 平行移動部分のフェッチ
    &lt;/span&gt;&lt;span style="color: blue"&gt;float4 &lt;/span&gt;t1 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneTranslationSampler, texCoord0 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;t2 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneTranslationSampler, texCoord1 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;t3 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneTranslationSampler, texCoord2 );
    &lt;span style="color: blue"&gt;float4 &lt;/span&gt;t4 = &lt;span style="color: blue"&gt;tex2Dlod&lt;/span&gt;( BoneTranslationSampler, texCoord3 );
    
    &lt;span style="color: blue"&gt;return &lt;/span&gt;CreateTransformFromQuaternionTransforms(
                    q1, t1,
                    q2, t2,
                    q3, t3,
                    q4, t4,
                    boneWeights );
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;頂点シェーダー本体のコードは以下のようになります。前々回のサンプルではCreateTransformFromQuaternionTransformsを呼んでいた部分がCreateTransformFromBoneTextureに変わっただけです。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;//-----------------------------------------------------------------------------
// 頂点シェーダー
//=============================================================================
&lt;/span&gt;&lt;span style="color: blue"&gt;VS_OUTPUT &lt;/span&gt;&lt;span style="color: maroon"&gt;VertexShader&lt;/span&gt;(&lt;span style="color: blue"&gt;VS_INPUT &lt;/span&gt;input)
{
    &lt;span style="color: blue"&gt;VS_OUTPUT &lt;/span&gt;output;
    
    &lt;span style="color: green"&gt;// スキン変換行列の取得
    &lt;/span&gt;&lt;span style="color: blue"&gt;float4x4 &lt;/span&gt;skinTransform =
                CreateTransformFromBoneTexture( input.BoneIndices, input.BoneWeights );
            
    skinTransform = &lt;span style="color: blue"&gt;mul&lt;/span&gt;( skinTransform, World );
  
    &lt;span style="color: green"&gt;// 頂点変換
    &lt;/span&gt;&lt;span style="color: blue"&gt;float4 &lt;/span&gt;position = &lt;span style="color: blue"&gt;mul&lt;/span&gt;(input.Position, skinTransform);
    output.Position = &lt;span style="color: blue"&gt;mul&lt;/span&gt;(&lt;span style="color: blue"&gt;mul&lt;/span&gt;(position, View), Projection);

    &lt;span style="color: green"&gt;// 法線変換
    &lt;/span&gt;&lt;span style="color: blue"&gt;float3 &lt;/span&gt;normal = &lt;span style="color: blue"&gt;normalize&lt;/span&gt;( &lt;span style="color: blue"&gt;mul&lt;/span&gt;( input.Normal, skinTransform));
    
    &lt;span style="color: blue"&gt;float3 &lt;/span&gt;light1 = &lt;span style="color: blue"&gt;max&lt;/span&gt;(&lt;span style="color: blue"&gt;dot&lt;/span&gt;(normal, Light1Direction), 0) * Light1Color;
    &lt;span style="color: blue"&gt;float3 &lt;/span&gt;light2 = &lt;span style="color: blue"&gt;max&lt;/span&gt;(&lt;span style="color: blue"&gt;dot&lt;/span&gt;(normal, Light2Direction), 0) * Light2Color;

    output.Lighting = light1 + light2 + AmbientColor;

    output.TexCoord = input.TexCoord;
    
    &lt;span style="color: blue"&gt;return &lt;/span&gt;output;
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;定数レジスタがいらなくなった&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ボーン情報を頂点テクスチャから読み込んでいるので、定数レジスタの数制限からくるボーン数制限がなくなりました。ただし、XNAフレームワークのコンテント・パイプラインで変換されるボーンインデックスは最大256個までとなっているので、最大ボーン数は256個になります。もちろん、コンテント・パイプラインを拡張して出力するボーンインデックスのフォーマットを変更すれば更に多くのボーンを使うこともできますが、256個以上のボーンが必要になるケースというのはあるのでしょうか？&lt;/p&gt;

&lt;p&gt;これでオリジナルのサンプルでは59個から4倍以上のボーン数を使えるようになりました。定数レジスタを必要としないので、余った定数レジスタは他の用途に使うことができます。&lt;/p&gt;

&lt;p&gt;PC上ではシェーダーモデル3.0以上のビデオカードが必要になりますが、Xbox 360上では問題なく動くし、この手法を活用できる場面(近日中の記事で紹介予定)も多いので、魅力的な手法ではないでしょうか？&lt;/p&gt;

&lt;p&gt;今回の手法で使えるボーン数が上限にまで達しましたが、次回はXbox 360専用の機能であるvFetchを使った手法を紹介したいと思います。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9595632" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B730A730FC30C030FC30E230C730EB30_+3.0/default.aspx">シェーダーモデル 3.0</category></item><item><title>クォータニオンの使いどころ</title><link>http://blogs.msdn.com/ito/archive/2009/05/01/more-bones-04.aspx</link><pubDate>Sat, 02 May 2009 07:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9583338</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9583338.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9583338</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;クォータニオンでボーン処理、その3:クォータニオンの使いどころ&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;前回はXNAフレームワーク内での基本的なクォータニオンの使い方、特にクォータニオンは回転行列の代わりに使えるといったことを紹介しました。ただ、それだけではクォータニオンを使いたいと思った人は少ないと思います。そこで今回はクォータニオン特有の利点と、ゲームでの実際の使用方法を紹介します。&lt;/p&gt;  &lt;p&gt;今回紹介するクォータニオンの特徴は以下の五つです&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;メモリ使用量が3x3の回転行列の半分以下になる &lt;/li&gt;    &lt;li&gt;回転の結合が容易にできる &lt;/li&gt;    &lt;li&gt;回転の補間が容易にできる &lt;/li&gt;    &lt;li&gt;正規化ができる &lt;/li&gt;    &lt;li&gt;行列への変換がオイラー角を使うのに比べて高速 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;メモリ使用量を減らす&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;メモリの使用量については特に大量の容量を必要とするアニメーションデータを減らす目的でクォータニオンが使われることが多いです、&lt;a href="http://www.xbox.com/ja-JP/games/b/bruteforce/details.page/" target="_blank" mce_href="http://www.xbox.com/ja-JP/games/b/bruteforce/details.page/"&gt;Brute Force&lt;/a&gt;ではメインキャラクター４体のアニメーションだけで約2時間近いデータがありました。このデータを単純に4x4の行列で持つと14MB以上になりますが、クォータニオンと移動の組み合わせにすると5.6MBと、半分以下のサイズになり、更にクォータニオン内のx,y,z,wの値の範囲は-1～1までなので、それを&lt;a href="http://blogs.msdn.com/ito/archive/2008/01/31/network-06-quantization.aspx" target="_blank" mce_href="http://blogs.msdn.com/ito/archive/2008/01/31/network-06-quantization.aspx"&gt;量子化&lt;/a&gt;してそれぞれの要素を16ビットと半分のサイズにすることで、4.5MBと元の３分の１以下のサイズに減らしていました。&lt;/p&gt;  &lt;p&gt;これでもXbox 1のメインメモリの64MBの7%近くを使用していたので、いつもアニメーターの人とプログラマーの間で「もっとアニメーションを増やしたい」「ダメ、メモリ足りない」というやり取りがしばしばありました。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;回転の結合が容易にできる&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;回転の結合についてですが、例えばフライトシミュレーター系のゲームを作っている場合、現在の飛行機の姿勢を保持しておいて、コントローラーによってフレーム毎のヨー、ピッチ、ロールの差分を現在の姿勢と結合することで飛行機の姿勢を変更します。&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;// コントローラーによるヨー、ピッチ、ロールの取得
&lt;/span&gt;&lt;span style="color: blue"&gt;float &lt;/span&gt;dt = (&lt;span style="color: blue"&gt;float&lt;/span&gt;)gameTime.ElapsedGameTime.TotalSeconds;
&lt;span style="color: blue"&gt;float &lt;/span&gt;factor = &lt;span style="color: #2b91af"&gt;MathHelper&lt;/span&gt;.ToRadians(180.0f) * dt;
&lt;span style="color: blue"&gt;float &lt;/span&gt;yaw = (padState.Triggers.Left - padState.Triggers.Right) * factor;
&lt;span style="color: blue"&gt;float &lt;/span&gt;pitch = padState.ThumbSticks.Left.Y * factor;
&lt;span style="color: blue"&gt;float &lt;/span&gt;roll = padState.ThumbSticks.Left.X * factor;

&lt;span style="color: green"&gt;// 行列を使った姿勢変更
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;deltaMtx = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateFromYawPitchRoll(yaw, pitch, roll);
rotationMatrix = rotationMatrix * deltaMtx;

&lt;span style="color: green"&gt;// クォータニオンを使った姿勢変更
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;deltaQuat = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromYawPitchRoll(yaw, pitch, roll);
rotationQuaternion = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.Concatenate(rotationQuaternion, deltaQuat);

&lt;span style="color: green"&gt;// クォータニオンの正規化
&lt;/span&gt;rotationQuaternion.Normalize();&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;行列でも回転の結合ができるのですが、行列の場合、単精度浮動小数点(float)の誤差が計算ごとに溜まっていき、最終的には正常な回転行列ではなくなってしまうという問題があります。そこで、正規化を使うことで計算誤差でおかしくなった回転状態を簡単に正常に戻すことのできるクォータニオンです。&lt;/p&gt;

&lt;p&gt;と、書きたかったのですが、よくよく考えるとXNAフレームワークを使っている場合、計算自体はXbox 360、Windows上のどちらでも倍精度(double)で行われるので、あんまり問題ありませんでした。ちなみに、単精度の計算すると60fpsのゲームで3分後くらいにモデルの形状がおかしくなってしまうという問題がありました。 &lt;/p&gt;

&lt;p&gt;そこで、プログラムのアップデート内で実際の速度の3,000倍の速さで更新するプログラムを作って試してみました。下はプログラムを実行し始めてから三時間経過した時の様子です。左側は行列で回転の結合をしただけのもの、右側はクォータニオンを使って結合、正規化をしたものです。左側の機体が右側の機体よりも大きくなっているのが分かると思います。これは、回転行列の結合を続けることで浮動小数点の誤差が積み重なって、正しい回転行列ではなくなってしまったという証拠です。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/itoxe1-17_4.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="itoxe1-17" border="0" alt="itoxe1-17" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/itoxe1-17_thumb_1.png" width="644" height="364" /&gt;&lt;/a&gt; ただし、前述のようにこのプログラムは本来の3000倍の速度で動作しているので、実際の時間に換算して１年になるので、XNAフレームワークをWindows, Xbox 360上で使っている限りは問題ありませんが、XNAフレームワーク以外で単精度の浮動小数点を使っている場合は精度の問題が発生するので、クォータニオンを使って回転の結合をした後に正規化をすることによって、この誤差を修正することができます。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;回転の補間が容易にできる&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;次にクォータニオンを使う醍醐味と言っていいほどの特徴が回転の補間です。オイラー角を使った場合、ひとつの軸のに対しての回転であれば回転の補間はできますが、自由な回転同士の補間は不可能です。それに対して、クォータニオンを使った場合はどんな回転の状態であれ、簡単に補間することができます。&lt;/p&gt;

&lt;p&gt;また、スキンアニメーションなどで複数の行列をブレンドしている、つまり補間していますが、これは線形補間でしかないので回転が含まれている行列同士の補間では厳密には正確な補間ができないのですが、スキンアニメーションのボーンブレンディングの場合は誤差が無視できる範囲でブレンディングが行われるので殆どの場合は問題ないように見えているというのが現状です。&lt;/p&gt;

&lt;p&gt;クォータニオンの補間にはLerp(ラープ)、Slerp(スラープ)を使って簡単に正確な回転補間ができます。ちなみにLerpはLinear Interporationの略で日本語では線形補間、SlerpはSphercal Linear Interpolationの略で、日本語では球面線形補間となります。&lt;/p&gt;

&lt;p&gt;下は0度回転の状態と90度回転したものを補間するコードです。ここではSlerpを使っていますが、この場合では線形補間であるLerpを使っても問題ありません。線形とは言ってもクォータニオンの世界のなかの線形であって、3次元空間の線形とは違います。クォータニオンのLerpとSlerpでは前者の方が計算が軽いですが、誤差が発生してしまいます。Brute Forceでは計算速度を稼ぐために回転角度が大きく違う時以外はLerpを使い、誤差を修正するために時々正規化していました。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// ０度と９０度回転の行列とクォータニオンの生成
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;mtx0 = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateRotationZ(&lt;span style="color: #2b91af"&gt;MathHelper&lt;/span&gt;.ToRadians(0));
&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;mtx1 = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateRotationZ(&lt;span style="color: #2b91af"&gt;MathHelper&lt;/span&gt;.ToRadians(90));

&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q0 = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromAxisAngle( &lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.UnitZ, &lt;span style="color: #2b91af"&gt;MathHelper&lt;/span&gt;.ToRadians(0));
&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q1 = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromAxisAngle(&lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.UnitZ, &lt;span style="color: #2b91af"&gt;MathHelper&lt;/span&gt;.ToRadians(90));

&lt;span style="color: green"&gt;// 補間
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;m = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.Slerp(mtx0, mtx1, t);
&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.Lerp(q0, q1, t);&lt;/pre&gt;

&lt;p&gt;コードだけでは、実際にどのように補間されているの分からないので、テストプログラムを使って動画にしてみました。赤い軸が０度の地点、緑の軸が９０度回転した位置を表しています。青い点は行列の補間の結果で、白い点はクォータニオンの補間の結果になります。&lt;/p&gt;

&lt;div style="padding-bottom: 0px; padding-left: 0px; width: 444px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:7be1cdd6-5b92-4a99-8685-1fd65ad4b160" class="wlWriterEditableSmartContent"&gt;&lt;div id="a07065c5-8601-473b-aaed-24c3a541386d" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://video.msn.com/video.aspx?vid=8fe0b2b7-4e98-4876-9219-1c44205a7f13&amp;amp;from=writer" target="_new"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/videod9043cdea8c3.jpg" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('a07065c5-8601-473b-aaed-24c3a541386d'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;embed src=\&amp;quot;http://images.video.msn.com/flash/soapbox1_1.swf\&amp;quot; quality=\&amp;quot;high\&amp;quot; width=\&amp;quot;432\&amp;quot; height=\&amp;quot;364\&amp;quot; wmode=\&amp;quot;transparent\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; pluginspage=\&amp;quot;http://macromedia.com/go/getflashplayer\&amp;quot; flashvars=\&amp;quot;c=v&amp;amp;v=8fe0b2b7-4e98-4876-9219-1c44205a7f13&amp;amp;from=writer&amp;amp;mkt=en-US\&amp;quot; &amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;クォータニオンの補間では白い点が綺麗に円弧を描いているのに対して、行列の変換では青い点が直線的に動いているのが分かると思います。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/blend-sphere-01_4.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="blend-sphere-01" border="0" alt="blend-sphere-01" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/blend-sphere-01_thumb_1.png" width="244" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;また、拡大してみると判りますが、クォータニオンでの補間だと問題ありませんが、行列の補間の場合だと形がゆがんでいます。動画を見ると、このゆがみは補完する中間地点に近づくほどに大きくなり、始点と終点付近で元に戻っている様子がわかると思います。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/blend-sphere-02_4.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="blend-sphere-02" border="0" alt="blend-sphere-02" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones04_1094F/blend-sphere-02_thumb_1.png" width="244" height="165" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;このように、行列の線形補間は回転の補間が苦手ということがわかったと思います。アニメーションデータの容量を少なくするためにキーフレーム間の補間をするときがありますが、すばやい回転アニメーション、例えば野球選手の投球モーションの腕の部分のように短い時間で大きな回転動作をする場合に行列の線形補間を使うと、回転モーションが正しく保管されずに縮こまった投球モーションになってしまいます。そこでクォータニオンを使えば少ないアニメーションデータでも綺麗な投球モーションになります。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;正規化ができる &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;これは既に上で何度か説明していますが、浮動小数点による計算誤差や、Lerpを使った時などに回転状態が徐々に崩れていってしまうという問題があるのですが、クォータニオンの場合は単純に&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.normalize.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.normalize.aspx"&gt;Quaternion.Normalize&lt;/a&gt;を呼び出すだけで簡単に正常な回転状態に戻すことができます。&lt;/p&gt;

&lt;p&gt;この正常な状態に戻せるというのは重要なことで、実際にゲームを作っていると最初プレイしているうちは滑らかに動いていたのに、時間が経つとガクガクしてくるという問題に直面することがあり、その原因が精度の問題だった場合、原因を突き止めるのが非常に困難になるので、こういった問題が発生する前から誤差があっても動作するコードが書けるというのは時間の節約にもなります。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;行列への変換がオイラー角を使うのに比べて高速&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;例えば爆破などのエフェクトで回転しながら飛び散る破片があるとします。この時に、X,Y,Zのオイラー角を使って実装した場合、フレーム毎に描画する前に行列に変換しないといけませんが、その変換過程で計算に時間の掛かるSin,Cosの三角関数が使用されます。それに対して、クォータニオンの場合は最初に回転速度を表すクォータニオンを生成しておけば、フレーム毎の更新では現在の姿勢を示すクォータニオンと結合するだけですみます。この結合とクォータニオンから行列への変換は計算時間の掛からない単純な積和演算だけで済むのでむので大量のオブジェクトを処理するときに有用です。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;クォータニオンを使う目安&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;三回に渡ってクォータニオンの特徴を説明してきましたが、最後にクォータニオンをいつ使うべきかを判断するポイントを紹介します。&lt;/p&gt;

&lt;p&gt;クォータニオンを使うと便利&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;アニメーションデータが多すぎるので圧縮したい 
    &lt;ul&gt;
      &lt;li&gt;キーフレーム間の回転補間 &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;自由に回転状態を変化させたい 
    &lt;ul&gt;
      &lt;li&gt;岩などのオブジェクトが地面の起伏の状態によって回転状態が変化する場合 &lt;/li&gt;

      &lt;li&gt;飛行機などの姿勢制御 &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;回転状態を変化させる必要はないけど対象となるオブジェクトが大量にある 
    &lt;ul&gt;
      &lt;li&gt;爆発などで大量の破片がランダムに回転しながら飛び散るエフェクト &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;オイラー角で十分&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;制限された回転 
    &lt;ul&gt;
      &lt;li&gt;FPS、TPSなどのカメラコントロール &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;回転状態を変化する必要がない 
    &lt;ul&gt;
      &lt;li&gt;爆発などで少数の破片がランダムに回転しながら飛び散るエフェクト &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;誤差があっても大丈夫 
    &lt;ul&gt;
      &lt;li&gt;回転の結合が短時間だけ必要な場合、上記のエフェクトなどカットシーン的な場面で使われる回転 &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;次は、いよいよ(やっと？)クォータニオンを使ったボーン数節約の実装例を紹介します。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9583338" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item><item><title>クォータニオンの使い方</title><link>http://blogs.msdn.com/ito/archive/2009/04/30/more-bones-03.aspx</link><pubDate>Fri, 01 May 2009 03:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9581575</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9581575.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9581575</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;クォータニオンでボーン処理、その2:クォータニオンの使い方&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;今回はXNAフレームワーク内でのクォータニオンの使い方の紹介をします。クォータニオンは回転行列の代替として使えるので、Matrix構造体と同じメソッドが用意されています。そこで、同じ操作に対応する行列とクォータニオンの両方のコードを紹介していきます。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;回転&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;回転行列を生成するのと同じようにクォータニオンでも&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.createfromyawpitchroll.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.createfromyawpitchroll.aspx"&gt;CreateFromYawPitchRoll&lt;/a&gt;、&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.createfromaxisangle.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.createfromaxisangle.aspx"&gt;CreateFromAxisAngle&lt;/a&gt;メソッドを使って任意の回転をするクォータニオンを生成できます。&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 回転行列の生成
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;m1 = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateFromYawPitchRoll(yaw, pitch, roll);
&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;m2 = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateFromAxisAngle(&lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.Up, angle);

&lt;span style="color: green"&gt;// クォータニオンの生成
// 回転行列とまったく同じ意味のものを生成できる
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q1 = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromYawPitchRoll(yaw, pitch, roll);
&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q2 = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromAxisAngle(&lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.Up, angle);&lt;/pre&gt;

&lt;p&gt;CreateFromYawPitchRollのそれぞれの引数はヨー(Yaw)、ピッチ(Pitch)、ロール(Roll)となっています。飛行機を例にすると、水平飛行状態で機首を左右に回転するのがヨー、機首を上下に回転させるのがピッチ、そして機体の前後を軸とした回転がロールになります。&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="yaw-pitch-roll copy" border="0" alt="yaw-pitch-roll copy" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones03_D941/yaw-pitch-roll%20copy_8.png" width="604" height="407" /&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;回転していないクォータニオン(単位クォータニオン)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;回転していない状態を表すクォータニオンは単位クォータニオンと呼びます。これも行列と同じように、&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.identity.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.identity.aspx"&gt;Quaternion.Identity&lt;/a&gt;プロパティが使えます。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 単位回転行列の生成(回転していない行列)
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;mi = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.Identity;

&lt;span style="color: green"&gt;// 単位クォータニオン(回転していないクォータニオン)
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;qi = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.Identity;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;結合(Concatenate)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;行列と同じように複数のクォータニオンを結合することで、複数の回転を組み合わせたものを生成することができます。&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.op_multiply.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.op_multiply.aspx"&gt;q1 * q2&lt;/a&gt;のようにして結合ができますが、ここで注意が必要なのは行列の結合の順番とは逆になることです。たとえば、二つの行列をm1 * m2として’結合した場合、意味的には&lt;strong&gt;「m1の回転をした後に、m2の回転をする」&lt;/strong&gt;となりますが、クォータニオンの結合、q1 * q2の場合は&lt;strong&gt;「q2の回転をした後に、q1の回転をする」&lt;/strong&gt;と違った意味になります。&lt;/p&gt;

&lt;p&gt;この原因はXNAフレームワークでは、q1 * q2は結合ではなく、数学的な二つのクォータニオンの乗算として定義されているからです。特に演算子オーバーロードは見た目が数式に近いものが書けるので、数学的な操作と同じように動作するようになっています。これは他の全ての数学関連のクラスや構造体内の演算子オーバーロード(*,/,+,-)でも同じルールに従っています。実はこれがVector3 * Matrixと書けない理由でもあります。&lt;/p&gt;

&lt;p&gt;このままだと混乱するので明示的に結合を表すために&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.concatenate.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.quaternion.concatenate.aspx"&gt;Concatenate&lt;/a&gt;メソッドがあります。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 回転行列の結合
// m1の回転をした後に、m2の回転をした結果を計算する
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;mtx = m1 * m2;

&lt;span style="color: green"&gt;// クォータニオンの結合
// 順番が行列とは逆になることに注意
// q2 * q1の意味はq1の回転をした後に、q2の回転をするという意味になる
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;quat = q2 * q1;

&lt;span style="color: green"&gt;// 上記の混乱を避けるために明示的にConcatenate(結合)メソッドを呼び出すことで
// q1の回転の後に、q2の回転をした結果を計算できる
&lt;/span&gt;quat = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.Concatenate(q1, q2);&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;頂点変換&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;行列を使っての頂点変換は多くの人が使っていると思いますが、クォータニオンを使っても同じように頂点変換ができます。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 回転行列を使った頂点変換
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;va = &lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.Transform(position, m1);

&lt;span style="color: green"&gt;// クォータニオンを使った頂点変換
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;vb = &lt;span style="color: #2b91af"&gt;Vector3&lt;/span&gt;.Transform(position, q1);&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;クォータニオン、行列間の変換&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;クォータニオンから回転行列へ、また回転行列からクォータニオンへの変換は以下のメソッドを使ってすることができます。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// クォータニオン、行列間の変換
// クォータニオンから回転行列を生成
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;m = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.CreateFromQuaternion(q1);

&lt;span style="color: green"&gt;// 回転行列からクォータニオンを生成する
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;q = &lt;span style="color: #2b91af"&gt;Quaternion&lt;/span&gt;.CreateFromRotationMatrix(m1);&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;分解&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;前述の方法では回転行列とクォータニオン間での変換でしたが、時にはスケールや移動も含まれている行列から回転部分だけを取り出したい場合もあります。この時に便利なのが&lt;a href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.matrix.decompose.aspx" target="_blank" mce_href="http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.matrix.decompose.aspx"&gt;Matrix.Decompose&lt;/a&gt;メソッドです。&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// 任意の行列をスケール、回転(クォータニオン)、移動の三つの情報に分解する
// もともとはコンテントパイプライン内でボーン情報をコンパクトにするために
// 設計されたもので、重い処理なので大量の分解をリアルタイムにするのには向いていない
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Matrix &lt;/span&gt;boneMatrix = &lt;span style="color: #2b91af"&gt;Matrix&lt;/span&gt;.Identity;

&lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;scale;
&lt;span style="color: #2b91af"&gt;Quaternion &lt;/span&gt;rotation;
&lt;span style="color: #2b91af"&gt;Vector3 &lt;/span&gt;translation;
boneMatrix.Decompose(&lt;span style="color: blue"&gt;out &lt;/span&gt;scale, &lt;span style="color: blue"&gt;out &lt;/span&gt;rotation, &lt;span style="color: blue"&gt;out &lt;/span&gt;translation);&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&amp;#160;&lt;strong&gt;まとめ&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;と、いうわけで以上に紹介したようにクォータニオンを回転行列の変わり使えるということが解ったかと思います。注意点としては、結合の順番に気をつけるか、Concatenateメソッドを使うことくらいです。&lt;/p&gt;

&lt;p&gt;次回はクォータニオンを使う醍醐味である回転の合成、補間について紹介します。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9581575" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item><item><title>クォータニオンってなに？</title><link>http://blogs.msdn.com/ito/archive/2009/04/28/more-bones-02.aspx</link><pubDate>Wed, 29 Apr 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9574809</guid><dc:creator>Yuichi Ito</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ito/comments/9574809.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ito/commentrss.aspx?PostID=9574809</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;クォータニオンでボーン処理、その１:クォータニオンってなに？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;クォータニオンの前知識なしでクォータニオンを使ったスキニングアニメーションのコードを理解するのは厳しいので、今回から数回に分けてクォータニオンを説明していきます。&lt;/p&gt;  &lt;p&gt;クォータニオン(Quaterinon)は日本語で&lt;a href="http://ja.wikipedia.org/wiki/%E5%9B%9B%E5%85%83%E6%95%B0" target="_blank" mce_href="http://ja.wikipedia.org/wiki/%E5%9B%9B%E5%85%83%E6%95%B0"&gt;四元数(しげんすう)&lt;/a&gt;と言い、定義的には3つの虚数単位を持つ超複素数系のひとつです。&lt;/p&gt;  &lt;p&gt;………&lt;/p&gt;  &lt;p&gt;と、いってもなんのことかさっぱり解らなくても大丈夫です(たぶん)。本来であれば数学的な説明も入れるべきですが、今回はスキンアニメーションでの使われ方の説明なので、そういった部分は割愛します。より詳しく数学的な意味が知りたい人は&lt;a href="http://www.amazon.co.jp/%E8%B6%85%E8%A4%87%E7%B4%A0%E6%95%B0%E5%85%A5%E9%96%80%E2%80%95%E5%A4%9A%E5%85%83%E7%92%B0%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81-I-L-Kantor/dp/4627061110" target="_blank" mce_href="http://www.amazon.co.jp/%E8%B6%85%E8%A4%87%E7%B4%A0%E6%95%B0%E5%85%A5%E9%96%80%E2%80%95%E5%A4%9A%E5%85%83%E7%92%B0%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81-I-L-Kantor/dp/4627061110"&gt;「超複素数入門」&lt;/a&gt;、どの様に回転を表すかを知るためには英語ですが&lt;a href="http://www.amazon.co.jp/Quaternions-Rotation-Sequences-Applications-Aerospace/dp/0691102988/ref=sr_1_1?ie=UTF8&amp;amp;s=english-books&amp;amp;qid=1240882473&amp;amp;sr=8-1" target="_blank"&gt;「Quaternions and Rotation Sequences」&lt;/a&gt;&lt;/a&gt;が良書ですし、日本語でも&lt;a href="http://www.amazon.co.jp/%E5%AE%9F%E4%BE%8B%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%B2%E3%83%BC%E3%83%A03D%E6%95%B0%E5%AD%A6-Fletcher-Dunn/dp/4873113776/ref=pd_sim_b_2" target="_blank" mce_href="http://www.amazon.co.jp/%E5%AE%9F%E4%BE%8B%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%B2%E3%83%BC%E3%83%A03D%E6%95%B0%E5%AD%A6-Fletcher-Dunn/dp/4873113776/ref=pd_sim_b_2"&gt;「実例で学ぶゲーム3D数学」&lt;/a&gt;が参考になると思います。&lt;/p&gt;  &lt;p&gt;クォータニオンを簡単に説明すると、回転行列の変わりに使える便利な道具です。&lt;/p&gt;  &lt;p&gt;行列の中で回転を表す部分は以下のようにRの部分、つまり3x3、9個の数値であらわします。XNAフレームワークの中では9個のfloatになります。&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mtx" border="0" alt="mtx" src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones02_108ED/mtx_3.png" width="217" height="140" mce_src="http://blogs.msdn.com/blogfiles/ito/WindowsLiveWriter/morebones02_108ED/mtx_3.png" /&gt; &lt;/p&gt;  &lt;p&gt;これがクォータニオンでは4個の数値、XNAフレームワーク内では4個のfloatで同じ回転を表すことができます。つまり、回転を表すのに必要なメモリが半分以下になる訳です。メモリ消費量だけで比べるのならx,y,z軸の回転角度を持つほうがより少ない消費量になりますが、オイラー角を使った場合、線形補間ができなかったり、行列への変換に三角関数を使う必要があったり、なにより面倒なジンバルロックの問題があったりと実際のゲーム開発では回転する範囲が制限されている場合以外ではオイラー角による回転が使われることは少なく、クォータニオンが使われるケースがほとんどです。&lt;/p&gt;  &lt;p&gt;クォータニオンの利点をまとめると&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;メモリ使用量が少ない、回転行列の半分、4x4の行列の1/4 &lt;/li&gt;    &lt;li&gt;行列と同じように線形補間(Learp)、または球面線形補間(Slerp)ができる &lt;/li&gt;    &lt;li&gt;行列への変換がオイラー角を使うのに比べて高速 &lt;/li&gt;    &lt;li&gt;ジンバルロックに悩まされない &lt;/li&gt;    &lt;li&gt;正規化が簡単 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;と、いった感じになりますが、弱点としては&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;オイラー角で回転をもつよりメモリ使用量が少し増える &lt;/li&gt;    &lt;li&gt;オイラー角と違って直感的に解りづらい&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;があります。&lt;/p&gt;  &lt;p&gt;次回はXNAフレームワーク内でどのようにクォータニオンを使うのかを説明します。&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9574809" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ito/archive/tags/XNA+_D530EC30FC30E030EF30FC30AF30_/default.aspx">XNA フレームワーク</category><category domain="http://blogs.msdn.com/ito/archive/tags/_B030E930D530A330AF30B930_/default.aspx">グラフィクス</category></item></channel></rss>