<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>わくわくプログラミング自習室 Blogs</title>
	<atom:link href="http://i-libro.net/wpmu/feed" rel="self" type="application/rss+xml" />
	<link>http://i-libro.net/wpmu</link>
	<description>管理人のブログです。</description>
	<pubDate>Sat, 14 Jan 2012 17:08:00 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>簡易データベース利用ライブラリ</title>
		<link>http://i-libro.net/wpmu/blog/archives/1110</link>
		<comments>http://i-libro.net/wpmu/blog/archives/1110#comments</comments>
		<pubDate>Sat, 14 Jan 2012 17:00:57 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/?p=1110</guid>
		<description><![CDATA[				かなり久々の更新になってしまいましたが、ちょっと便利そうなものができたので公開しておきます。  ときどき職場で使うツールをWebアプリとして作ることがあるのですが、面倒なのがデータベースへのアクセス。面倒というか、たまにしか書かないのでSQLやPHPを忘れてしまうのですね。そこで、JavaScriptのオブジェクトをそのままデータベースに書き込むライブラリを作りました。これならJavaScriptさえ覚えていれば、データベースを利用するアプリを簡単に作ることができるはずです。仕事で使う都合で、簡単なユーザー認証機能も加えています。
				dowasureDBjsの詳しい説明はこちら ※ソース（jsとphp）は説明ページのgithubへのリンクから落とせます   テストを兼ねて、取引先とファイルをやりとりするためのアップローダを作ってみました。アップローダといっても誰でも書き込める公開タイプのではなく、大きなファイルを送るために「宅ふぁいる便」的な目的で使うものです。ファイルをアップロードする部分はphpを書かざるをえなかったのですが、dowasureDBjsを使うことで、ユーザー認証と、フォルダのアクセス制御（他の取引先のフォルダが見えないように制限）の部分は比較的簡単に作ることができました。
				アップローダのソース
				]]></description>
			<content:encoded><![CDATA[				<p>かなり久々の更新になってしまいましたが、ちょっと便利そうなものができたので公開しておきます。  ときどき職場で使うツールをWebアプリとして作ることがあるのですが、面倒なのがデータベースへのアクセス。面倒というか、たまにしか書かないのでSQLやPHPを忘れてしまうのですね。そこで、JavaScriptのオブジェクトをそのままデータベースに書き込むライブラリを作りました。これならJavaScriptさえ覚えていれば、データベースを利用するアプリを簡単に作ることができるはずです。仕事で使う都合で、簡単なユーザー認証機能も加えています。</p>
				<div id="attachment_1111" class="wp-caption alignnone" style="width: 310px"><a href="http://i-libro.net/wpmu/files/2012/01/desc001.png"><img class="size-medium wp-image-1111" src="http://i-libro.net/wpmu/files/2012/01/desc001.png" alt="dowasureDBjsの利用例" width="300" height="135" /></a><p class="wp-caption-text">dowasureDBjsの利用例</p></div>
				<p><a href="http://i-libro.net/game/article/dowasureDBjs/">dowasureDBjsの詳しい説明はこちら ※ソース（jsとphp）は説明ページのgithubへのリンクから落とせます </a> <span id="more-1110"></span> テストを兼ねて、取引先とファイルをやりとりするためのアップローダを作ってみました。アップローダといっても誰でも書き込める公開タイプのではなく、大きなファイルを送るために「宅ふぁいる便」的な目的で使うものです。ファイルをアップロードする部分はphpを書かざるをえなかったのですが、dowasureDBjsを使うことで、ユーザー認証と、フォルダのアクセス制御（他の取引先のフォルダが見えないように制限）の部分は比較的簡単に作ることができました。</p>
				<p><a href="https://github.com/ari2008/LWUploaderGB">アップローダのソース</a></p>
				<p><div id="attachment_1112" class="wp-caption aligncenter" style="width: 310px"><p class="wp-caption-text">アップローダの実行画面</p></div><a href="http://i-libro.net/wpmu/files/2012/01/man005.png"><img class="size-medium wp-image-1112" src="http://i-libro.net/wpmu/files/2012/01/man005.png" alt="アップ</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/1110/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門第2部】物理エンジンBulletとDXライブラリを組み合わせて使う その3</title>
		<link>http://i-libro.net/wpmu/blog/archives/1094</link>
		<comments>http://i-libro.net/wpmu/blog/archives/1094#comments</comments>
		<pubDate>Sun, 07 Aug 2011 20:57:53 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/1094</guid>
		<description><![CDATA[				かなり時間が空いてしまいましたが、BulletとDXライブラリに関する解説の続きです。今回はBulletの計算結果に合わせて、DXライブラリで3Dモデルを表示する方法を解説します。
				
				DXBullet_3DTest_src02.zip（要Visual C++ 2010 Express） 
				DXBullet_3DTest_bin02.zip（実行ファイル）
				&#160;
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				©CRYPTON FUTURE MEDIA, INC.    解説中で使用しているモデルは前回に続きenamel toy box（ハッチさん運営）で公開されている「PMDねんどろ風初音ミクv1.1」
				pmdファイルのダウンロードや組み合わせ方については、過去記事も参考にしてください。
				  
				動かしてみよう
				最初にサンプルプログラムを実行して、結果を確認してください。前回のサンプルを改造したもので、落ちてくるブロックの下にモデルが表示されるようにしています。ブロックがモデルに当たると、回転したり床から落っこちたりします。
				
				&#160;
				座標系の変換
				前回記事ではすっかり忘れていたのですが、DXライブラリはDirect3Dと同じ左手座標系、Bulletは右手座標系なので表示する前に変換してやらなければいけません。そのための関数を数カ所に加えています（座標系については初回記事を参照）。
				「_dxdebugdraw.h」の中で定義しているbtVGet関数は、btVector3からVECTOR型に変換するためのものですが、このときにZ軸の正負を反転させます。
				●_dexdebugdraw.h
				
				//DXライブラリ用のBox2Dのデバッグドロー

#include &#60;DxLib.h&#62;

#include &#60;LinearMath/btIDebugDraw.h&#62;

class DxDebugDraw : public btIDebugDraw{
private:
	int m_debugMode;
	//座標変換
	inline VECTOR btVGet(const btVector3 &#38;inv){return VGet(inv.getX(), inv.getY(), -inv.getZ());}
public:
				
				●main.h
				上記の関数はDxDebugDrawクラスの中でしか使えないので、同じ働きをする関数を「main.h」にも加えます。
				
				//座標変換
inline VECTOR btVGet(const btVector3 &#38;inv){return VGet(inv.getX(), inv.getY(), -inv.getZ());}
inline VECTOR btRotVGet(const btVector3 &#38;inv){return VGet(-inv.getX(), -inv.getY(), inv.getZ());}
				
				btVGet関数は、位置を左手座標系に変換するために使います。btRotVGet関数は、回転角度を左手座標系に変換するために使います。
				これ以降、プログラムで座標を指定するときはbulletに合わせて右手座標系を使うことにします。そうしておけば、
				ゲームの処理→bulletの処理→左手座標系に変換→DXライブラリで表示
				という一方通行で済むので、考え方が簡単になるわけです。
				&#160;
				モデルに対応するボディを物理空間に追加する
				まず、モデルに対応する直方体のボディを追加します。実はここが一番調べるのに時間がかかりました。直方体のボディはbtBoxShapeクラスを使って簡単に作れるのですが、これは常に直方体の中心が原点となります。ところがサンプルで使用するモデルは、足下が原点となっているため、そのままだとボディの位置とモデルの位置がずれてしまうのです。
				APIドキュメントによれば、自由な形のボディを追加したい場合はbtConvexHullShapeクラスを使うらしいのですが、たかだか原点をずらした直方体を作る程度で頂点を細かく設定していくのは面倒です。色々と調べた結果、btCompoundShapeクラスを使うことに思い至りました。btCompoundShapeクラスは複数のシェイプを組み合わせてシェイプを作ります。その際に位置や角度を行列で指定できるのです。
				●main.cpp
				
				//ステージ初期化
void InitStage(){
	//古いアニメーション情報を削除
	EraseAnimInfo(&#38;g_stage.heroanim);

	//ゲームデータ全体のゼロ初期化
	ZeroMemory(&#38;g_stage, sizeof(g_stage));
	//全ボディ・ジョイント削除
	DeleteAllBody();
	SetBasicDemo();

	//主人公位置の初期化
	g_stage.heropos = VGet( 318.0f, 210.0f, -353.0f );
	//アニメーション情報を初期化
	InitAnimInfo(&#38;g_stage.heroanim, g_images.hero, HERO_STAND);
	btCompoundShape *heroshape [...]]]></description>
			<content:encoded><![CDATA[				<p>かなり時間が空いてしまいましたが、BulletとDXライブラリに関する解説の続きです。今回はBulletの計算結果に合わせて、DXライブラリで3Dモデルを表示する方法を解説します。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/08/ws002526.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002526" src="http://i-libro.net/wpmu/files/2011/08/ws002526-thumb.jpg" width="404" height="319" /></a></p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_src02.zip">DXBullet_3DTest_src02.zip</a>（要Visual C++ 2010 Express） </p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_bin02.zip">DXBullet_3DTest_bin02.zip</a>（実行ファイル）</p>
				<p>&#160;</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<p>©CRYPTON FUTURE MEDIA, INC.    <br />解説中で使用しているモデルは前回に続き<a href="http://enamelhp.web.fc2.com/">enamel toy box</a>（ハッチさん運営）で公開されている「<b>PMDねんどろ風初音ミク</b><b>v1.1</b>」</p>
				<p>pmdファイルのダウンロードや組み合わせ方については、<a href="http://i-libro.net/wpmu/blog/archives/876">過去記事</a>も参考にしてください。</p>
				<p>  <span id="more-1094"></span><br />
				<h2>動かしてみよう</h2>
				<p>最初にサンプルプログラムを実行して、結果を確認してください。前回のサンプルを改造したもので、落ちてくるブロックの下にモデルが表示されるようにしています。ブロックがモデルに当たると、回転したり床から落っこちたりします。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/08/ws0025271.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002527" src="http://i-libro.net/wpmu/files/2011/08/ws002527-thumb1.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/08/ws0025281.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002528" src="http://i-libro.net/wpmu/files/2011/08/ws002528-thumb1.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/08/ws0025291.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002529" src="http://i-libro.net/wpmu/files/2011/08/ws002529-thumb1.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/08/ws0025311.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002531" src="http://i-libro.net/wpmu/files/2011/08/ws002531-thumb1.jpg" width="244" height="193" /></a></p>
				<p>&#160;</p>
				<h2>座標系の変換</h2>
				<p>前回記事ではすっかり忘れていたのですが、DXライブラリはDirect3Dと同じ<strong>左手座標系</strong>、Bulletは<strong>右手座標系</strong>なので表示する前に変換してやらなければいけません。そのための関数を数カ所に加えています（座標系については<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<p>「<strong>_dxdebugdraw.h</strong>」の中で定義している<strong>btVGet関数</strong>は、btVector3からVECTOR型に変換するためのものですが、このときにZ軸の正負を反転させます。</p>
				<h4>●_dexdebugdraw.h</h4>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="bcacb253-fb9c-4ebe-9ae4-676c7bbacc1c" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//DXライブラリ用のBox2Dのデバッグドロー

#include &lt;DxLib.h&gt;

#include &lt;LinearMath/btIDebugDraw.h&gt;

class DxDebugDraw : public btIDebugDraw{
private:
	int m_debugMode;
	//座標変換
	inline VECTOR btVGet(const btVector3 &amp;inv){return VGet(inv.getX(), inv.getY(), -inv.getZ());}
public:</pre>
				</div>
				<h4>●main.h</h4>
				<p>上記の関数はDxDebugDrawクラスの中でしか使えないので、同じ働きをする関数を「main.h」にも加えます。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="4f9cbd40-955e-4e49-8047-2286ccc3a63d" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//座標変換
inline VECTOR btVGet(const btVector3 &amp;inv){return VGet(inv.getX(), inv.getY(), -inv.getZ());}
inline VECTOR btRotVGet(const btVector3 &amp;inv){return VGet(-inv.getX(), -inv.getY(), inv.getZ());}</pre>
				</div>
				<p><strong>btVGet関数</strong>は、位置を左手座標系に変換するために使います。<strong>btRotVGet関数</strong>は、回転角度を左手座標系に変換するために使います。</p>
				<p>これ以降、プログラムで座標を指定するときはbulletに合わせて右手座標系を使うことにします。そうしておけば、</p>
				<p><strong>ゲームの処理→bulletの処理→左手座標系に変換→DXライブラリで表示</strong></p>
				<p>という一方通行で済むので、考え方が簡単になるわけです。</p>
				<p>&#160;</p>
				<h2>モデルに対応するボディを物理空間に追加する</h2>
				<p>まず、モデルに対応する直方体のボディを追加します。実はここが一番調べるのに時間がかかりました。直方体のボディは<a href="http://www.bulletphysics.com/Bullet/BulletFull/classbtBoxShape.html" target="_blank">btBoxShapeクラス</a>を使って簡単に作れるのですが、これは常に直方体の中心が原点となります。ところがサンプルで使用するモデルは、<strong>足下が原点</strong>となっているため、そのままだと<strong>ボディの位置とモデルの位置がずれてしまう</strong>のです。</p>
				<p>APIドキュメントによれば、自由な形のボディを追加したい場合は<a href="http://www.bulletphysics.com/Bullet/BulletFull/classbtConvexHullShape.html" target="_blank">btConvexHullShapeクラス</a>を使うらしいのですが、たかだか原点をずらした直方体を作る程度で頂点を細かく設定していくのは面倒です。色々と調べた結果、<a href="http://www.bulletphysics.com/Bullet/BulletFull/classbtCompoundShape.html" target="_blank">btCompoundShapeクラス</a>を使うことに思い至りました。btCompoundShapeクラスは<strong>複数のシェイプを組み合わせて</strong>シェイプを作ります。その際に位置や角度を行列で指定できるのです。</p>
				<h4>●main.cpp</h4>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="4ea1911b-7617-47c1-831a-c6b16b1b50ef" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//ステージ初期化
void InitStage(){
	//古いアニメーション情報を削除
	EraseAnimInfo(&amp;g_stage.heroanim);

	//ゲームデータ全体のゼロ初期化
	ZeroMemory(&amp;g_stage, sizeof(g_stage));
	//全ボディ・ジョイント削除
	DeleteAllBody();
	SetBasicDemo();

	//主人公位置の初期化
	g_stage.heropos = VGet( 318.0f, 210.0f, -353.0f );
	//アニメーション情報を初期化
	InitAnimInfo(&amp;g_stage.heroanim, g_images.hero, HERO_STAND);
	btCompoundShape *heroshape = new btCompoundShape();
	btBoxShape *box = new btBoxShape(btVector3(btScalar(2.5),btScalar(5.),btScalar(2.5)));
	btTransform shift;
	shift.setIdentity();
	shift.setOrigin(btVector3(0,5,0));
	heroshape-&gt;addChildShape(shift, box);
	m_collisionShapes.push_back(heroshape);
	m_collisionShapes.push_back(box);
	//初期位置と角度設定
	btTransform transform, center;
	transform.setIdentity();
	transform.setOrigin(btVector3(g_stage.heropos.x, g_stage.heropos.y, g_stage.heropos.z));
	transform.setRotation(btQuaternion(0, 3.14f, 0, 0));//向き
	btScalar mass(1.);	//質量0なら静的ボディ
	btVector3 localInertia(0,0,0);
	heroshape-&gt;calculateLocalInertia(mass,localInertia);
	btDefaultMotionState* myMotionState = new btDefaultMotionState(transform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,heroshape,localInertia);
	g_stage.herobody = new btRigidBody(rbInfo);
	g_world-&gt;addRigidBody(g_stage.herobody);

	//ゲーム開始時刻の記録
	g_stage.gamestarttime = g_lasttime;
}</pre>
				</div>
				<p>まず、new演算子を使ってbtCompoundShapeのインスタンスを作成して、<strong>ポインタshape</strong>に代入します（16行）。次に（5, 10, 5）というサイズのbtBoxShapeのインスタンスを作成して、<strong>ポインタbox</strong>に代入します（17行）。</p>
				<p>btTransform型の変数shiftを定義し、<strong>setIdentitiy関数</strong>で初期化してから、<strong>setOrigin関数</strong>で<strong>（0,5,0）という移動行列</strong>を設定します（18～20行）。これでボックスは上に5ずらされることになります。</p>
				<p>btCompoundShapeクラスの<strong>addChildShape関数</strong>を使い、shapeにboxを追加します（21行）。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002533" src="http://i-libro.net/wpmu/files/2011/08/ws002533.jpg" width="400" height="238" /></p>
				<p>※サンプルファイルではm_collisionShapesにboxを入れ忘れているので、69行目の後辺りに「m_collisionShapes.push_back(box);」を加えておいてください。そうしなくても動作しますが、deleteAllBody関数がboxを削除してくれないのでメモリリークが起きます。</p>
				<p>ここから先は<a href="http://i-libro.net/wpmu/blog/archives/1066">前回記事</a>の「ボディを追加する」で説明したものとほぼ同じ処理です。</p>
				<p>異なっている点はボディの初期位置を設定するtransformに対して、<strong>setRotation関数</strong>で回転角度を設定している点です。座標系などの都合で、初期設定のままだとモデルが後ろ向きになってしまうため、Y軸で180度回転させています（28行）。</p>
				<p>できあがったボディはg_stage.herobodyに記憶させておきます（34行）。</p>
				<p>&#160;</p>
				<h2>ボディに合わせてモデルを表示する</h2>
				<p>DrawGameMain関数の中で、ボディの位置と角度を調べ、それに合わせてモデルを描画します。こちらはそれほど複雑な処理ではありません。</p>
				<h4>●main.cpp</h4>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="8ae7fc9f-3a47-45c0-9ecb-f5f3130b988f" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void DrawGameMain(){
	//DrawBox(0,0,640,480, 0xFFDDDD, TRUE);
	//キー取得
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);

	int herostate = HERO_STAND;
	if((key &amp; PAD_INPUT_LEFT) || (key &amp; PAD_INPUT_RIGHT)) {
		herostate = HERO_RUN;
	}
	if(key &amp; PAD_INPUT_B){
		herostate = HERO_JUMP;
	}
	if(IsBKeyTrigger(key)==true) GoGameClear();
	//アニメーション設定
	StepAnimTime(&amp;g_stage.heroanim, herostate);

	//移動と表示
	btTransform herotrans;	//bulletから情報を取得
	g_stage.herobody-&gt;getMotionState()-&gt;getWorldTransform(herotrans);
	//　位置取得
	g_stage.heropos = btVGet(herotrans.getOrigin());
	MV1SetPosition(g_stage.heroanim.model, g_stage.heropos);
	//　角度取得
	btMatrix3x3 rot = herotrans.getBasis();
	btVector3 euler;
	rot.getEulerZYX(euler[2], euler[1], euler[0]);
	MV1SetRotationXYZ(g_stage.heroanim.model, btRotVGet(euler));
	MV1DrawModel(g_stage.heroanim.model) ;

	//カメラの設定
	SetCameraPositionAndTarget_UpVecY(btVGet(btVector3(320.0f, 240.0f, -420.0f)),
		 btVGet(btVector3(320.0f, 210.0f, -310.0f) ) );
	//ちょっとした視点変更
	if(key &amp; PAD_INPUT_C){
		SetCameraPositionAndTarget_UpVecY(btVGet(btVector3(320.0f, 240.0f, -450.0f)),
			g_stage.heropos );
	}
	SetCameraNearFar(10, 1000);
	SetupCamera_Perspective( PHI_F / 5 );
	//SetupCamera_Ortho(150);
	//テキスト表示
	DrawStringToHandle(60, 0, "Xキーでタイトルへ、Cキーで視点変更",
		0xFFFF00, g_middlefont);
}</pre>
				</div>
				<p>btTransform型の変数herotransを定義します（18行）。btRidigBodyクラスのgetMotionState関数で<a href="http://www.bulletphysics.com/Bullet/BulletFull/classbtMotionState.html" target="_blank">btMotionStateクラス</a>のインスタンスを取得し、さらにその<strong>getWorldTransform関数</strong>を呼び出して変形行列を取得します（19行）。APIリファレンスを見る限り、btMotionStateクラスは変形行列を記憶しておく程度の役割しかないようです。</p>
				<p>位置は<strong>btTransformクラス</strong>の<strong>getOrigin関数</strong>で取得できます。ここでbtVGet関数を利用して左手座標系に変換します（21行）。後はDXライブラリの関数でモデルに位置を設定します。</p>
				<p>角度はまず<strong>getBasis関数</strong>で3&#215;3行列を取り出し、<strong>getEulerZYX関数</strong>でX、Y、Z軸それぞれの回転角度を取り出します（24～26行）。ちなみにEuler（オイラー）は<a href="http://ja.wikipedia.org/wiki/%E3%82%AA%E3%82%A4%E3%83%A9%E3%83%BC%E8%A7%92" target="_blank">オイラー角</a>のことです。後はそれをbtRotVGet関数で左手座標系に変換し、DXライブラリの関数で設定します（27行）。</p>
				<p>DXライブラリでのモデル表示やアニメーションについては過去記事を参照してください（<a href="http://i-libro.net/wpmu/blog/archives/824">過去記事1</a>、<a href="http://i-libro.net/wpmu/blog/archives/876">過去記事2</a>）。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/1094/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門第2部】物理エンジンBulletとDXライブラリを組み合わせて使う その2</title>
		<link>http://i-libro.net/wpmu/blog/archives/1066</link>
		<comments>http://i-libro.net/wpmu/blog/archives/1066#comments</comments>
		<pubDate>Sun, 29 May 2011 18:02:00 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/1066</guid>
		<description><![CDATA[				前回記事に続いてBulletエンジンとDXライブラリを組み合わせて使う方法を説明していきます。
				
				DXBullet_3DTest_src01.zip（要Visual C++ 2010 Express）
				DXBullet_3DTest_bin01.zip（実行ファイル）
				  
				&#160;
				Bulletの使い方も基本的な部分はBox2Dと同じです。すなわち、
				
				最初にワールドを作る 
				ワールドにボディ（rigid body＝剛体）を追加する 
				定期的にstepSimulation関数を呼び出す 
				
				という流れは同じなのです。ただし、Bulletはいくつかのコンポーネントに分かれていて、必要な部分だけを組み合わせて利用できるような設計になっています。その分、Box2Dより複雑です。また、結構重いです。3Dのゲームが満足に動くスペックのパソコンがあったほうがいいでしょう。
				ここでは前に作ったBox2D用のサンプルプログラムを元に、Bulletに置き換える形で改造しました。
				&#160;
				デバッグドロー用のコードを書く
				まずは共通点が多いデバッグドローの部分から移植することにします。デバッグドローというのは、テスト用にボディを簡易描画する機能です。物理エンジンを使うときは物理エンジンが算出した座標、角度などに合わせて、DirectX、OpenGL、DXライブラリなどの描画APIを使って3Dモデルを描いていくのですが、その処理に間違いがあると、物理エンジンの結果と画面に表示されたものが合わなくなってしまいます。こういうときに物理エンジンのデバッグドローを使えば、物理エンジンがどういう結果を出しているのかを直接見ることができるわけです。
				まず、Bulletのサンプルからデバッグドローを担当しているクラスを探し、そのソースコードをコピーします。中身はOpenGL用になっているので、それをDXライブラリ用に書き換えていきます。
				ヘッダファイルは、ほぼコピペしてクラス名を変えたぐらいですが、11行目でbtVGetという独自の関数を宣言しています。これはBulletが使うbtVector3構造体を受け取り、DXライブラリ用のVECTOR構造体を返す関数です。
				●_dxdebugdraw.h
				
				//DXライブラリ用のBox2Dのデバッグドロー

#include &#60;DxLib.h&#62;

#include &#60;LinearMath/btIDebugDraw.h&#62;

class DxDebugDraw : public btIDebugDraw{
private:
	int m_debugMode;
	//座標変換
	inline VECTOR btVGet(const btVector3 &#38;inv){return VGet(inv.getX(), inv.getY(), inv.getZ());}
public:
	DxDebugDraw();
	virtual void drawLine(const btVector3&#38; from,const btVector3&#38; to,const btVector3&#38; fromColor, const btVector3&#38; toColor);
	virtual void drawLine(const btVector3&#38; from,const btVector3&#38; to,const btVector3&#38; color);
	virtual void drawSphere (const btVector3&#38; p, btScalar radius, const btVector3&#38; color);
	virtual void drawBox [...]]]></description>
			<content:encoded><![CDATA[				<p>前回記事に続いてBulletエンジンとDXライブラリを組み合わせて使う方法を説明していきます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws0022191.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002219" src="http://i-libro.net/wpmu/files/2011/05/ws002219-thumb1.jpg" width="504" height="398" /></a></p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_src01.zip">DXBullet_3DTest_src01.zip</a>（要Visual C++ 2010 Express）</p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_bin01.zip">DXBullet_3DTest_bin01.zip</a>（実行ファイル）</p>
				<p>  <span id="more-1066"></span>
				<p>&#160;</p>
				<p>Bulletの使い方も基本的な部分はBox2Dと同じです。すなわち、</p>
				<ol>
				<li>最初にワールドを作る </li>
				<li>ワールドにボディ（rigid body＝剛体）を追加する </li>
				<li>定期的にstepSimulation関数を呼び出す </li>
				</ol>
				<p>という流れは同じなのです。ただし、Bulletはいくつかのコンポーネントに分かれていて、必要な部分だけを組み合わせて利用できるような設計になっています。その分、Box2Dより複雑です。また、結構重いです。3Dのゲームが満足に動くスペックのパソコンがあったほうがいいでしょう。</p>
				<p>ここでは前に作ったBox2D用のサンプルプログラムを元に、Bulletに置き換える形で改造しました。</p>
				<p>&#160;</p>
				<h2>デバッグドロー用のコードを書く</h2>
				<p>まずは共通点が多い<strong>デバッグドロー</strong>の部分から移植することにします。デバッグドローというのは、テスト用にボディを簡易描画する機能です。物理エンジンを使うときは物理エンジンが算出した座標、角度などに合わせて、DirectX、OpenGL、DXライブラリなどの描画APIを使って3Dモデルを描いていくのですが、その処理に間違いがあると、物理エンジンの結果と画面に表示されたものが合わなくなってしまいます。こういうときに物理エンジンのデバッグドローを使えば、物理エンジンがどういう結果を出しているのかを直接見ることができるわけです。</p>
				<p>まず、Bulletのサンプルからデバッグドローを担当しているクラスを探し、そのソースコードをコピーします。中身はOpenGL用になっているので、それをDXライブラリ用に書き換えていきます。</p>
				<p>ヘッダファイルは、ほぼコピペしてクラス名を変えたぐらいですが、11行目で<strong>btVGet</strong>という独自の関数を宣言しています。これはBulletが使う<strong>btVector3構造体</strong>を受け取り、DXライブラリ用の<strong>VECTOR構造体</strong>を返す関数です。</p>
				<p>●_dxdebugdraw.h</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="0805e395-6787-414f-92f1-7c323a37f5ff" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//DXライブラリ用のBox2Dのデバッグドロー

#include &lt;DxLib.h&gt;

#include &lt;LinearMath/btIDebugDraw.h&gt;

class DxDebugDraw : public btIDebugDraw{
private:
	int m_debugMode;
	//座標変換
	inline VECTOR btVGet(const btVector3 &amp;inv){return VGet(inv.getX(), inv.getY(), inv.getZ());}
public:
	DxDebugDraw();
	virtual void drawLine(const btVector3&amp; from,const btVector3&amp; to,const btVector3&amp; fromColor, const btVector3&amp; toColor);
	virtual void drawLine(const btVector3&amp; from,const btVector3&amp; to,const btVector3&amp; color);
	virtual void drawSphere (const btVector3&amp; p, btScalar radius, const btVector3&amp; color);
	virtual void drawBox (const btVector3&amp; boxMin, const btVector3&amp; boxMax, const btVector3&amp; color, btScalar alpha);
	virtual void drawTriangle(const btVector3&amp; a,const btVector3&amp; b,const btVector3&amp; c,const btVector3&amp; color,btScalar alpha);
	virtual void drawContactPoint(const btVector3&amp; PointOnB,const btVector3&amp; normalOnB,btScalar distance,int lifeTime,const btVector3&amp; color);
	virtual void reportErrorWarning(const char* warningString);
	virtual void draw3dText(const btVector3&amp; location,const char* textString);
	virtual void setDebugMode(int debugMode);
	virtual int	getDebugMode() const { return m_debugMode;}
};</pre>
				</div>
				<p>cppファイルの中身はDXライブラリの<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/category0.html#func0">3D図形描画関数</a>を使って、だいたい同じ結果になるようにしています。</p>
				<p>●_dxdebugdraw.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="58657c69-7f50-49d1-99e5-7005ee10670e" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//DXライブラリ用のBox2Dのデバッグドロー

#include "_dxdebugdraw.h"

//コンストラクタ
DxDebugDraw::DxDebugDraw()
:m_debugMode(0)
{

}

void DxDebugDraw::drawLine(const btVector3&amp; from,const btVector3&amp; to,const btVector3&amp; fromColor, const btVector3&amp; toColor)
{
	DrawLine3D(btVGet(from), btVGet(to),
		GetColor( int(fromColor.getX()*255), int(fromColor.getY()*255), int(fromColor.getZ()*255) )
		);
}

void DxDebugDraw::drawLine(const btVector3&amp; from,const btVector3&amp; to,const btVector3&amp; color)
{
	drawLine(from,to,color,color);
}

void DxDebugDraw::drawSphere (const btVector3&amp; p, btScalar radius, const btVector3&amp; color)
{
	DrawSphere3D(btVGet(p), radius, 10,
		GetColor( int(color.getX()*255), int(color.getY()*255), int(color.getZ()*255) )
		, 0xFFFFFF, TRUE);
}
……後略……</pre>
				</div>
				<h2>ワールドを作る</h2>
				<p>いくつかのグローバル変数を定義していきます。main.cppには<strong>btDynamicsWorld型</strong>のポインタg_worldを定義します。Bulletにはワールドのためのクラスが数種類があり、btDynamicsWorld型その元となる<strong>抽象クラス</strong>です。そのサブクラスのbtDiscreteDynamicsWorldクラスやbtSoftRigidDynamicsWorldクラスのインスタンスを作成して、ポインタに代入します。ワールド用のクラスは4種類ぐらいあり、どう違うのかは今のところ調べ切れていません。単純な剛体での物理演算ではbtDiscreteDynamicsWorldクラスを使うようです。</p>
				<p>その後のbtClockは時間計測用のクラスですが結局使っていません。</p>
				<p>●main.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="75cfa59d-a200-4a2d-9d85-1c56a6fe9d6e" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">#include "main.h"

//グローバル変数
GameState g_gamestate = GAME_TITLE;

//box2d関連
btDynamicsWorld*	g_world;
btClock m_clock;
</pre>
				</div>
				<p>_utils.cppでは、<strong>DxDebugDraw型変数</strong>のg_debugdrawを定義します。これは後でg_worldに設定してやります。</p>
				<p>他に5つの変数やポインタを定義しています（10～14行目）。<strong>btAlignedObjectArray</strong>はボディの形（シェイプ）を記憶するコレクションクラスです。他の4つの用途は調べ切れていませんが、World用クラスのインスタンスを作る際に必要なものです。どうやら独自の衝突判定処理を書きたいときに、これらのサブクラスを作るようです。</p>
				<p>●_utils.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="bece6d92-df79-4b1b-a368-00454b836e3d" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//デバッグドロー
#ifdef  B2D_DEBUG_DRAW
DxDebugDraw g_debugdraw;
#endif
//フォント
int g_middlefont;			//中サイズフォントハンドル

//keep the collision shapes, for deletion/cleanup
btAlignedObjectArray&lt;btCollisionShape*&gt;	m_collisionShapes;
btBroadphaseInterface*	m_broadphase;
btCollisionDispatcher*	m_dispatcher;
btConstraintSolver*	m_solver;
btDefaultCollisionConfiguration* m_collisionConfiguration;
</pre>
				</div>
				<p>ワールドを作る処理は<strong>initBullet関数</strong>にまとめました。この関数はWinMain関数でメインループを始める前に呼び出すようにしています。ソースコードを三手の通り、いくつかのクラスのインスタンスを作って各ポインタに代入していき、最後に<strong>setGravity関数</strong>で重力を設定します。色々と謎な部分があるのですが、今回の例ではこのとおりにやっておけば問題ないようです。</p>
				<p>●_utils.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="58147132-cdda-4aa8-b7c0-a3f59c4a37a4" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void initBullet(){
	//デフォルトの衝突処理を登録？
	///collision configuration contains default setup for memory, collision setup
	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	//m_collisionConfiguration-&gt;setConvexConvexMultipointIterations();
	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);

	//衝突判定を効率化するためのもの？
	m_broadphase = new btDbvtBroadphase();

	///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
	btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
	m_solver = sol;

	//ワールド作成
	g_world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);

	//重力設定
	g_world-&gt;setGravity(btVector3(0,-10,0));

}</pre>
				</div>
				<p>&#160;</p>
				<p>&#160;</p>
				<h2>ボディを追加する</h2>
				<p>ボディを追加する処理はmain.cppの<strong>SetBasicDemo関数</strong>にまとめました。下記は「地面」の役割をするスタティックボディを追加している部分です。この後に上から落下するダイナミックボディを追加する処理が続きます。</p>
				<p>●main.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="71895260-588e-4380-8c3f-cccd8e60df63" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void SetBasicDemo(){
	//地形のシェイプを作成
	{
		///create a few basic rigid bodies
		btCollisionShape* groundShape =
			new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
	//	btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);

		//衝突判定に登録
		m_collisionShapes.push_back(groundShape);

		//地形の位置を設定？
		btTransform groundTransform;
		groundTransform.setIdentity();
		groundTransform.setOrigin(btVector3( 320.0f, 160.0f, -350.0f));

		//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
		//質量と慣性の設定？
		btScalar mass(0.);	//質量0なら静的ボディ
		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);
		btVector3 localInertia(0,0,0);
		if (isDynamic){
			groundShape-&gt;calculateLocalInertia(mass,localInertia);
		}

		//シェイプから剛体を作成？
		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
		btRigidBody* body = new btRigidBody(rbInfo);

		//ワールドに配置
		//add the body to the dynamics world
		g_world-&gt;addRigidBody(body);
	}
……後略……</pre>
				</div>
				<p>まず、<strong>btCollisionShapeクラス</strong>のインスタンスを作成します（5～6行）。btBoxShape（箱）の他にbtSphereShape（球）など色々な種類があります。以下のクラス構成図を参考にしてください。ここでは（50, 50, 50）と指定しているので、<strong>一辺の長さ100の立方体</strong>が作られます。</p>
				<p><a href="http://www.continuousphysics.com/Bullet/BulletFull/classbtCollisionShape.html">http://www.continuousphysics.com/Bullet/BulletFull/classbtCollisionShape.html</a></p>
				<p>作成したシェイプはbtAlignedObjectArray型のm_collisionShapesにpush_back関数で登録します。これはおそらく衝突判定で使用されるはずです（10行）。</p>
				<p>次に初期位置を<strong>btTransform型変数</strong>に記憶します（13～15行）。</p>
				<p>質量（mass）と慣性（localInertia）の値を設定します。massを0にすると動かない<strong>スタティックボディ</strong>に、0より大きい値にすると<strong>ダイナミックボディ</strong>になります。ダイナミックボディにするときは<strong>calculateLocalInertia関数</strong>で質量と慣性を設定します（19～25行）。</p>
				<p>btTransform型変数を引数にして、<strong>btDefaultMotionState型</strong>のインスタンスを作成します。これはボディの位置と重心位置を設定するためのもののようです（29行）。</p>
				<p>これまで作ってきたいくつかのインスタンスを引数にして、<strong>btRigidBodyConstrucionInfo型</strong>のインスタンスを作成し、それを引数にして<strong>btRigidBody型</strong>のインスタンスを作成します（30～31行）。</p>
				<p>最後に<strong>addRigidBody関数</strong>でワールドに追加します。</p>
				<p>ボディの反発率や摩擦力、速度などはbtRigidBodyクラスのメンバ関数で設定します。</p>
				<p><a title="http://www.continuousphysics.com/Bullet/BulletFull/classbtRigidBody.html" href="http://www.continuousphysics.com/Bullet/BulletFull/classbtRigidBody.html">http://www.continuousphysics.com/Bullet/BulletFull/classbtRigidBody.html</a></p>
				<p>&#160;</p>
				<h2>シミュレーションを進める</h2>
				<p>後は定期的に<strong>stepSimulation関数</strong>を呼び出せば、Bulletが各ボディの位置を計算で求めてくれます。stepSimulation関数の第1引数に進めたい時間をミリ秒で指定しますが、この値が使われるのは<strong>第2引数が0</strong>のときです。第2引数が1以上だとデフォルト値の<strong>60分の1秒（もしくは第3引数に指定した値）</strong>で計算を進めます。Bulletは60fpsの動作に最適化されているらしいのですが、ここでは低スペックのパソコンでも動くよう0を指定して、現実の経過時間に合わせた動きにしています。</p>
				<p>※追記：どうも第2引数に0を指定すると、挙動にムラが出過ぎる印象です。「stepSimulation(g_frametime, 1, 1.0f/30.0f);」として30fpsとするか、「stepSimulation(g_frametime);」として60fpsのまま使ったほうがいいような気がしてきました。</p>
				<p>●main.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="97901820-36d2-4088-a1b7-ba2278c16d06" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//メインループ
void MyMain(){
	//ゲーム開始からの時間を計る
	g_stage.gametime = g_lasttime - g_stage.gamestarttime;
	//b2bの時間を進める
	g_world-&gt;stepSimulation(g_frametime, 0);
	//各画面の描画
	switch(g_gamestate){
	case GAME_TITLE:
		DrawGameTitle();
		break;
	case GAME_MAIN:
		DrawGameMain();
		break;
	case GAME_CLEAR:
		DrawGameClear();
		break;
	case GAME_OVER:
		DrawGameOver();
		break;
	}
}</pre>
				</div>
				<p>デバッグドローで描画するには、メインループが始まる前に<strong>setDebugDrawer関数</strong>でデバッグドロー用関数のインスタンスを設定し、<strong>setDebugMode関数</strong>で何を描画するかを設定します（12～13行）。そして、メインループの中で<strong>debugDrawWorld関数</strong>を呼び出します。</p>
				<p>●_utils.cpp</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="b5a439ff-f382-4c0b-a528-771fdd430b98" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//3Dエンジンバレット初期化
	initBullet();

	SetDrawScreen( DX_SCREEN_BACK );
	//ファイルの読み込み
	if( LoadFiles() == -1) {
		MessageBox(NULL, "ファイル読み込み失敗", "DXライブラリ", MB_OK);
		return -1;
	}
	//デバッグドロー用
#ifdef B2D_DEBUG_DRAW
	g_world-&gt;setDebugDrawer(&amp;g_debugdraw);
	g_world-&gt;getDebugDrawer()-&gt;setDebugMode(btIDebugDraw::DBG_DrawWireframe);
#endif

	g_lasttime = GetNowCount() &amp; INT_MAX;	//現在時刻の記録
	while(	ProcessMessage() == 0 &amp;&amp; g_exitflag==FALSE )
	{
		//1ループにかかった時間を計測
		int curtime = GetNowCount() &amp; INT_MAX;
		g_frametime = (float)(curtime - g_lasttime) / 1000.0f;
		g_lasttime = curtime;
		//フレーム間隔が異常に延びた場合は0.03秒とする
		if (g_frametime &gt; 0.03f) g_frametime = 0.03f;

		ClsDrawScreen();
		MyMain();
		//デバッグドロー
#ifdef B2D_DEBUG_DRAW
		g_world-&gt;debugDrawWorld();
#endif
		ScreenFlip();
	}</pre>
				</div>
				<h2>すべてのボディを削除する</h2>
				<p>サンプルプログラムでは、Xキーを押すとタイトル画面に戻り、すべてのボディを削除します。この処理を見ると、すべてのボディを列挙する方法がわかります。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="02fe8868-23c3-478f-a47f-a9a77dda53cb" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//全ボディの削除
void DeleteAllBody(){
	//cleanup in the reverse order of creation/initialization

	//remove the rigidbodies from the dynamics world and delete them
	int i;
	for (i=g_world-&gt;getNumCollisionObjects()-1; i&gt;=0 ;i--)
	{
		btCollisionObject* obj = g_world-&gt;getCollisionObjectArray()[i];
		btRigidBody* body = btRigidBody::upcast(obj);
		if (body &amp;&amp; body-&gt;getMotionState())
		{
			delete body-&gt;getMotionState();
		}
		g_world-&gt;removeCollisionObject( obj );
		delete obj;
	}

	//delete collision shapes
	for (int j=0;j&lt;m_collisionShapes.size();j++)
	{
		btCollisionShape* shape = m_collisionShapes[j];
		delete shape;
	}
	m_collisionShapes.clear();
}</pre>
				</div>
				<p>ボディを削除するには、<strong>getNumCollisionObjects関数</strong>で総数を調べて逆順のループをし、<strong>getCollisionObjectArray関数</strong>で1つずつ取り出して削除していきます（7～9行）。</p>
				<p>削除するときはまずgetMotionState関数で<strong>btMotionState</strong>のインスタンスを削除し、その後<strong>removeCollistionObject関数</strong>でボディを削除しないといけないようです（11～16行）。</p>
				<p>その後はシェイプをすべて削除します（20～25行）。</p>
				<p>&#160;</p>
				<p>&#160;</p>
				<p>以上で説明は終わりです。ここからゲーム作りに持って行くには、最低でも</p>
				<ul>
				<li>btRigitBodyの扱い方 </li>
				<li>衝突判定の使い方 </li>
				<li>描画するべきボディを列挙する方法 </li>
				</ul>
				<p>などを調べなければいけないでしょう。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/1066/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門第2部】物理エンジンBulletとDXライブラリを組み合わせて使う　その1</title>
		<link>http://i-libro.net/wpmu/blog/archives/1059</link>
		<comments>http://i-libro.net/wpmu/blog/archives/1059#comments</comments>
		<pubDate>Sun, 29 May 2011 15:44:27 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/1059</guid>
		<description><![CDATA[				ほぼ3ヶ月ぶりの更新です。今回解説するのは、DXライブラリと3D用物理エンジンBullet（バレット）を組み合わせて使う方法です。Box2Dと基本的な考え方は似ているのですが、細かいところが色々と難しいですね。とりあえずBulletの一番簡単なBasicDemoを移植できたので、そこまでを解説します。
				－ブロックが床に落下して飛び散る。
				DXBullet_3DTest_src01.zip（要Visual C++ 2010 Express）
				DXBullet_3DTest_bin01.zip（実行ファイル）
				  
				Bulletをダウンロードする
				まずは公式サイトからBulletをダウンロードします。
				http://bulletphysics.org/wordpress/
				－左上に小さく表示されている「Bullet Download」をクリック
				－一番上の「bullet-278.zip」をダウンロードして解凍する
				解凍したファイルを適当な場所に保存します。適当といっても、VCディレクトリで参照するので後から移動しなくてもいいところにしてください。今回は「c:\temp」というフォルダに保存しました。
				解凍したフォルダ内の「msvc」フォルダに、Visual C++ 2008用のソースコードが格納されているので、それを開きます。
				－「msvc」を開く
				「2008」「2008_amd_opencl」「2008_dx11_directcompute」の3種類があります。DXライブラリはDirectX9ベースなので、「2008」の中のソースコードを使うことにします。ちなみdx11用は筆者のノートパソコンでは重すぎて動かせませんでした。
				－「2008」を開く
				－slnファイルをダブルクリック
				－「Visual C++ 2010」を選ぶ
				－「完了」をクリックしてVC++2010用に変換
				&#160;
				これをビルドすると、コンパイルとリンクは無事終わるはずですが、最後に「指定されたファイルが見つかりません」というエラーが表示されます。これはプロパティ設定で、実行ファイルを4階層上のフォルダに出力するようになっているためです。
				－ビルドにはちょっと時間がかかる
				－エラーが出て起動できない。
				&#160;
				Bulletのフォルダに移動すると、「AppAllBulletDemos.exe」というファイルができているはずです。なぜ、ここに作るかというと、デモプログラムがこのフォルダの中にあるOpenGL用のdllファイルを使用するからです。ダブルクリックして実行すると、デモを起動することができます。
				－AppAllBulletDemos.exeをダブルクリック
				－右上の「Tests」でデモの種類を選ぶ
				&#160;
				DXライブラリ用にビルドし直す
				このプロジェクトが出力する「lib」ファイルを利用するのですが、その前にDXライブラリに合わせてビルドし直す必要があります。変更が必要なのは1点、「ランタイムライブラリ」を「マルチスレッドデバッグdll」から「マルチスレッドデバッグ」に変更することです。リリースビルド用のlibファイルを作りたい場合は、「マルチスレッド」を選びます。
				－「Shift」キーを押しながらクリックして、全プロジェクトを選択し、右クリックして「プロパティ」を選択
				－「構成プロパティ」→「C/C++」→「コード生成」を選択し、「ラインタイムライブラリ」から「マルチスレッドデバッグ（/MTd）」を選択
				またビルドし直すと、「lib」フォルダ内の「Debug」フォルダの中に大量のlibファイルが作られます。
				
				&#160;
				DXライブラリでBulletを使うためのプロジェクト設定
				自分で作ったプログラムでBulletを使うには、それに合わせたプロジェクト設定をしなければいけません。「AppAllBulletDemos」プロジェクトのプロパティを参考にしながら設定していきます。
				プロジェクトを作成したら、まずはVC++ディレクトリを設定して、Box2DではなくBulletのフォルダを参照させます。
				－「構成プロパティ」→「VC++ディレクトリ」を選択
				－Bulletのフォルダのsrcフォルダを指定
				－先ほどビルドして作ったlibファイルがあるDebugフォルダを指定
				「全般」設定はふだんDXライブラリを使うときと同じはずです。
				
				「C/C++」→「コード生成」では、「拡張命令セットを有効にする」で「ストリーミングSIMD拡張機能」を選びます。
				
				「リンカー」→「入力」で追加の依存ファイルの設定を行います。
				
				
				追加するのは次の表のとおりです。「AppAllBulletDemos」プロジェクトの設定を参考にし、そこからOpenGL周りの設定を抜きました。間違えるとビルドできないので、ここからコピー＆ペーストしたほうがいいでしょう。
				
				
				
				
				ConvexDecomposition.lib            BulletMultiThreaded.lib             BulletWorldImporter.lib             BulletSoftBody.lib       [...]]]></description>
			<content:encoded><![CDATA[				<p>ほぼ3ヶ月ぶりの更新です。今回解説するのは、DXライブラリと<strong>3D用物理エンジンBullet（バレット）</strong>を組み合わせて使う方法です。Box2Dと基本的な考え方は似ているのですが、細かいところが色々と難しいですね。とりあえずBulletの一番簡単な<strong>BasicDemo</strong>を移植できたので、そこまでを解説します。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002216.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002216" src="http://i-libro.net/wpmu/files/2011/05/ws002216-thumb.jpg" width="304" height="181" /></a><a href="http://i-libro.net/wpmu/files/2011/05/ws002219.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002219" src="http://i-libro.net/wpmu/files/2011/05/ws002219-thumb.jpg" width="304" height="182" /></a>－ブロックが床に落下して飛び散る。</p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_src01.zip">DXBullet_3DTest_src01.zip</a>（要Visual C++ 2010 Express）</p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXBullet_3DTest_bin01.zip">DXBullet_3DTest_bin01.zip</a>（実行ファイル）</p>
				<p>  <span id="more-1059"></span><br />
				<h2>Bulletをダウンロードする</h2>
				<p>まずは公式サイトからBulletをダウンロードします。</p>
				<p><a href="http://bulletphysics.org/wordpress/">http://bulletphysics.org/wordpress/</a></p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002148.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002148" src="http://i-libro.net/wpmu/files/2011/05/ws002148-thumb.jpg" width="404" height="267" /></a>－左上に小さく表示されている「<a href="http://code.google.com/p/bullet/downloads/list">Bullet Download</a>」をクリック</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002149.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002149" src="http://i-libro.net/wpmu/files/2011/05/ws002149-thumb.jpg" width="404" height="122" /></a>－一番上の「bullet-278.zip」をダウンロードして解凍する</p>
				<p>解凍したファイルを適当な場所に保存します。適当といっても、VCディレクトリで参照するので後から移動しなくてもいいところにしてください。今回は「c:\temp」というフォルダに保存しました。</p>
				<p>解凍したフォルダ内の「msvc」フォルダに、Visual C++ 2008用のソースコードが格納されているので、それを開きます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002221.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002221" src="http://i-libro.net/wpmu/files/2011/05/ws002221-thumb.jpg" width="504" height="383" /></a>－「msvc」を開く</p>
				<p>「2008」「2008_amd_opencl」「2008_dx11_directcompute」の3種類があります。DXライブラリはDirectX9ベースなので、「2008」の中のソースコードを使うことにします。ちなみdx11用は筆者のノートパソコンでは重すぎて動かせませんでした。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002158.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002158" src="http://i-libro.net/wpmu/files/2011/05/ws002158-thumb.jpg" width="504" height="184" /></a>－「2008」を開く</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002222.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002222" src="http://i-libro.net/wpmu/files/2011/05/ws002222-thumb.jpg" width="504" height="319" /></a>－slnファイルをダブルクリック</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002159.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002159" src="http://i-libro.net/wpmu/files/2011/05/ws002159-thumb.jpg" width="344" height="144" /></a>－「Visual C++ 2010」を選ぶ</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002160.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002160" src="http://i-libro.net/wpmu/files/2011/05/ws002160-thumb.jpg" width="344" height="338" /></a>－「完了」をクリックしてVC++2010用に変換</p>
				<p>&#160;</p>
				<p>これをビルドすると、コンパイルとリンクは無事終わるはずですが、最後に「指定されたファイルが見つかりません」というエラーが表示されます。これはプロパティ設定で、実行ファイルを<strong>4階層上のフォルダに出力する</strong>ようになっているためです。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002175.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002175" src="http://i-libro.net/wpmu/files/2011/05/ws002175-thumb.jpg" width="509" height="194" /></a>－ビルドにはちょっと時間がかかる</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002174.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002174" src="http://i-libro.net/wpmu/files/2011/05/ws002174-thumb.jpg" width="404" height="202" /></a>－エラーが出て起動できない。</p>
				<p>&#160;</p>
				<p>Bulletのフォルダに移動すると、「AppAllBulletDemos.exe」というファイルができているはずです。なぜ、ここに作るかというと、デモプログラムがこのフォルダの中にあるOpenGL用のdllファイルを使用するからです。ダブルクリックして実行すると、デモを起動することができます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002176.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002176" src="http://i-libro.net/wpmu/files/2011/05/ws002176-thumb.jpg" width="404" height="307" /></a>－AppAllBulletDemos.exeをダブルクリック</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002185.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002185" src="http://i-libro.net/wpmu/files/2011/05/ws002185-thumb.jpg" width="504" height="269" /></a>－右上の「Tests」でデモの種類を選ぶ</p>
				<p>&#160;</p>
				<h2>DXライブラリ用にビルドし直す</h2>
				<p>このプロジェクトが出力する「lib」ファイルを利用するのですが、その前にDXライブラリに合わせてビルドし直す必要があります。変更が必要なのは1点、「<strong>ランタイムライブラリ」を「マルチスレッドデバッグdll」から「マルチスレッドデバッグ」に変更</strong>することです。リリースビルド用のlibファイルを作りたい場合は、「マルチスレッド」を選びます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002201.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002201" src="http://i-libro.net/wpmu/files/2011/05/ws002201-thumb.jpg" width="404" height="341" /></a>－「Shift」キーを押しながらクリックして、全プロジェクトを選択し、右クリックして「プロパティ」を選択</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002223.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002223" src="http://i-libro.net/wpmu/files/2011/05/ws002223-thumb.jpg" width="504" height="204" /></a>－「構成プロパティ」→「C/C++」→「コード生成」を選択し、「ラインタイムライブラリ」から「マルチスレッドデバッグ（/MTd）」を選択</p>
				<p>またビルドし直すと、「lib」フォルダ内の「Debug」フォルダの中に大量のlibファイルが作られます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002182.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002182" src="http://i-libro.net/wpmu/files/2011/05/ws002182-thumb.jpg" width="404" height="192" /></a></p>
				<p>&#160;</p>
				<h2>DXライブラリでBulletを使うためのプロジェクト設定</h2>
				<p>自分で作ったプログラムでBulletを使うには、それに合わせたプロジェクト設定をしなければいけません。「AppAllBulletDemos」プロジェクトのプロパティを参考にしながら設定していきます。</p>
				<p>プロジェクトを作成したら、まずはVC++ディレクトリを設定して、Box2DではなくBulletのフォルダを参照させます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002186.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002186" src="http://i-libro.net/wpmu/files/2011/05/ws002186-thumb.jpg" width="504" height="139" /></a>－「構成プロパティ」→「VC++ディレクトリ」を選択</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002189.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002189" src="http://i-libro.net/wpmu/files/2011/05/ws002189-thumb.jpg" width="404" height="127" /></a>－Bulletのフォルダのsrcフォルダを指定</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002191.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002191" src="http://i-libro.net/wpmu/files/2011/05/ws002191-thumb.jpg" width="404" height="134" /></a>－先ほどビルドして作ったlibファイルがあるDebugフォルダを指定</p>
				<p>「全般」設定はふだんDXライブラリを使うときと同じはずです。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002194.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002194" src="http://i-libro.net/wpmu/files/2011/05/ws002194-thumb.jpg" width="504" height="219" /></a></p>
				<p>「C/C++」→「コード生成」では、「拡張命令セットを有効にする」で「ストリーミングSIMD拡張機能」を選びます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws0022231.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002223" src="http://i-libro.net/wpmu/files/2011/05/ws002223-thumb1.jpg" width="504" height="192" /></a></p>
				<p>「リンカー」→「入力」で追加の依存ファイルの設定を行います。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002226.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002226" src="http://i-libro.net/wpmu/files/2011/05/ws002226-thumb.jpg" width="504" height="158" /></a></p>
				<p><a href="http://i-libro.net/wpmu/files/2011/05/ws002197.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS002197" src="http://i-libro.net/wpmu/files/2011/05/ws002197-thumb.jpg" width="404" height="141" /></a></p>
				<p>追加するのは次の表のとおりです。「AppAllBulletDemos」プロジェクトの設定を参考にし、そこからOpenGL周りの設定を抜きました。間違えるとビルドできないので、ここからコピー＆ペーストしたほうがいいでしょう。</p>
				<table border="0" cellspacing="0" cellpadding="2" width="522">
				<tbody>
				<tr>
				<td valign="top" width="522">
				<p>ConvexDecomposition.lib            <br />BulletMultiThreaded.lib             <br />BulletWorldImporter.lib             <br />BulletSoftBody.lib             <br />BulletDynamics.lib             <br />BulletCollision.lib             <br />BulletFileLoader.lib             <br />LinearMath.lib</p>
				</td>
				</tr>
				</tbody>
				</table>
				<p>&#160;</p>
				<p>長くなったので、ここで一区切りとします。次の記事ではサンプルのソースコードの中身について説明していきます。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/1059/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】2Dに合わせて3Dグラフィックスを描画する その3</title>
		<link>http://i-libro.net/wpmu/blog/archives/1010</link>
		<comments>http://i-libro.net/wpmu/blog/archives/1010#comments</comments>
		<pubDate>Mon, 21 Mar 2011 02:01:31 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/1010</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				
				引き続き前々回記事で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。今回説明するのは表示範囲内にあるモデルを絞り込む方法です。範囲内の物体を高速に行うのは意外と面倒なのですが、ここではBox2DのQueryAABBという関数を使います。AABBは「Axis Aligned Bounding Box」の略で、「軸に沿った範囲を表す矩形」という意味になります。軸に沿わない――つまり回転もありうる矩形に比べると、高速に判定ができるわけです。
				
				  
				QueryAABB関数はb2Worldクラスのメンバ関数で、引数にはb2QueryCallback型のcallbackと、b2AABB型のaabbを取ります。callbackは範囲内にあるボディがあったときに呼び出してもらう関数を指定し、aabbには範囲を指定します。
				void b2World::QueryAABB (b2QueryCallback *callback, const b2AABB &#38;aabb ) const      
				
				まずはcallbackに渡す関数から用意します。まず、ヘッダファイルにb2QueryCallbackクラスを継承したクラスの定義を書きます。
				
				//表示範囲の地形を判定するためのコールバック
class ViewAreaQueryCallback : public b2QueryCallback
{
public:
	bool ReportFixture(b2Fixture* fixture);
};
				
				「継承」や「クラス」と聞くと難しく感じるかもしれませんが、今回の場合は上記のとおりに書いておけば問題ありません。ここではC++の文法についてはあまり細かくは説明しませんが、クラスの定義の書き方を見せておきましょう。
				
				
				
				class クラス名:public 継承元のクラス名
				        { 
				public: ←以降の定義はクラスの外部から利用可能 
				publicなメンバ関数・メンバ変数の定義 
				private: ←以降の定義はクラス内部でのみ利用可能 
				privateなメンバ関数・メンバ変数の定義 
				}
				
				
				
				QueryAABB関数は「ReportFixture」という名前の関数を呼び出すよう設計されているので、それを名前も引数も間違えないように定義しなければいけません。b2QueryCallbackクラスの定義には「絶対にReportFixture関数を間違えないように書けよ！」という指令が書いてあるので、そのクラスを継承すると、もし間違いがあればコンパイラがエラーを出してくれるのです。
				ReportFixture関数の定義は次のように書きます。中に書くことは後で説明するので、先にqueryAABB関数の使い方を説明しましょう。
				
				bool ViewAreaQueryCallback::ReportFixture(b2Fixture* fixture){
……この後実行したい処理を書く……
}
				
				範囲を指定してqueryAABB関数を呼び出す
				queryAABB関数の呼び出しは、前回説明したRenderAll関数の中に書いています。
				
				//レンダリング
void RenderAll(){
	……中略……
	//物理エンジンでのスクリーン座標を求める
	//DebugDraw時にDRAWSCALERATE倍にしていることに注意
	float phy_screen_x = (float)g_stage.screen_x / (WLDSC * DDRAWSCALERATE);
	float phy_screen_y = [...]]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<hr />
				<p>引き続き<a href="http://i-libro.net/wpmu/blog/archives/942">前々回記事</a><strong></strong>で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。今回説明するのは<strong>表示範囲内にあるモデルを絞り込む</strong>方法です。範囲内の物体を高速に行うのは意外と面倒なのですが、ここではBox2Dの<strong>QueryAABB</strong>という関数を使います。AABBは「Axis Aligned Bounding Box」の略で、「軸に沿った範囲を表す矩形」という意味になります。軸に沿わない――つまり回転もありうる矩形に比べると、高速に判定ができるわけです。</p>
				<p align="center"><a href="http://i-libro.net/wpmu/files/2011/03/ws001631.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001631" src="http://i-libro.net/wpmu/files/2011/03/ws001631-thumb.jpg" width="400" height="175" /></a></p>
				<p>  <span id="more-1010"></span>
				<p>QueryAABB関数はb2Worldクラスのメンバ関数で、引数にはb2QueryCallback型の<strong>callback</strong>と、b2AABB型の<strong>aabb</strong>を取ります。callbackは範囲内にあるボディがあったときに呼び出してもらう関数を指定し、aabbには範囲を指定します。</p>
				<blockquote><p>void b2World::QueryAABB (b2QueryCallback *callback, const b2AABB &amp;aabb ) const      </p>
				</blockquote>
				<p>まずはcallbackに渡す関数から用意します。まず、ヘッダファイルに<strong>b2QueryCallbackクラス</strong>を継承したクラスの定義を書きます。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="6264e6b9-8f74-418d-a337-83bb191296d9" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//表示範囲の地形を判定するためのコールバック
class ViewAreaQueryCallback : public b2QueryCallback
{
public:
	bool ReportFixture(b2Fixture* fixture);
};</pre>
				</div>
				<p>「継承」や「クラス」と聞くと難しく感じるかもしれませんが、今回の場合は上記のとおりに書いておけば問題ありません。ここではC++の文法についてはあまり細かくは説明しませんが、クラスの定義の書き方を見せておきましょう。</p>
				<table border="0" cellspacing="0" cellpadding="2" width="522">
				<tbody>
				<tr>
				<td valign="top" width="522">class クラス名:public 継承元のクラス名<br />
				        <br />{ </p>
				<p>public: ←以降の定義はクラスの外部から利用可能 </p>
				<p>publicなメンバ関数・メンバ変数の定義 </p>
				<p>private: ←以降の定義はクラス内部でのみ利用可能 </p>
				<p>privateなメンバ関数・メンバ変数の定義 </p>
				<p>}</td>
				</tr>
				</tbody>
				</table>
				<p>QueryAABB関数は「ReportFixture」という名前の関数を呼び出すよう設計されているので、それを名前も引数も間違えないように定義しなければいけません。b2QueryCallbackクラスの定義には<strong>「絶対にReportFixture関数を間違えないように書けよ！」</strong>という指令が書いてあるので、そのクラスを継承すると、もし<strong>間違いがあればコンパイラがエラーを出してくれる</strong>のです。</p>
				<p>ReportFixture関数の定義は次のように書きます。中に書くことは後で説明するので、先にqueryAABB関数の使い方を説明しましょう。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="1d686d5f-3a2a-4aa9-af04-3a471be41140" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">bool ViewAreaQueryCallback::ReportFixture(b2Fixture* fixture){
……この後実行したい処理を書く……
}</pre>
				</div>
				<h2>範囲を指定してqueryAABB関数を呼び出す</h2>
				<p>queryAABB関数の呼び出しは、前回説明したRenderAll関数の中に書いています。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="2a7c567a-72a8-424e-a4ad-baff0b94b693" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//レンダリング
void RenderAll(){
	……中略……
	//物理エンジンでのスクリーン座標を求める
	//DebugDraw時にDRAWSCALERATE倍にしていることに注意
	float phy_screen_x = (float)g_stage.screen_x / (WLDSC * DDRAWSCALERATE);
	float phy_screen_y = (float)g_stage.screen_y / (WLDSC * DDRAWSCALERATE);

	//表示範囲内にいる地形と敵を描画する
	//Box2DのQueryAABB関数を使って範囲内のボディを列挙させる
	clsDx();	//デバッグドロー用の処理なので意味はなし
	ViewAreaQueryCallback callback;
	b2AABB aabb;
	aabb.lowerBound.Set(phy_screen_x-1.0f, phy_screen_y-1.0f);
	aabb.upperBound.Set((float)(g_stage.screen_x+640) / (WLDSC * DDRAWSCALERATE)+1.0f,
		(float)(g_stage.screen_y+480) / (WLDSC * DDRAWSCALERATE)+1.0f );
	g_world.QueryAABB(&amp;callback, aabb);
#ifdef B2D_DEBUG_DRAW
	//表示範囲内を表す四角形を描画する
	DrawBox(VIWX(aabb.lowerBound.x), VIWY(aabb.lowerBound.y),
		VIWX(aabb.upperBound.x), VIWY(aabb.upperBound.y), 0x888888, FALSE);
#endif
	……後略……</pre>
				</div>
				<p>6～7行目は前回説明した「物理座標系での表示範囲の左上隅の座標値（phy_screen_x, phy_screen_y）」を求める計算です。</p>
				<p>12行目でb2QueryCallbackクラスを継承したViewAreaQueryCallbackクラス型の変数を定義しています。</p>
				<p>13行目でb2AABB型の変数aabbを定義し、そのb2Vec2型メンバ変数のlowerBoundとupperBoundに、表示範囲の左上隅と右下隅の座標を指定します。</p>
				<p>後はQueryAABB関数を呼び出すだけです（17行目）。</p>
				<h2>ReportFixture関数内でモデルを描画する</h2>
				<p>範囲内にボディが入っている場合、その数だけReportFixture関数が呼び出されます。その中でモデルの描画を行っていきます。</p>
				<p>描画するものの種類ごとに処理を分けなければいけないので、関数内の記述は長めですが基本的にはモデルの描画処理の繰り返しです。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="4f7ef5dc-4c25-454f-bc92-ae310136e0ea" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//表示範囲内の地形ブロックを描画する
bool ViewAreaQueryCallback::ReportFixture(b2Fixture* fixture){
	b2Body *body = fixture-&gt;GetBody();
	if(body != NULL){
		Character *ch = (Character*)body-&gt;GetUserData();
		b2Vec2 epos = body-&gt;GetPosition();
		float eangle = body-&gt;GetAngle();
		b2Vec2 evec = body-&gt;GetLinearVelocity();

		//キャラ種別ごとの処理
		if(ch-&gt;type &gt;= MAP_GROUND &amp;&amp; ch-&gt;type &lt;= MAP_PIRAMID){
			//printfDx("MAP BLOCK Found!\n");
			int curmodel = g_images.cube1;
			switch(ch-&gt;type){
			case MAP_FRAGILE:
				curmodel = g_images.cube3;
				break;
			case MAP_HATENA:
				curmodel = g_images.cube5;
				break;
			case MAP_PIPE1:
			case MAP_PIPE2:
			case MAP_PIPE3:
			case MAP_PIPE4:
				curmodel = g_images.cube2;
				break;
			case MAP_PIRAMID:
				curmodel = g_images.cube4;
				break;
			}
			DrawBlocks(curmodel, VIW3D(epos.x+0.3f, epos.y+0.54f, WORLDZPOS + 5.0f),
				ch-&gt;size / 36, eangle);
		} else if(ch-&gt;type == MAP_GOALFLAG) {
			//printfDx("GOAL Flag Found!\n");
			MV1SetPosition(g_images.goalflag, VIW3D(epos.x+0.3f, epos.y+0.54f, WORLDZPOS + 5.0f));
			MV1DrawModel(g_images.goalflag);
		} else if(ch-&gt;type == MAP_MONSTER_MASHROOM){
			//printfDx("Monster Found!\n");
			//キノコモンスターの描画処理
			int idx = ch-&gt;enemyidx;
			if(g_stage.monster[idx].used == false) return true;
			//モンスターのアニメーション進行
			if(evec.x &lt; 0) StepAnimTime(&amp;g_stage.enemyanim[idx], 1);
			else StepAnimTime(&amp;g_stage.enemyanim[idx], 0);
			//変形と描画
			MV1SetPosition(g_stage.enemyanim[idx].model, VIW3D(epos.x, epos.y+0.54f) );
			MV1SetRotationXYZ(g_stage.enemyanim[idx].model, VGet(0.0f, -PHI_F/2, 0.0f));
			MV1DrawModel(g_stage.enemyanim[idx].model);
		}
	}
	//検索を継続する場合はtrue
	return true;
}</pre>
				</div>
				<p>関数の引数として、ボディの形状を表す<strong>フィクスチャー</strong>が渡されます。そこから描画するモデルの情報を取り出すために、b2FixtureクラスのgetBody関数を使って<strong>ボディ</strong>を取得し、ユーザー情報、位置、角度、速度を取り出します（3～8行）。速度は敵キャラクターの移動方向を調べるために使います。</p>
				<p>ユーザー情報はmain.h内で定義している<strong>Character構造体</strong>で、そのメンバ変数typeにキャラクターの種類を表す定数が記憶されているので、それを使って描画します。</p>
				<p>地形に使うモデルは今回唯一自作したもので、36ピクセル÷50×10＝7.2に納まるようなサイズで作成しています。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001595.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001595" src="http://i-libro.net/wpmu/files/2011/03/ws001595-thumb.jpg" width="404" height="157" /></a></p>
				<p>マップデータ内ではボディの数を減らすために、ブロック複数個分をまとめて1つのボディとして扱っています。そこで、ブロックを並べて表示する<strong>DrawBlocks関数</strong>も定義しました。ブロックの数などを受け取ると、その数だけ並べて描画します。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="7f8bad74-b1e7-48d8-9c63-8a42c9332756" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void DrawBlocks(int model, VECTOR center, int num, float eangle){
	float startx = center.x - UNITSIZE_3D * ((float)num / 2.0f);
	for(int i=0; i&lt;num; i++){
		MV1SetPosition(model, VGet(startx + UNITSIZE_3D * i, center.y, center.z));
		MV1SetRotationXYZ(model, VGet(-eangle, 0.0f, 0.0f));
		MV1DrawModel(model);
	}
}</pre>
				</div>
				<p>&#160;</p>
				<p>マリオ風ゲームの解説はこれでおしまいです。</p>
				<p>3Dグラフィックスについてはまだまだ解説していないことがたくさんありますが、ここまでの内容だけでも色々な2Dゲームを3D化することができるはずです。ぜひ挑戦してみてください。</p>
				<p>いつになるかわかりませんが、機会を見て完全3Dのゲームプログラミングの解説もやりたいものだと考えております。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/1010/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】2Dに合わせて3Dグラフィックスを描画する その2</title>
		<link>http://i-libro.net/wpmu/blog/archives/997</link>
		<comments>http://i-libro.net/wpmu/blog/archives/997#comments</comments>
		<pubDate>Sun, 13 Mar 2011 19:11:50 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/997</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				
				引き続き前々回記事で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。解説を書く中でソースコード中の問題をいくつか見つけて修正したので、新たにこちらのソースコードをダウンロードし直してください。
				maori-bros3D_src2.zip（要Visual C++ 2010 Express）
				横スクロールタイプのゲームでは、ステージ内のどこを画面に表示するのかを決めなければいけません。3Dグラフィックスの場合、どこが表示されるかを決めるのはカメラです。カメラがどこに配置され、どこを注視しているかによって、「何がどこに表示されるのか」が決定されます。つまり、スクロールの進行に合わせてカメラを動かさなければならないということです。
				サンプルプログラムの2D部分では、左右は主人公が画面中央に来るようにスクロールし、上下は画面の端から200px以内に主人公が入ったときにスクロールすることにしています。そのために主人公の現在位置から、表示範囲の左上隅座標（screen_x, screen_y）を求める計算を行っています。
				
				  
				以下はその計算を行っているRenderAll関数の冒頭です。この関数はDrawGameMain関数やDrawGameOver関数から呼び出され、画面描画をまとめて行います。
				main.h
				
				void RenderAll(){
	//スクロール座標調整
	b2Vec2 pos = g_stage.hero.body-&#62;GetPosition();
	int hx = (int)(pos.x * WLDSC * DDRAWSCALERATE);
	int hy = (int)(pos.y * WLDSC * DDRAWSCALERATE);
	g_stage.screen_x = hx - 320;
	if(	hy - SCROLL_LIMIT &#60; g_stage.screen_y ){
		g_stage.screen_y = hy - SCROLL_LIMIT;
	}
	if( 480 - SCROLL_LIMIT &#60; hy - g_stage.screen_y ){
		g_stage.screen_y = hy + SCROLL_LIMIT - 480;
	}
	……続く……
				
				まず、Box2Dでの主人公の座標を変数posに求め、前回説明した単位変換の計算（50を掛けてさらに1.5を掛ける）を行って、2D画面表示用の座標hx、hyを求めます。
				左右は常に主人公が画面中央に来るようスクロールするので、hxから画面幅の半分の320を引いたものをscreen_xに記憶します。
				上下スクロールでは、主人公と画面上下端の距離を調べ、それが定数SCROLL_LIMIT（200px）未満なら、SCROLL_LIMITの間隔を保つようにscreen_yを調整します。
				カメラの座標を決める
				screen_x、screen_yは表示範囲の左上端を表しています。ここからカメラの位置を求めます。カメラは表示範囲の中央を映すように配置する必要があるので、screen_x、screen_yの位置から2D座標で（320,240）だけ移動した位置にします。
				
				以下はRenderAll関数内のカメラ位置の設定を行っている部分です。
				main.cpp
				
					……前略……
	//物理エンジンでのスクリーン座標を求める
	//DebugDraw時にDRAWSCALERATE倍にしていることに注意
	float phy_screen_x = (float)g_stage.screen_x [...]]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<hr />
				<p>引き続き<a href="http://i-libro.net/wpmu/blog/archives/942">前々回記事</a><strong></strong>で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。解説を書く中でソースコード中の問題をいくつか見つけて修正したので、新たにこちらのソースコードをダウンロードし直してください。</p>
				<p><a href="http://i-libro.net/game/download.php?fname=maori-bros3D_src2.zip">maori-bros3D_src2.zip</a>（要Visual C++ 2010 Express）</p>
				<p>横スクロールタイプのゲームでは、<strong>ステージ内のどこを画面に表示するのか</strong>を決めなければいけません。3Dグラフィックスの場合、どこが表示されるかを決めるのは<strong>カメラ</strong>です。カメラがどこに配置され、どこを注視しているかによって、「何がどこに表示されるのか」が決定されます。つまり、スクロールの進行に合わせてカメラを動かさなければならないということです。</p>
				<p>サンプルプログラムの2D部分では、左右は主人公が画面中央に来るようにスクロールし、上下は画面の端から200px以内に主人公が入ったときにスクロールすることにしています。そのために主人公の現在位置から、<strong>表示範囲の左上隅座標（screen_x, screen_y）</strong>を求める計算を行っています。</p>
				<p align="center"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001629" src="http://i-libro.net/wpmu/files/2011/03/ws0016291.jpg" width="402" height="300" /></p>
				<p>  <span id="more-997"></span>
				<p>以下はその計算を行っている<strong>RenderAll関数</strong>の冒頭です。この関数はDrawGameMain関数やDrawGameOver関数から呼び出され、画面描画をまとめて行います。</p>
				<p><strong>main.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="5a01cdb7-f5f6-4e23-be5d-0584630455f1" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void RenderAll(){
	//スクロール座標調整
	b2Vec2 pos = g_stage.hero.body-&gt;GetPosition();
	int hx = (int)(pos.x * WLDSC * DDRAWSCALERATE);
	int hy = (int)(pos.y * WLDSC * DDRAWSCALERATE);
	g_stage.screen_x = hx - 320;
	if(	hy - SCROLL_LIMIT &lt; g_stage.screen_y ){
		g_stage.screen_y = hy - SCROLL_LIMIT;
	}
	if( 480 - SCROLL_LIMIT &lt; hy - g_stage.screen_y ){
		g_stage.screen_y = hy + SCROLL_LIMIT - 480;
	}
	……続く……</pre>
				</div>
				<p>まず、Box2Dでの主人公の座標を<strong>変数pos</strong>に求め、前回説明した単位変換の計算（50を掛けてさらに1.5を掛ける）を行って、2D画面表示用の<strong>座標hx、hy</strong>を求めます。</p>
				<p>左右は常に主人公が画面中央に来るようスクロールするので、hxから画面幅の半分の320を引いたものをscreen_xに記憶します。</p>
				<p>上下スクロールでは、主人公と画面上下端の距離を調べ、それが定数SCROLL_LIMIT（200px）未満なら、SCROLL_LIMITの間隔を保つようにscreen_yを調整します。</p>
				<h2>カメラの座標を決める</h2>
				<p>screen_x、screen_yは表示範囲の左上端を表しています。ここからカメラの位置を求めます。カメラは表示範囲の中央を映すように配置する必要があるので、screen_x、screen_yの位置から<strong>2D座標で（320,240）だけ移動した位置</strong>にします。</p>
				<p align="center"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001628" src="http://i-libro.net/wpmu/files/2011/03/ws001628.jpg" width="402" height="249" /></p>
				<p align="left">以下はRenderAll関数内のカメラ位置の設定を行っている部分です。</p>
				<p align="left"><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="3b79e2e1-95c4-453e-ae27-8e26e7fcb224" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	……前略……
	//物理エンジンでのスクリーン座標を求める
	//DebugDraw時にDRAWSCALERATE倍にしていることに注意
	float phy_screen_x = (float)g_stage.screen_x / (WLDSC * DDRAWSCALERATE);
	float phy_screen_y = (float)g_stage.screen_y / (WLDSC * DDRAWSCALERATE);

	……中略……

	//カメラ設定
	VECTOR campos = VIW3D(phy_screen_x, phy_screen_y, WORLDZPOS - 30.0f);
	campos.x += 320 / (WLDSC * DDRAWSCALERATE) * VIEW3DSCALE;
	campos.y -= 240 / (WLDSC * DDRAWSCALERATE) * VIEW3DSCALE;
	VECTOR atpos = VGet(campos.x, campos.y, WORLDZPOS);
	SetCameraPositionAndTargetAndUpVec(campos, atpos, VGet(0,1,0) );
	SetCameraNearFar(10, 1000);
	SetupCamera_Ortho(70);
}</pre>
				</div>
				<p>まず、2D座標のscreen_x、screen_yをBox2Dの座標系の<strong>phy_screen_x、phy_screen_y</strong>に変換します（50*1.5で割る）。それを元にVIW3D関数で3Dの座標を求め、（320,240）を3D座標に変換した分だけずらします。カメラは注視点からZ軸沿いに－30.0fずらした位置に設定します。</p>
				<p>&#160;</p>
				<p>以下は主人公のモデルを描画している部分です。3行目で3D座標を求めるときに、y座標を0.54fずらしています。3Dモデルの原点がモデルの中央にないので、ここで補正して意図通りの位置に表示されるようにしているのです。ずらす量はモデルに合わせて変える必要があります。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="4e025849-fac1-4925-8d8e-359cbe3fe35e" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//b2Vec2 pos = g_stage.hero.body-&gt;GetPosition();
	float angle = g_stage.hero.body-&gt;GetAngle();
	VECTOR heropos = VIW3D(pos.x, pos.y+0.54f);

	//ヒーロー描画
	StepAnimTime(&amp;g_stage.heroanim, g_stage.herostate + g_stage.turnleft);
	MV1SetPosition(g_stage.heroanim.model, heropos);
	MV1SetRotationXYZ(g_stage.heroanim.model, VGet(-angle, -PHI_F/2, 0.0f));
	MV1DrawModel(g_stage.heroanim.model);</pre>
				</div>
				<p>&#160;</p>
				<p>次回は表示範囲内のモデルだけを描画する方法について説明します。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/997/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】2Dに合わせて3Dグラフィックスを描画する　その1</title>
		<link>http://i-libro.net/wpmu/blog/archives/984</link>
		<comments>http://i-libro.net/wpmu/blog/archives/984#comments</comments>
		<pubDate>Thu, 10 Mar 2011 09:40:29 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/984</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				
				前回記事で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。このゲームデモはもともと2D向けに作ったものです。3D版ではジャンプ処理のあたりを少し調整しましたが、基本的にはほとんど同じプログラムです。main.hの12行目にある定数B2D_DEBUG_DRAWのコメントを解除してから実行すると……
				main.h
				
				#include &#60;DxLib.h&#62;
#include &#60;Box2D/Box2D.h&#62;
#ifdef _DEBUG
	#pragma comment(lib, "Box2D_d.lib")
#endif
#ifndef _DEBUG
	#pragma comment(lib, "Box2D.lib")
#endif
#include "_dxdebugdraw.h"

//定数
#define B2D_DEBUG_DRAW
const int VELOCITYITE = 6;		//速度計算精度
const int POSITIONITE = 2;		//位置計算精度

				
				3Dグラフィックスに重なってBox2Dのデバッグドロー（物理エンジンが管理しているボディやジョイントを表示するデバッグ用機能）が表示されます。これを見ると完全に2Dのプログラムであることがわかると思います。
				
				©CRYPTON FUTURE MEDIA, INC. 
				Copyright (C) 2008-2010 唄音ウタProject, 飴屋／菖蒲 All Rights Reserved.
				
				2Dと3Dの表示を合わせるには？
				DXライブラリは2Dと3Dを混在して扱える（というより、もともと2D描画でも3Dグラフィックス機能を利用している）ので、同時に表示すること自体は普通にできます。しかし、座標軸の向きや単位などが違うので、まったく同じように動かすのはそれほど簡単ではありません。
				ソースコードを見せる前に、ひとつひとつ理屈を説明していきましょう。
				座標軸の方向の違いは比較的簡単に解決できます。2DのYの座標値にマイナスを付けて負の値にしてやればいいのです。2DのY座標値も3Dの負のY座標値も、絶対値が増えるほど下になります。この方式ならX座標値はそのまま使えるので、ちょっとした計算で簡単に座標変換できます。
				
				&#160;
				次は座標やサイズに使う単位の問題について考えてみます。サンプルプログラムでは2D、3Dの座標系に加えて、もうひとつの座標系があります。それはBox2Dが使う物理演算用の座標系です。この座標系では単位としてメートルが使われています。
				2Dグラフィックスではピクセルを単位として使うのがやりやすいので、2D版のプログラムではピクセルでキャラクタの位置や大きさを指定し、それをメートルに換算してからBox2Dに渡し、画面描画を行う際にまたピクセルに戻していました。具体的には「50ピクセル＝1メートル」としていたので、Box2Dに渡す前に50で割り、画面表示する前に50を掛けていたのです。
				
				これに合わせて3Dグラフィックスを描画するのですが、前に説明したとおり3Dの座標系には単位はありません。ですから理論上はメートル単位やピクセル単位の座標値、サイズ値をそのまま使ってもいいことになります。
				しかし、実際に使うとなると色々な問題が出てきます。ひとつはモデルのサイズです。PMDエディタで調べたところ、PMDねんどろ風初音ミクv1.1のサイズはだいたい「13」ということがわかりました。モデルを綺麗に見せるためには拡大縮小を避けたほうがいいので、原寸で表示して2Dとサイズが合うように調整するのが望ましいといえます。
				
				ここでもうひとつ問題になってくるのは、元の2D描画のサイズが小さすぎることです。元のプログラムでは、マップを構成する1ブロックのサイズを36ピクセルで作成していましたが、これに合わせて3Dのモデルを表示すると、ディテールがほとんど見えなくなってしまいます。
				色々検討した結果、2Dのデバッグドローの表示は元の1.5倍、3D描画はBox2Dのメートル単位の値を10倍して表示することにしました。
				
				2Dのデバッグドローを1.5倍にする処理は、次のように定数DDRAWSCALERATEを定義しておいて……
				_dxdebugdraw.h
				
				const float DDRAWSCALERATE = 1.5f;	//表示のみ拡大したいときに使用
class DxDebugDraw :public b2DebugDraw{
private:
	b2Vec2 screen_pos;
	float WLDSC;
	inline int ColorValue(b2Color col){
				
				座標、サイズ値をメートル単位から変換するときに、DDRAWSCALERATEを掛けるようにします。
				_dxdebugdraw.cpp
				
					inline int ColorValue(b2Color col){
		return (int)(col.r * 0xFF0000 + col.g * 0xFF00 + col.b * [...]]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<hr />
				<p><a href="http://i-libro.net/wpmu/blog/archives/942"><strong>前回記事</strong></a>で公開したマリオブラザーズ風のゲームデモのグラフィックス処理について解説していきます。このゲームデモはもともと<a href="http://i-libro.net/wpmu/blog/archives/451">2D向けに作ったもの</a>です。3D版ではジャンプ処理のあたりを少し調整しましたが、基本的にはほとんど同じプログラムです。main.hの12行目にある<strong>定数B2D_DEBUG_DRAW</strong>のコメントを解除してから実行すると……</p>
				<p><strong>main.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="a14188e0-4299-4b24-a27f-63df31382b93" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">#include &lt;DxLib.h&gt;
#include &lt;Box2D/Box2D.h&gt;
#ifdef _DEBUG
	#pragma comment(lib, "Box2D_d.lib")
#endif
#ifndef _DEBUG
	#pragma comment(lib, "Box2D.lib")
#endif
#include "_dxdebugdraw.h"

//定数
#define B2D_DEBUG_DRAW
const int VELOCITYITE = 6;		//速度計算精度
const int POSITIONITE = 2;		//位置計算精度
</pre>
				</div>
				<p>3Dグラフィックスに重なってBox2Dの<strong>デバッグドロー</strong>（物理エンジンが管理しているボディやジョイントを表示するデバッグ用機能）が表示されます。これを見ると完全に2Dのプログラムであることがわかると思います。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001607.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001607" src="http://i-libro.net/wpmu/files/2011/03/ws001607-thumb.jpg" width="404" height="319" /></a></p>
				<p>©CRYPTON FUTURE MEDIA, INC. </p>
				<p>Copyright (C) 2008-2010 唄音ウタProject, 飴屋／菖蒲 All Rights Reserved.</p>
				<p><span id="more-984"></span></p>
				<h2>2Dと3Dの表示を合わせるには？</h2>
				<p>DXライブラリは2Dと3Dを混在して扱える（というより、もともと2D描画でも3Dグラフィックス機能を利用している）ので、同時に表示すること自体は普通にできます。しかし、座標軸の向きや単位などが違うので、<strong>まったく同じように動かす</strong>のはそれほど簡単ではありません。</p>
				<p>ソースコードを見せる前に、ひとつひとつ理屈を説明していきましょう。</p>
				<p><strong>座標軸の方向の違い</strong>は比較的簡単に解決できます。2Dの<strong>Yの座標値にマイナスを付けて負の値に</strong>してやればいいのです。2DのY座標値も3Dの負のY座標値も、絶対値が増えるほど下になります。この方式ならX座標値はそのまま使えるので、ちょっとした計算で簡単に座標変換できます。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001615" src="http://i-libro.net/wpmu/files/2011/03/ws0016151.jpg" width="502" height="285" /></p>
				<p>&#160;</p>
				<p>次は<strong>座標やサイズに使う単位の問題</strong>について考えてみます。サンプルプログラムでは2D、3Dの座標系に加えて、もうひとつの座標系があります。それはBox2Dが使う<strong>物理演算用の座標系</strong>です。この座標系では単位として<strong>メートル</strong>が使われています。</p>
				<p>2Dグラフィックスでは<strong>ピクセル</strong>を単位として使うのがやりやすいので、2D版のプログラムではピクセルでキャラクタの位置や大きさを指定し、それをメートルに換算してからBox2Dに渡し、画面描画を行う際にまたピクセルに戻していました。具体的には<strong>「50ピクセル＝1メートル」</strong>としていたので、Box2Dに渡す前に50で割り、画面表示する前に50を掛けていたのです。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001617" src="http://i-libro.net/wpmu/files/2011/03/ws0016171.jpg" width="502" height="79" /></p>
				<p>これに合わせて3Dグラフィックスを描画するのですが、前に説明したとおり3Dの座標系には単位はありません。ですから理論上はメートル単位やピクセル単位の座標値、サイズ値をそのまま使ってもいいことになります。</p>
				<p>しかし、実際に使うとなると色々な問題が出てきます。ひとつは<strong>モデルのサイズ</strong>です。PMDエディタで調べたところ、PMDねんどろ風初音ミクv1.1のサイズはだいたい「13」ということがわかりました。モデルを綺麗に見せるためには拡大縮小を避けたほうがいいので、<strong>原寸で表示して2Dとサイズが合うように調整</strong>するのが望ましいといえます。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001583.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001583" src="http://i-libro.net/wpmu/files/2011/03/ws001583-thumb.jpg" width="404" height="249" /></a></p>
				<p>ここでもうひとつ問題になってくるのは、元の<strong>2D描画のサイズが小さすぎる</strong>ことです。元のプログラムでは、マップを構成する1ブロックのサイズを<strong>36ピクセル</strong>で作成していましたが、これに合わせて3Dのモデルを表示すると、ディテールがほとんど見えなくなってしまいます。</p>
				<p>色々検討した結果、2Dのデバッグドローの表示は<strong>元の1.5倍</strong>、3D描画はBox2Dの<strong>メートル単位の値を10倍</strong>して表示することにしました。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001618" src="http://i-libro.net/wpmu/files/2011/03/ws0016181.jpg" width="502" height="212" /></p>
				<p>2Dのデバッグドローを1.5倍にする処理は、次のように<strong>定数DDRAWSCALERATE</strong>を定義しておいて……</p>
				<p><strong>_dxdebugdraw.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="7ae24666-3fdb-4819-91aa-f3e4d115df66" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">const float DDRAWSCALERATE = 1.5f;	//表示のみ拡大したいときに使用
class DxDebugDraw :public b2DebugDraw{
private:
	b2Vec2 screen_pos;
	float WLDSC;
	inline int ColorValue(b2Color col){</pre>
				</div>
				<p>座標、サイズ値をメートル単位から変換するときに、DDRAWSCALERATEを掛けるようにします。</p>
				<p><strong>_dxdebugdraw.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="cf3cc18f-b0a6-44bc-aa10-bb09738a4e0e" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	inline int ColorValue(b2Color col){
		return (int)(col.r * 0xFF0000 + col.g * 0xFF00 + col.b * 0xFF);
	}
	inline int VIWX(float32 x){
		return (int)(x * WLDSC * DDRAWSCALERATE - screen_pos.x);
	}
	inline int VIWY(float32 y){
		return (int)(y * WLDSC * DDRAWSCALERATE - screen_pos.y);
	}
	inline int VIW(float32 v){
		return (int)(v * WLDSC * DDRAWSCALERATE);
	}</pre>
				</div>
				<p>3Dグラフィックスを描画する処理では、<strong>定数VIEW3DSCALE</strong>を定義しておいて……</p>
				<p><strong>main.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="f1838d13-4055-48b8-b99f-c2f491d71142" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//定数
#define B2D_DEBUG_DRAW
const int VELOCITYITE = 6;		//速度計算精度
const int POSITIONITE = 2;		//位置計算精度
const float GRAVITY_Y = 20.0f;	//重力加速度
const float WLDSC = 50.0f;		//世界倍率
const float SCREENAREA = 300.0f;//スクリーン範囲（ステージ外判定用）
const int SCROLL_LIMIT = 100;	//スクロール限界
const float VIEW3DSCALE = 10.0f;	//3D座標への変換に使うスケール値
const float WORLDZPOS = 320.0f;	//X軸の座標（全キャラ固定）
const float UNITSIZE_3D = 7.2f;	//3Dの1モデルのサイズ</pre>
				</div>
				<p>2D座標から3D座標を求める<strong>VIW3D関数</strong>を定義します。</p>
				<p><strong>_utils.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="88680240-08cf-41c1-9143-1f03fda734dc" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//3D向けの座標変換関数
VECTOR VIW3D(float x, float y, float z3d){
	return VGet(x * VIEW3DSCALE, -y * VIEW3DSCALE, z3d);
}</pre>
				</div>
				<p>この関数は、次のように2D座標から3D座標値を納めたVECTOR型の3D座標値を求めます。3つめの<strong>引数z3d</strong>は省略可能で、省略した場合は<strong>定数WORLDZPOS</strong>（320.0f）が使われます。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="2985ba13-c279-472d-8210-f906745b69fd" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">b2Vec2 pos = g_stage.hero.body-&gt;GetPosition();
VECTOR heropos = VIW3D(pos.x, pos.y+0.05f);
MV1SetPosition(g_stage.heroanim.model, heropos);
MV1DrawModel(g_stage.heroanim.model);</pre>
				</div>
				<p>後はこの設定で2Dと3Dがうまく合うよう、<strong>SetupCamera_Ortho関数</strong>の値を調整します（今回は70を指定しています）。<strong>並行投影カメラ</strong>を設定するSetupCamera_Orth関数については<a href="http://i-libro.net/wpmu/blog/archives/652">過去の記事</a>を参照してください。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="8702d483-00df-474c-942b-85180adcd89f" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	SetCameraNearFar(10, 1000);
	SetupCamera_Ortho(70);
</pre>
				</div>
				<p>ちなみに並行投影カメラを使うと<strong>2Dっぽい描画</strong>になりますが、完全に一致するわけではありません。カメラの注視点（このゲームの場合は画面中央）に近い場所のみピタリと重なり、<strong>そこから遠くなるほど大きくずれていきます</strong>。ただし、3D描画全てが同じようにずれるので、注視点の位置で揃うように作成しておけば実用上の問題はありません。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001608.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001608" src="http://i-libro.net/wpmu/files/2011/03/ws001608-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/03/ws001611.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001611" src="http://i-libro.net/wpmu/files/2011/03/ws001611-thumb.jpg" width="244" height="193" /></a></p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001610.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001610" src="http://i-libro.net/wpmu/files/2011/03/ws001610-thumb.jpg" width="244" height="193" /></a></p>
				<p>&#160;</p>
				<p>&#160;</p>
				<p>さて、今回は少々ややこしい計算をしましたが、それは元々が2Dのプログラムだったからです。マップデータやキャラクターサイズなどをすべてピクセルで指定していたため、そこを変更するとなると全体にわたる微調整が必要です。</p>
				<p>もし最初から3D前提で作るなら、最初からBox2Dのメートル単位で指定した方が簡単でいいかもしれません。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001619" src="http://i-libro.net/wpmu/files/2011/03/ws0016191.jpg" width="502" height="171" /></p>
				<p>&#160;</p>
				<p>次回は<strong>スクロール処理</strong>と<strong>範囲内のみ描画</strong>する方法について解説します。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/984/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】MikuMikuDance風かつマリオブラザーズ風なゲームデモ公開</title>
		<link>http://i-libro.net/wpmu/blog/archives/942</link>
		<comments>http://i-libro.net/wpmu/blog/archives/942#comments</comments>
		<pubDate>Sat, 05 Mar 2011 19:49:45 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/942</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				
				ようやくマリオブラザーズ風のゲームデモができあがりました。元々2D前提で作ったものを3Dに変更したため、座標変換がややこしいことになってしまい、予想以上に手こずりました。取り急ぎソースコードと実行ファイルを公開しますが、解説はまた日を改めてとさせてください。
				
				動画も用意したのですが、ゲームとキャプチャソフトを同時に実行できるスペックが無かったので、iPhoneで撮影しています。BGMはYoutubeの機能で合成したもので、実際のプログラムは無音です。操作方法はカーソルキーの左右とXキー、頭突きで動くブロックは動くだけでコインなどは出てきません。
				http://www.youtube.com/watch?v=56foghugriI（クリックして動画再生）
				©CRYPTON FUTURE MEDIA, INC.    Copyright (C) 2008-2010 唄音ウタProject, 飴屋／菖蒲 All Rights Reserved.
				解説中で使用しているモデルはenamel toy box（ハッチさん運営）で公開されている「PMDねんどろ風初音ミクv1.1」と「PMDねんどろ風デフォ子v1.11」です。
				  
				&#160;
				&#160;
				ソースコードとコンパイル済みの実行ファイルは以下からダウンロードできます。
				maori-bros3D_src.zip（要Visual C++ 2010 Express）
				maori-bros3D_bin.zip（Windows用実行ファイル）
				どちらもモデルファイルやテクスチャファイルを別途ダウンロードして、mediaフォルダ内にコピーする必要があります。「MmdDefoko1.11.pmd」は「MmdDefoko.pmd」にファイル名を変更しないといけません。ファイル名中にピリオドや数字があると、DXライブラリがモーションファイルを読み込んでくれなくなるためです。
				
				以前の記事で説明したとおり、トゥーンマップのBMPファイルもコピーしておいてください。無くても動作しますが、トゥーン調表示になりません。
				ちなみに、meidaフォルダ内に最初から入っているファイルは、こちらで作成したモーションファイルや地形のモデルファイル、マップファイルなどです。
				&#160;
				次回は2Dゲームに合わせて3D描画を行う方法や、必要な範囲内だけ描画して処理を軽くする方法などを説明する予定です。
]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<hr />
				<p>ようやく<strong>マリオブラザーズ風のゲームデモ</strong>ができあがりました。元々<a href="http://i-libro.net/wpmu/blog/archives/451">2D前提で作ったもの</a>を3Dに変更したため、座標変換がややこしいことになってしまい、予想以上に手こずりました。取り急ぎソースコードと実行ファイルを公開しますが、解説はまた日を改めてとさせてください。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001596.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001596" src="http://i-libro.net/wpmu/files/2011/03/ws001596-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/03/ws001599.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001599" src="http://i-libro.net/wpmu/files/2011/03/ws001599-thumb.jpg" width="244" height="193" /></a></p>
				<p>動画も用意したのですが、ゲームとキャプチャソフトを同時に実行できるスペックが無かったので、iPhoneで撮影しています。BGMはYoutubeの機能で合成したもので、実際のプログラムは無音です。操作方法はカーソルキーの左右とXキー、頭突きで動くブロックは動くだけでコインなどは出てきません。</p>
				<p><a href="http://www.youtube.com/watch?v=56foghugriI" target="_blank">http://www.youtube.com/watch?v=56foghugriI</a>（クリックして動画再生）</p>
				<p>©CRYPTON FUTURE MEDIA, INC.    <br />Copyright (C) 2008-2010 唄音ウタProject, 飴屋／菖蒲 All Rights Reserved.</p>
				<p>解説中で使用しているモデルは<a href="http://enamelhp.web.fc2.com/">enam<font color="#666666"></font>el toy box</a>（ハッチさん運営）で公開されている<strong>「PMDねんどろ風初音ミクv1.1」</strong>と<strong>「PMDねんどろ風デフォ子v1.11」</strong>です。</p>
				<p>  <span id="more-942"></span>
				<p>&#160;</p>
				<p>&#160;</p>
				<p>ソースコードとコンパイル済みの実行ファイルは以下からダウンロードできます。</p>
				<p><a href="http://i-libro.net/game/download.php?fname=maori-bros3D_src.zip">maori-bros3D_src.zip</a>（要Visual C++ 2010 Express）</p>
				<p><a href="http://i-libro.net/game/download.php?fname=maori-bros3D_bin.zip">maori-bros3D_bin.zip</a>（Windows用実行ファイル）</p>
				<p>どちらもモデルファイルやテクスチャファイルを別途ダウンロードして、mediaフォルダ内にコピーする必要があります。「MmdDefoko1.11.pmd」は<strong>「MmdDefoko.pmd」にファイル名を変更</strong>しないといけません。ファイル名中にピリオドや数字があると、DXライブラリがモーションファイルを読み込んでくれなくなるためです。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001602.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001602" src="http://i-libro.net/wpmu/files/2011/03/ws001602-thumb.jpg" width="404" height="307" /></a></p>
				<p><a href="http://i-libro.net/wpmu/blog/archives/556">以前の記事</a>で説明したとおり、<strong>トゥーンマップ</strong>のBMPファイルもコピーしておいてください。無くても動作しますが、トゥーン調表示になりません。</p>
				<p>ちなみに、meidaフォルダ内に最初から入っているファイルは、こちらで作成したモーションファイルや地形のモデルファイル、マップファイルなどです。</p>
				<p>&#160;</p>
				<p>次回は<strong>2Dゲームに合わせて3D描画を行う方法</strong>や、<strong>必要な範囲内だけ描画して処理を軽くする方法</strong>などを説明する予定です。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/942/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】アニメーションの切り替えを滑らかにする</title>
		<link>http://i-libro.net/wpmu/blog/archives/910</link>
		<comments>http://i-libro.net/wpmu/blog/archives/910#comments</comments>
		<pubDate>Mon, 28 Feb 2011 13:30:30 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/910</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）。
				
				前回は「立つ」「走る」「ジャンプ」のアニメーションをキー操作に合わせて切り替える方法を説明しましたが、一瞬でモデルの向きやポーズが変わってしまうため、不自然に見えるという問題がありました。これを解決するために、DXライブラリには複数のアニメーションをブレンドするMV1SetAttachAnimBlendRate関数が用意されています。ただし、再生時間の設定やアタッチ、デタッチといった処理に合わせて、さらにブレンド率の設定もしなければいけないので、どうスマートに組み込むかが工夫のしどころです。
				
				今回の作例：いきなり「立つ」→「ジャンプ」へ切り替わるのではなく、切り替わり途中の中間段階のポーズが自動的に作られる     ©CRYPTON FUTURE MEDIA, INC.     解説中で使用しているモデルは前回に続きenamel toy box（ハッチさん運営）で公開されている「PMDねんどろ風初音ミクv1.1」
				※今回は拡大していないオリジナルのモデルをそのまま使用します。
				  
				アニメーションのブレンドの何が面倒なのか
				今回も変更点が多めなので、完成状態のソースコードをダウンロードし、それを見ながら解説を読み進めてください。
				DXB2D_3DTest_src06.zip（要Visual C++ 2010 Express）
				このファイルをダウンロードして解凍したら、そのフォルダ内にmediaフォルダを作成し、モデルファイル、テクスチャファイル（texフォルダ）、トゥーンマップの画像ファイル、そして3つのモーションファイルをコピーします。要するに前回のmediaフォルダと同じ状態にしてください。もちろんVC++ディレクトリなどの設定も過去記事と同じように行う必要があります。
				&#160;
				さて、本題のアニメーションのブレンドですが、それを設定するためのMV1SetAttachAnimBlenRate関数そのものはシンプルです。
				int MV1SetAttachAnimBlendRate( int MHandle, int AttachIndex, float Rate ) ;
				
				モデルハンドルMHandleとアタッチ番号AttachIndexを指定し、0.0f～1.0fのブレンド率Rateを指定するだけです。Rateで指定した割合だけ、アニメーションがモデルに影響を与えます。
				ただし、アニメーションが滑らかに切り替わるようにするには、1つのモデルにアニメーションを2つアタッチし、古い方は100%（1.0f）→0%（0.0f）、新しい方は0%→100%となるようにブレンド率を変化させていかなければいけません。
				
				これをアニメーションに再生時間を設定する処理や、その他のゲーム本編の処理と同時に行わなければいけないので、ちょっとばかりややこしいことになります。そこでサンプルのソースコードでは、アニメーションの再生処理を任せっきりにできる関数を作っています。
				そのおかげで、DrawGameMain関数は14行目でStepAnimTimeという関数を呼び出すだけでアニメーションが完了するようになりました。
				main.cpp
				
				void DrawGameMain(){
	DrawBox(0,0,640,480, 0xFFDDDD, TRUE);
	//キー取得
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);

	int herostate = HERO_STAND;
	if((key &#38; PAD_INPUT_LEFT) &#124;&#124; (key &#38; PAD_INPUT_RIGHT)) {
		herostate = HERO_RUN;
	}
	if(key &#38; PAD_INPUT_B){
		herostate = HERO_JUMP;
	}
	//アニメーション設定
	StepAnimTime(&#38;g_stage.heroanim, herostate);

	//移動と表示
	MV1SetPosition(g_stage.heroanim.model, g_stage.heropos);
	MV1DrawModel(g_stage.heroanim.model) ;
	MV1SetPosition(g_stage.heroanim.model, [...]]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）。</p>
				<hr />
				<p>前回は「立つ」「走る」「ジャンプ」のアニメーションをキー操作に合わせて切り替える方法を説明しましたが、一瞬でモデルの向きやポーズが変わってしまうため、不自然に見えるという問題がありました。これを解決するために、DXライブラリには<strong>複数のアニメーションをブレンド</strong>する<strong>MV1SetAttachAnimBlendRate関数</strong>が用意されています。ただし、再生時間の設定やアタッチ、デタッチといった処理に合わせて、さらにブレンド率の設定もしなければいけないので、どうスマートに組み込むかが工夫のしどころです。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/03/ws001584.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001584" src="http://i-libro.net/wpmu/files/2011/03/ws001584-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/03/ws001587.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001587" src="http://i-libro.net/wpmu/files/2011/03/ws001587-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/03/ws001588.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001588" src="http://i-libro.net/wpmu/files/2011/03/ws001588-thumb.jpg" width="244" height="193" /></a></p>
				<p>今回の作例：いきなり「立つ」→「ジャンプ」へ切り替わるのではなく、切り替わり途中の<strong>中間段階のポーズ</strong>が自動的に作られる     <br />©CRYPTON FUTURE MEDIA, INC.     <br />解説中で使用しているモデルは前回に続き<a href="http://enamelhp.web.fc2.com/">enamel toy box</a>（ハッチさん運営）で公開されている「<b>PMDねんどろ風初音ミク</b><b>v1.1</b>」</p>
				<p><strong>※今回は拡大していないオリジナルのモデルをそのまま使用します</strong><strong>。</strong></p>
				<p>  <span id="more-910"></span><br />
				<h2>アニメーションのブレンドの何が面倒なのか</h2>
				<p>今回も変更点が多めなので、<strong>完成状態のソースコードをダウンロード</strong>し、それを見ながら解説を読み進めてください。</p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXB2D_3DTest_src06.zip">DXB2D_3DTest_src06.zip</a>（要Visual C++ 2010 Express）</p>
				<p>このファイルをダウンロードして解凍したら、そのフォルダ内に<strong>mediaフォルダ</strong>を作成し、モデルファイル、テクスチャファイル（texフォルダ）、トゥーンマップの画像ファイル、そして3つのモーションファイルをコピーします。要するに<strong><a href="http://i-libro.net/wpmu/blog/archives/876">前回</a>のmediaフォルダと同じ状態</strong>にしてください。もちろんVC++ディレクトリなどの設定も過去記事と同じように行う必要があります。</p>
				<p>&#160;</p>
				<p>さて、本題のアニメーションのブレンドですが、それを設定するための<strong>MV1SetAttachAnimBlenRate関数</strong>そのものはシンプルです。</p>
				<blockquote><p>int MV1SetAttachAnimBlendRate( int MHandle, int AttachIndex, float Rate ) ;</p>
				</blockquote>
				<p>モデルハンドル<strong>MHandle</strong>とアタッチ番号<strong>AttachIndex</strong>を指定し、0.0f～1.0fのブレンド率<strong>Rate</strong>を指定するだけです。Rateで指定した割合だけ、アニメーションがモデルに影響を与えます。</p>
				<p>ただし、アニメーションが滑らかに切り替わるようにするには、1つのモデルに<strong>アニメーションを2つアタッチ</strong>し、<strong>古い方は100%（1.0f）→0%（0.0f）</strong>、<strong>新しい方は0%→100%</strong>となるようにブレンド率を変化させていかなければいけません。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001580" src="http://i-libro.net/wpmu/files/2011/02/ws0015801.jpg" width="502" height="344" /></p>
				<p>これをアニメーションに再生時間を設定する処理や、その他のゲーム本編の処理と同時に行わなければいけないので、ちょっとばかりややこしいことになります。そこでサンプルのソースコードでは、<strong>アニメーションの再生処理を任せっきりにできる関数</strong>を作っています。</p>
				<p>そのおかげで、DrawGameMain関数は14行目でStepAnimTimeという関数を呼び出すだけでアニメーションが完了するようになりました。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="0f2262a9-7a23-45b4-9bf0-78e3d8127f82" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void DrawGameMain(){
	DrawBox(0,0,640,480, 0xFFDDDD, TRUE);
	//キー取得
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);

	int herostate = HERO_STAND;
	if((key &amp; PAD_INPUT_LEFT) || (key &amp; PAD_INPUT_RIGHT)) {
		herostate = HERO_RUN;
	}
	if(key &amp; PAD_INPUT_B){
		herostate = HERO_JUMP;
	}
	//アニメーション設定
	StepAnimTime(&amp;g_stage.heroanim, herostate);

	//移動と表示
	MV1SetPosition(g_stage.heroanim.model, g_stage.heropos);
	MV1DrawModel(g_stage.heroanim.model) ;
	MV1SetPosition(g_stage.heroanim.model, VAdd(g_stage.heropos, VGet(15, 0, 15)) );
	MV1DrawModel(g_stage.heroanim.model) ;
</pre>
				</div>
				<h2>アニメーション用情報を記憶する構造体を用意する</h2>
				<p>2つのアニメーションを同時にアタッチして徐々に切り替えるためには、最低でも2つのアタッチ番号を記憶する必要があります。個別の変数で管理するとわかりにくいので、アニメーション再生に必要な情報をまとめて記憶する<strong>AnimInfo構造体</strong>を定義することにしました。また、StageInfo構造体内にはAnimInfo型のメンバheroanimを定義します。</p>
				<p><strong>main.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="f35ac9e4-11da-4a9e-8e9b-c6589928ee9d" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//アニメーション情報
struct AnimInfo{
	int model;		//モデルハンドル
	int anim;		//現在のアニメーション番号
	int attach;		//現在のアタッチ番号
	int oldanim;	//古いアニメーション番号
	int oldattach;	//古いアタッチ番号
	int starttime;	//現在のアニメーションの再生開始時刻
};
const int ANIMBLENDTIME = 500;	//ブレンドする時間（ミリ秒）
//ゲームデータ記録用構造体
struct StageInfo{
	int timerstart;			//待機タイマーの開始時刻
	int gamestarttime;		//ゲームの開始時間
	int gametime;			//ゲーム開始からの経過ミリ秒
	float mapsize_w, mapsize_h;	//マップサイズ
	int screen_x, screen_y;	//表示原点（スクロール用）

	VECTOR heropos;	//主人公の位置
	AnimInfo heroanim;	//主人公のアニメーション情報
};
//アニメーション用ポーズ定数
enum HeroState{HERO_STAND, HERO_RUN, HERO_JUMP};</pre>
				</div>
				<p>AnimBlend構造体には、新旧2組みのアタッチ番号とアニメーション番号の他に、モデルハンドルと<strong>アニメーションの再生開始時刻</strong>を記憶します。再生開始時刻<strong>starttime</strong>はブレンドする期間を制限するためのものです。 </p>
				<p><strong>現在時刻－starttime</strong>が定数<strong>ANIMBLENDTIME</strong>より小さい間、アニメーションのブレンドを行うようにします。ANIMBLENDTIMEには500ミリ秒を指定しているので、0.5秒間掛けてアニメーションを切り替えることになります。</p>
				<p>実際にサンプルを実行してみて長すぎると感じた場合は、ANIMBLENDTIMEを適当に減らしてください。</p>
				<h2>アニメーションを適切にデタッチするためのしくみ</h2>
				<p>アニメーションのブレンドが終わったら、適切に古いアニメーションをデタッチする必要があります。また、すでにデタッチをしているのに、繰り返しデタッチしないようにしなければいけません。そこで、AnimInfo構造体のメンバ<strong>oldattach</strong>が－1ならデタッチ済みまたはアタッチ前なことを示すことにしました。</p>
				<p>しかし、ゲーム開始時点ではoldattachは0で初期化されているので、<strong>アニメーションが再生される前に－1を代入しておく</strong>必要があります。また、ゲームの場合はゲーム本編→ゲームオーバーかタイトル画面→またゲーム本編……という流れになるので、直前のゲーム本編が終わるときにデタッチし損なった場合を考えて、ゲーム本編開始前に<strong>すべてのアニメーションをデタッチ</strong>するしくみが必要です。</p>
				<p>そこで、_utils.cpp（main.cppではありません）に<strong>InitAnimInfo関数</strong>と<strong>EraseAnimInfo関数</strong>という2つの関数を定義しました。</p>
				<p><strong>_utils.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="bc1fb638-2ccb-43c4-b5f7-475d2d14a627" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//モデルを複製し、初期状態のアニメーションを設定する
void InitAnimInfo(AnimInfo *ainfo, int srcmodel, int firstanim){
	ainfo-&gt;model = MV1DuplicateModel(srcmodel);
	ainfo-&gt;attach = MV1AttachAnim(ainfo-&gt;model, firstanim);
	ainfo-&gt;oldattach = -1;	//これは必須
}
//アニメーションをモデルごとを削除する
void EraseAnimInfo(AnimInfo *ainfo){
	if(ainfo-&gt;model != 0) MV1DeleteModel(ainfo-&gt;model);
	ainfo-&gt;model = 0;
}</pre>
				</div>
				<p>InitAnimInfo関数は<strong>MV1DuplicateModel関数</strong>を使ってモデルの複製を作り、oldattachに－1を代入する処理を行います。</p>
				<blockquote>
				<p>int MV1DuplicateModel( int SrcMHandle ) ;</p>
				</blockquote>
				<p>MV1DuplicateModel関数でモデルハンドルを複製すると、容量を食うモデルデータやアニメーションデータは共有しつつも、アタッチの状態や変形情報を個別に持つ<strong>独立したモデルハンドル</strong>が作成されます。そこで、ファイルから読み込んだモデルデータそのものには手を付けず、その複製を使うようにすると、複製したモデルデータを削除するだけでアタッチ情報などをまとめて消すことができます。</p>
				<p align="center"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001537" src="http://i-libro.net/wpmu/files/2011/02/ws0015371.jpg" width="402" height="252" /></p>
				<p>ステージ情報の初期化を行うInitStage関数内ではInitAnimInfo関数とEraseAnimInfo関数を次のように使用しています。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="c9481693-6c46-4b46-8333-aff2449992be" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//ステージ初期化
void InitStage(){
	//古いアニメーション情報を削除
	EraseAnimInfo(&amp;g_stage.heroanim);

	//ゲームデータ全体のゼロ初期化
	ZeroMemory(&amp;g_stage, sizeof(g_stage));
	//全ボディ・ジョイント削除
	DeleteAllBody();

	//主人公位置の初期化
	g_stage.heropos = VGet( 320.0f, 225.0f, -350.0f );
	//アニメーション情報を初期化
	InitAnimInfo(&amp;g_stage.heroanim, g_images.hero, HERO_STAND);

	//ゲーム開始時刻の記録
	g_stage.gamestarttime = g_lasttime;
}</pre>
				</div>
				<p>他の処理よりも前にEraseAnimInfo関数を呼び出して、前回ゲーム本編を実行したときに作成されたアタッチ情報などを複製モデルデータごと削除します。その後、InitAnimInfo関数を呼び出して、新たなモデルの複製を作成し、最初のアニメーションをアタッチします。</p>
				<h2>ブレンドしながらアニメーションを再生する</h2>
				<p>最後に本題の<strong>StepAnimTime関数</strong>について説明しましょう。この関数は必要に応じてアタッチ、デタッチ、ブレンド、再生時間の設定を行う関数です。少し長めなのでちょっとずつ説明していきます。</p>
				<p><strong>_utils.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="cd420536-3f78-4068-9b94-8b2279287e2e" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//アニメーション進行
void StepAnimTime(AnimInfo *ainfo, int animindex){
	//アタッチを変更する必要があるかどうかチェック
	if(ainfo-&gt;anim != animindex){
		//古い物をデタッチ
		if(ainfo-&gt;oldattach != -1){
			MV1DetachAnim(ainfo-&gt;model, ainfo-&gt;oldattach);
			ainfo-&gt;oldattach = -1;
		}
		//古い情報を待避
		ainfo-&gt;oldanim = ainfo-&gt;anim;
		ainfo-&gt;oldattach = ainfo-&gt;attach;
		//新しいアニメーションをアタッチ
		ainfo-&gt;anim = animindex;
		ainfo-&gt;attach = MV1AttachAnim(ainfo-&gt;model, ainfo-&gt;anim);
		//再生開始時間を記憶
		ainfo-&gt;starttime = g_stage.gametime;
	}</pre>
				</div>
				<p>まず、AnimInfo構造体のアニメーション番号animと引数animindexを比較して、<strong>アタッチするアニメーションを切り替える必要があるかどうか</strong>をチェックします。ここまでは前回の解説と考え方は同じです。</p>
				<p>ただし、単純に現在のものをデタッチして、新しいものをアタッチするのではなく、古いものが存在すればそれをデタッチしてから、現在のものをoldanimとoldattatchに移し、その後で新しいアニメーションをアタッチします。次の図のように玉突きするように置き換えていくイメージです。</p>
				<p align="center"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001579" src="http://i-libro.net/wpmu/files/2011/02/ws0015791.jpg" width="231" height="242" /></p>
				<p>最後に現在時間をAnimInfo構造体の<strong>starttime</strong>に記憶します。</p>
				<p>続いて、現在のアニメーションに再生時間を設定します。この部分は関数を見やすくするために、<strong>StepAnimTimeSub</strong>という別関数に切り出しています。中でやっていることは前回記事で説明した再生時間の設定とほぼ同じです。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="ad53ca91-dbe5-4e20-a82f-1053de64faf8" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//メインのアニメーションの時間を設定
	StepAnimTimeSub(ainfo-&gt;model, ainfo-&gt;attach);
</pre>
				</div>
				<p>次にブレンド処理が必要かどうかを判定します。この判定には先に説明した、<strong>「現在時間－starttime &lt; ANIMBLENDTIME」</strong>という式を使います。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="44f88b9c-c0cf-426c-84ed-4a6345a9f98c" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//ブレンドが必要かどうか
	int time = g_stage.gametime - ainfo-&gt;starttime;
	if(time &lt; ANIMBLENDTIME &amp;&amp; ainfo-&gt;oldattach != -1){
		float brate = (float)time / (float)ANIMBLENDTIME;
		MV1SetAttachAnimBlendRate(ainfo-&gt;model, ainfo-&gt;attach, brate);
		//古いアニメーションのブレンドと時間設定
		MV1SetAttachAnimBlendRate(ainfo-&gt;model, ainfo-&gt;oldattach, 1.0f-brate);
		StepAnimTimeSub(ainfo-&gt;model, ainfo-&gt;oldattach);
</pre>
				</div>
				<p>ブレンド処理が必要と判定された場合は、「現在時間－starttime」をANIMBLENDTIMEで割ってブレンド率<strong>brate</strong>を求め、現在のアニメーションにはそのままbrateを設定し、古いアニメーションには「1.0f－brate」を設定していきます。これで徐々に古いアニメーションから現在のアニメーションへと変わって行きます。古いアニメーションも忘れずに再生時間を設定してアニメーションを進行させます。</p>
				<p>ブレンド処理が不要と判定された場合は、以下の処理を行います。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="45d8108b-3c95-4a68-9b06-a7e6b7915573" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	} else {
		//ブレンドレートを1にする
		MV1SetAttachAnimBlendRate(ainfo-&gt;model, ainfo-&gt;attach, 1.0f);
		//古いものをデタッチ
		if(ainfo-&gt;oldattach != -1){
			MV1DetachAnim(ainfo-&gt;model, ainfo-&gt;oldattach);
			ainfo-&gt;oldattach = -1;
		}
	}
}
</pre>
				</div>
				<p>現在のアニメーションのブレンド率を1に設定し、古いアニメーションがまだアタッチされたままなら、デタッチしてoldattachに－1を代入します。</p>
				<p>これで簡単に複数の3Dアニメーションが扱えるようになりました。</p>
				<p>&#160;</p>
				<p>これで<strong>3Dグラフィックスを使った2Dゲーム</strong>を作るために必要な知識は、一通り説明が終わりました。次の最終記事ではその実例として、1ヶ月ほど前に作った<a href="http://i-libro.net/wpmu/blog/archives/451">マリオもどきのテストプログラム</a>と今回のプログラムを組み合わせ、<strong>MMDモデルを使ったマリオ風ゲーム</strong>を作成します。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/910/feed</wfw:commentRss>
		</item>
		<item>
		<title>【DXライブラリ3D入門】モデルをアニメーションさせよう（後編）</title>
		<link>http://i-libro.net/wpmu/blog/archives/876</link>
		<comments>http://i-libro.net/wpmu/blog/archives/876#comments</comments>
		<pubDate>Sun, 27 Feb 2011 06:53:48 +0000</pubDate>
		<dc:creator>ari</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[C言語（Windows）]]></category>

		<category><![CDATA[DXライブラリ]]></category>

		<guid isPermaLink="false">http://i-libro.net/wpmu/blog/archives/876</guid>
		<description><![CDATA[				お知らせ：DXライブラリオンライン関数リファレンス付録編の3D関数編を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」のリファレンスをご参照ください）。
				注：本記事で配布するソースコードにはモデルデータは含めませんので、それぞれの配布元から別途ダウンロードしてください（詳しくは初回記事を参照）
				
				前回記事ではMikuMikuDanceを使ってモーションファイル（VMD形式）を作成しました。今回はそのモーションファイルをDXライブラリで読み込んで再生します。ゲームとまではいきませんが、キー操作に合わせて「立つ」「走る」「ジャンプする」の3つのモーションが切り替わるようにします。 
				
				今回の作例    ©CRYPTON FUTURE MEDIA, INC.     解説中で使用しているモデルは前回に続きenamel toy box（ハッチさん運営）で公開されている「PMDねんどろ風初音ミクv1.1」
				  
				DXライブラリのアニメーション関数
				これまではソースコードを少しずつ改造していく流れで説明していましたが、今回は変更点がちょっと多めです。そこで先に完成状態のソースコードをダウンロードし、それを見ながら解説を読み進めてください。
				DXB2D_3DTest_src05.zip（要Visual C++ 2010 Express）
				このファイルをダウンロードして解凍したら、そのフォルダ内にmediaフォルダを作成し、モデルファイル、テクスチャファイル（texフォルダ）、トゥーンマップの画像ファイル、そして3つのモーションファイルをコピーします。
				
				MMD_Miku_O_vmd.zip（モーションファイル）
				&#160;
				準備が終わったところで、DXライブラリのアニメーション関数について説明していきましょう。少々ややこしいので、まずは概要から説明していきます。
				MV1LoadModel関数の説明によると、DXライブラリはモデルファイルの読み込みと同時にモーションファイルを読み込みます。本来はモーションデータを中に持ったモデルファイルを想定しているようですが、MikuMikuDanceではモデルはPMD、モーションはVMDに分かれています。そこで、PMDファイルを読み込む際に、同じフォルダ内に「モデルファイル名＋000から始まる3桁の連番.vmd」という名前のモーションファイルがあれば、それを読み込むしくみになっています。
				
				読み込まれたモーションファイルは、モデルデータに紐づけされたアニメーションデータとなります。利用するときは、モデルハンドルとアニメーション番号を組み合わせて指定します。アニメーション番号はVMDファイルの名前に含まれていた連番です。
				アニメーションは複数あるので、どれを使うかを選ばねばなりません。その処理のことを、アニメーションをモデルにアタッチする、といいます。次回の説明になりますが、複数のアニメーションをアタッチし、ブレンドして使うことも可能です。
				MV1AttachAnim関数を使ってアニメーションをアタッチすると、アタッチ番号というものが返され、以降はそれを使ってアニメーションを制御します。アニメーション番号とアタッチ番号は混同しやすいので注意してください。アタッチ番号はモデルに複数のアニメーションがアタッチされているときにそれを区別するために使われるもので、1つしかアタッチしないときは常に0になります。
				
				アタッチが終わったら、アニメーションを進行させます。そのためにゲームのメインループ中で、MV1SetAttachAnimTime関数を使ってアニメーションの再生時間を設定し続けなければいけません。たとえば、4秒間のアニメーションだったら、0～4まで増える数値を設定し続ける必要があります。これをどう処理するかがアニメーション処理のキモとなるでしょう。
				
				再生時間を設定する際に注意が必要なのは、MikuMikuDanceでは1フレームの経過時間が1/30秒なのに対し、DXライブラリでは1フレーム＝1秒として処理する点です。そのため、DXライブラリで設定する再生時間は、通常の30倍のスピードで変化させる必要があります。
				モーションの読み込みとアタッチ
				では、実際のソースコードを見て、具体的な説明をしていきましょう。ゲーム進行中のデータを記憶するStageInfo構造体に現在再生しているアニメーション番号とアタッチ番号を記憶するメンバ変数を追加します。また、アニメーションを指定しやすくするために、HERO_STAND、HERO_RUN、HERO_JUMPという定数を持つHeroState列挙体を定義します。
				main.h
				
				//ゲームデータ記録用構造体
struct StageInfo{
	int timerstart;			//待機タイマーの開始時刻
	int gamestarttime;		//ゲームの開始時間
	int gametime;			//ゲーム開始からの経過ミリ秒
	float mapsize_w, mapsize_h;	//マップサイズ
	int screen_x, screen_y;	//表示原点（スクロール用）

	VECTOR heropos;	//主人公の位置
	int hero_anim;	//主人公のアニメーション番号
	int hero_attach;//アタッチ番号
};
//アニメーション用ポーズ定数
enum HeroState{HERO_STAND, HERO_RUN, HERO_JUMP};
				
				以前のソースコードでは、LoadFiles関数内でモデルデータを読み込んだ後、拡大したり輪郭線の幅を変更したりしていましたが、今回からカメラの位置で大きさを調整することにしたのでそれらは必要ありません。おかげでかなりシンプルになります。
				main.cpp
				
				//ファイルの読み込み
int LoadFiles(){
	//ファイル読み込み処理をここに書く
	g_images.hero = MV1LoadModel("media\\MMD_Miku_O.pmd");
	if(g_images.hero == -1) return -1;
	//読み込み成功
	return 1;
}
				
				ステージ開始時に呼び出されるInitStage関数の中で、「立つ」アニメーションをアタッチします。
				main.cpp
				
				//ステージ初期化
void InitStage(){
	//ゲームデータ全体のゼロ初期化
	ZeroMemory(&#38;g_stage, sizeof(g_stage));
	//全ボディ・ジョイント削除
	DeleteAllBody();

	//主人公位置の初期化
	g_stage.heropos = VGet( 320.0f, 225.0f, -350.0f );
	//初期アニメ設定
	g_stage.hero_attach = MV1AttachAnim(g_images.hero, HERO_STAND);	

	//ゲーム開始時刻の記録
	g_stage.gamestarttime = [...]]]></description>
			<content:encoded><![CDATA[				<p><strong>お知らせ：</strong>DXライブラリオンライン関数リファレンス付録編の<a href="http://i-libro.net/game/c14vc2010/dxlib_reference_3d/">3D関数編</a>を公開しました。まだすべての関数の解説は揃っておりませんが、本記事を読む助けとしていただければ幸いです（足りない関数については本家「DXライブラリ置き場」の<a href="http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_3d.html">リファレンス</a>をご参照ください）。</p>
				<p><strong>注：</strong>本記事で配布するソースコードには<strong>モデルデータは含めません</strong>ので、それぞれの配布元から別途ダウンロードしてください（詳しくは<a href="http://i-libro.net/wpmu/blog/archives/495">初回記事</a>を参照）</p>
				<hr />
				<p>前回記事ではMikuMikuDanceを使ってモーションファイル（VMD形式）を作成しました。今回はそのモーションファイルをDXライブラリで読み込んで再生します。ゲームとまではいきませんが、キー操作に合わせて「立つ」「走る」「ジャンプする」の<strong>3つのモーションが切り替わる</strong>ようにします。 </p>
				<p><a href="http://i-libro.net/wpmu/files/2011/02/ws001486.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001486" src="http://i-libro.net/wpmu/files/2011/02/ws001486-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/02/ws001491.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001491" src="http://i-libro.net/wpmu/files/2011/02/ws001491-thumb.jpg" width="244" height="193" /></a></p>
				<p>今回の作例    <br />©CRYPTON FUTURE MEDIA, INC.     <br />解説中で使用しているモデルは前回に続き<a href="http://enamelhp.web.fc2.com/">enamel toy box</a>（ハッチさん運営）で公開されている「<b>PMDねんどろ風初音ミク</b><b>v1.1</b>」</p>
				<p>  <span id="more-876"></span><br />
				<h2>DXライブラリのアニメーション関数</h2>
				<p>これまではソースコードを少しずつ改造していく流れで説明していましたが、今回は変更点がちょっと多めです。そこで先に<strong>完成状態のソースコード</strong>をダウンロードし、それを見ながら解説を読み進めてください。</p>
				<p><a href="http://i-libro.net/game/download.php?fname=DXB2D_3DTest_src05.zip">DXB2D_3DTest_src05.zip</a>（要Visual C++ 2010 Express）</p>
				<p>このファイルをダウンロードして解凍したら、そのフォルダ内に<strong>mediaフォルダ</strong>を作成し、モデルファイル、テクスチャファイル（texフォルダ）、トゥーンマップの画像ファイル、そして3つのモーションファイルをコピーします。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/02/ws0015221.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001522" src="http://i-libro.net/wpmu/files/2011/02/ws001522-thumb1.jpg" width="304" height="233" /></a></p>
				<p><a href="http://i-libro.net/game/download.php?fname=MMD_Miku_O_vmd.zip">MMD_Miku_O_vmd.zip</a>（モーションファイル）</p>
				<p>&#160;</p>
				<p>準備が終わったところで、DXライブラリのアニメーション関数について説明していきましょう。少々ややこしいので、まずは概要から説明していきます。</p>
				<p>MV1LoadModel関数の説明によると、DXライブラリはモデルファイルの読み込みと同時にモーションファイルを読み込みます。本来はモーションデータを中に持ったモデルファイルを想定しているようですが、MikuMikuDanceではモデルはPMD、モーションはVMDに分かれています。そこで、PMDファイルを読み込む際に、同じフォルダ内に<strong>「モデルファイル名＋000から始まる3桁の連番.vmd」</strong>という名前のモーションファイルがあれば、それを読み込むしくみになっています。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001524" src="http://i-libro.net/wpmu/files/2011/02/ws0015241.jpg" width="342" height="193" /></p>
				<p>読み込まれたモーションファイルは、モデルデータに紐づけされた<strong>アニメーションデータ</strong>となります。利用するときは、<strong>モデルハンドルとアニメーション番号</strong>を組み合わせて指定します。アニメーション番号はVMDファイルの名前に含まれていた連番です。</p>
				<p>アニメーションは複数あるので、どれを使うかを選ばねばなりません。その処理のことを、アニメーションをモデルに<strong>アタッチ</strong>する、といいます。次回の説明になりますが、複数のアニメーションをアタッチし、ブレンドして使うことも可能です。</p>
				<p><strong>MV1AttachAnim関数</strong>を使ってアニメーションをアタッチすると、<strong>アタッチ番号</strong>というものが返され、以降はそれを使ってアニメーションを制御します。アニメーション番号とアタッチ番号は混同しやすいので注意してください。アタッチ番号はモデルに複数のアニメーションがアタッチされているときにそれを区別するために使われるもので、1つしかアタッチしないときは常に0になります。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001526" src="http://i-libro.net/wpmu/files/2011/02/ws0015261.jpg" width="242" height="196" /></p>
				<p>アタッチが終わったら、アニメーションを進行させます。そのためにゲームのメインループ中で、<strong>MV1SetAttachAnimTime関数</strong>を使って<strong>アニメーションの再生時間を設定</strong>し続けなければいけません。たとえば、4秒間のアニメーションだったら、0～4まで増える数値を設定し続ける必要があります。これをどう処理するかがアニメーション処理のキモとなるでしょう。</p>
				<p><img style="padding-left: 0px;padding-right: 0px;float: none;margin-left: auto;margin-right: auto;padding-top: 0px" border="0" alt="WS001527" src="http://i-libro.net/wpmu/files/2011/02/ws0015271.jpg" width="402" height="132" /></p>
				<p>再生時間を設定する際に注意が必要なのは、MikuMikuDanceでは<strong>1フレームの経過時間が1/30秒</strong>なのに対し、DXライブラリでは<strong>1フレーム＝1秒</strong>として処理する点です。そのため、DXライブラリで設定する再生時間は、通常の30倍のスピードで変化させる必要があります。</p>
				<h2>モーションの読み込みとアタッチ</h2>
				<p>では、実際のソースコードを見て、具体的な説明をしていきましょう。ゲーム進行中のデータを記憶するStageInfo構造体に<strong>現在再生しているアニメーション番号</strong>と<strong>アタッチ番号</strong>を記憶するメンバ変数を追加します。また、アニメーションを指定しやすくするために、HERO_STAND、HERO_RUN、HERO_JUMPという定数を持つ<strong>HeroState列挙体</strong>を定義します。</p>
				<p><strong>main.h</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="1d408182-858c-4c1d-b4e7-3ea5a630d970" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//ゲームデータ記録用構造体
struct StageInfo{
	int timerstart;			//待機タイマーの開始時刻
	int gamestarttime;		//ゲームの開始時間
	int gametime;			//ゲーム開始からの経過ミリ秒
	float mapsize_w, mapsize_h;	//マップサイズ
	int screen_x, screen_y;	//表示原点（スクロール用）

	VECTOR heropos;	//主人公の位置
	int hero_anim;	//主人公のアニメーション番号
	int hero_attach;//アタッチ番号
};
//アニメーション用ポーズ定数
enum HeroState{HERO_STAND, HERO_RUN, HERO_JUMP};</pre>
				</div>
				<p>以前のソースコードでは、LoadFiles関数内でモデルデータを読み込んだ後、拡大したり輪郭線の幅を変更したりしていましたが、今回からカメラの位置で大きさを調整することにしたのでそれらは必要ありません。おかげでかなりシンプルになります。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="686a2cc2-8be2-48f9-b2d2-8431bf6a677a" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//ファイルの読み込み
int LoadFiles(){
	//ファイル読み込み処理をここに書く
	g_images.hero = MV1LoadModel("media\\MMD_Miku_O.pmd");
	if(g_images.hero == -1) return -1;
	//読み込み成功
	return 1;
}</pre>
				</div>
				<p>ステージ開始時に呼び出されるInitStage関数の中で、「立つ」アニメーションをアタッチします。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="67dea04f-3f87-476c-945c-d5659696ed74" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">//ステージ初期化
void InitStage(){
	//ゲームデータ全体のゼロ初期化
	ZeroMemory(&amp;g_stage, sizeof(g_stage));
	//全ボディ・ジョイント削除
	DeleteAllBody();

	//主人公位置の初期化
	g_stage.heropos = VGet( 320.0f, 225.0f, -350.0f );
	//初期アニメ設定
	g_stage.hero_attach = MV1AttachAnim(g_images.hero, HERO_STAND);	

	//ゲーム開始時刻の記録
	g_stage.gamestarttime = g_lasttime;
}</pre>
				</div>
				<p>11行目でMV1AttachAnim関数に2つの引数を指定していますが、省略可能なものを含めると4つの引数を指定できます。</p>
				<blockquote>
				<p><strong>アニメーションをアタッチする</strong></p>
				<p>int MV1AttachAnim( int MHandle, int AnimIndex, int AnimSrcMHandle, int NameCheck ) ;</p>
				</blockquote>
				<p>引数<strong>MHandle</strong>はモデルハンドル、<strong>AnimIndex</strong>はアニメーション番号です。残りの2つの引数は、他のモデルが持つアニメーションをアタッチするときに使います。<strong>AnimSrcMHandle</strong>にはアニメーションを持つモデルのハンドルを指定します。モデルのフレーム（MikuMikuDanceでのボーンのこと）の構造が違うとうまくアタッチできない場合がありますが、<strong>NameCheck</strong>にTRUEを指定すると、フレームの名前が一致しない場合はアタッチされないようになります。</p>
				<h2>キー操作に合わせてアニメーションを切り替える</h2>
				<p>アニメーションの再生処理はDrawGameMain関数の中にあります。長めなので少しずつ見ていきます。まずはキーの状態に合わせて再生するアニメーションを切り替える部分です。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="f85e84e3-0cb0-47ab-afe1-4a8ad11d2c6b" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">void DrawGameMain(){
	DrawBox(0,0,640,480, 0xFFDDDD, TRUE);
	//キー取得
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);

	int herostate = HERO_STAND;
	if((key &amp; PAD_INPUT_LEFT) || (key &amp; PAD_INPUT_RIGHT)) {
		herostate = HERO_RUN;
	}
	if(key &amp; PAD_INPUT_B){
		herostate = HERO_JUMP;
	}</pre>
				</div>
				<p>何も押していないときは変数herostateにHERO_STANDが代入され、左右のカーソルキーを押したときはHERO_RUN、Xキー（ジョイパッドならBボタン）が押されたときはHERO_JUMPが代入されるようにしています。</p>
				<p>続いてアニメーションのアタッチです。herostateの値に応じ、必要ならアタッチするアニメーションを切り替えます。現在再生しているアニメーション番号はg_stageのメンバhero_animに記憶しているので、それとherostateを比較すれば、切り替えが必要かどうかがわかります。</p>
				<p><strong>main.cpp</strong></p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="fcac0d6a-fec0-42c8-bc0b-091ae1ecbdc4" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//アニメーション設定
	//現在のアニメーションのアタッチ番号取得
	//アタッチを変更する必要があるかどうかチェック
	if(g_stage.hero_anim != herostate){
		//古い物をデタッチ
		MV1DetachAnim(g_images.hero, g_stage.hero_attach);
		//新しいアニメーションをアタッチ
		g_stage.hero_anim = herostate;
		g_stage.hero_attach = MV1AttachAnim(g_images.hero, g_stage.hero_anim);
	}</pre>
				</div>
				<p>新しいアニメーションをアタッチする前に、古いアニメーションを外さなければいけません。その処理を<strong>デタッチ</strong>といいます。</p>
				<blockquote>
				<p>int MV1DetachAnim( int MHandle, int AttachIndex ) ;</p>
				</blockquote>
				<p>MV1DetachAnim関数の引数はモデルハンドルと<strong>アタッチ番号</strong>です。<strong>アニメーション番号ではありません</strong>ので間違わないよう注意してください。 </p>
				<p>デタッチした後は、新しいアニメーションをアタッチし、アニメーション番号とアタッチ番号をg_stageに記憶します。</p>
				<h2>アニメーションの再生時間を進める</h2>
				<p>アニメーションの再生時間は、実際の時間進行と同じスピードで、0～終了時間まで設定し続けなければいけません。ゲーム開始からの経過時間がg_stageのメンバgametimeに記憶しているので、それをうまく使うようにします。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="4a506afb-d904-46e0-87f2-e7f2966f865d" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">	//時間進行
	//総時間取得
	int totaltime = (int)(MV1GetAttachAnimTotalTime(g_images.hero, g_stage.hero_attach) * 1000.0f);
	//アニメーション時間を算出して設定（MMDでは1フレーム＝1/30秒なので補正が必要）
	float animtime;
	if(totaltime == 0) animtime = 0.0f;
	else {
		animtime = (float)(g_stage.gametime * 30 % totaltime) / 1000.0f;
	}
	MV1SetAttachAnimTime(g_images.hero, g_stage.hero_attach, animtime);
	clsDx();printfDx("%6.3f\n", animtime);//時間チェック
	printfDx("%d", g_stage.hero_attach);//アタッチ番号チェック
</pre>
				</div>
				<p>まず、<strong>MV1GetAttachAnimTotalTIme関数</strong>を使ってアニメーションの総時間を取得します（3行目）。この関数はfloat型の値を返しますが、int型のミリ秒と組み合わせて計算させたいので、1000を掛けてint型にキャストします。</p>
				<blockquote>
				<p>float MV1GetAttachAnimTotalTime( int MHandle, int AttachIndex ) ;</p>
				</blockquote>
				<p>もし<strong>総時間が0（1つのフレームしかない状態）</strong>だった場合、設定する再生時間も0にしないとエラーになります。そのための確認を6行目で行っています。</p>
				<p>続いて次の計算式で再生時間を求めます。</p>
				<table border="0" cellspacing="0" cellpadding="2" width="522">
				<tbody>
				<tr>
				<td valign="top" width="522">(float)(g_stage.gametime * 30 % totaltime) / 1000.0f;</td>
				</tr>
				</tbody>
				</table>
				<p>gametimeに30を掛けてからtotaltimeで割った余りを求めることで、0～totaltimeまで変化する数値を取得します。それを1000で割った実数にすると再生時間が求められます。先に説明したとおり、<strong>経過時間に30を掛ける</strong>ところがポイントです。求められる再生時間は0～totaltimeですが、実際の30倍の速度で時間が変化します。</p>
				<p>最後に<strong>MV1SetAttachAnimTime関数</strong>で再生時間を設定します。</p>
				<blockquote>
				<p>int MV1SetAttachAnimTime( int MHandle, int AttachIndex, float Time ) ;</p>
				</blockquote>
				<p>ここまでで重要な部分はおしまいです。後はこれまで説明したものと同じように、モデルの移動・表示、カメラの設定を行います。標準は右方向からの視点ですが、Cキーを押すと正面からの視点に変わるようにしています。</p>
				<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" id="3a839ba8-7fd4-49ee-a14e-9287581a7ef5" class="wlWriterEditableSmartContent">
				<pre name="code" class="c">
	//移動と表示
	MV1SetPosition(g_images.hero, g_stage.heropos);
	MV1DrawModel(g_images.hero) ;
	MV1SetPosition(g_images.hero, VAdd(g_stage.heropos, VGet(15, 0, 15)) );
	MV1DrawModel(g_images.hero) ;
	MV1SetPosition(g_images.hero, VAdd(g_stage.heropos, VGet(-15, 0, 15)) );
	MV1DrawModel(g_images.hero) ;

	//カメラの設定
	SetCameraPositionAndTarget_UpVecY(VGet(270.0f, 240.0f, -345.0f),
		VAdd(g_stage.heropos, VGet(0, 1, 10)) );
	//ちょっとした視点変更
	if(key &amp; PAD_INPUT_C){
		SetCameraPositionAndTarget_UpVecY(VGet(320.0f, 240.0f, -385.0f),
			VAdd(g_stage.heropos, VGet(0, 1, 25)) );
	}
	SetCameraNearFar(10, 1000);
	SetupCamera_Perspective( PHI_F / 5 );
	//SetupCamera_Ortho(150);
}</pre>
				</div>
				<p>実行すると最初は立ちモーションで再生されます。カーソルの左右キーのどちらかを押すと走るモーション、Xキーを押すとジャンプします。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/02/ws001528.jpg"><img style="margin: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001528" src="http://i-libro.net/wpmu/files/2011/02/ws001528-thumb.jpg" width="244" height="193" /></a><a href="http://i-libro.net/wpmu/files/2011/02/ws001531.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001531" src="http://i-libro.net/wpmu/files/2011/02/ws001531-thumb.jpg" width="244" height="193" /></a></p>
				<p>Cキーを押すと正面からの視点に切り替わります。左上の数値は計算で求めた<strong>再生時間</strong>と<strong>アタッチ番号</strong>です。</p>
				<p><a href="http://i-libro.net/wpmu/files/2011/02/ws001532.jpg"><img style="padding-left: 0px;padding-right: 0px;padding-top: 0px" border="0" alt="WS001532" src="http://i-libro.net/wpmu/files/2011/02/ws001532-thumb.jpg" width="244" height="193" /></a></p>
				<p>&#160;</p>
				<p>これで目的は果たせていますが、アニメーションの切り替わりがぎこちないですね。そこで次回は<strong>アニメーションをブレンドして切り替わりをより滑らかに</strong>する方法を説明します。</p>
]]></content:encoded>
			<wfw:commentRss>http://i-libro.net/wpmu/blog/archives/876/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

