スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

DXライブラリでBullet

こんにちは。
毎度間が空くペチコです。

歳を重ねると年単位が「先日」と思うようになるのです。ヨボヨボ



しばらく放って置いたらシェーダの事がすっぱり頭から抜け落ちてしまったので
物理演算エンジンBulletで遊んでみようと思いました。

Bullet公式ページ

VS2005のせいか最新の2.81はビルドエラー頻出だったので2.78を使ってます。
DXライブラリさんがBulletも使えるように重複名称等考えてくれてますので、リファレンス通りcmakeでプロジェクトを作ってVC++でビルドしたらすんなりインストールできました。
ホントDXライブラリさんの気配りには頭が下がります。

ただ数カ所VS2005では使えない関数があったので同種のものに置き換えてビルドしました。
なにぶんインストール自体は随分と前にやってたのでどこを変更したか覚えてないのです。


新しい事柄にチャレンジする場合は取り敢えず"Hello World"の表示と相場が決まってますので、
こちらのサイト様こちらのサイト様を参考にDXライブラリ用に実装してみました。


#include "DxLib.h"
#include <btBulletDynamicsCommon.h>

//プラグマ宣言リンカ
#pragma comment( lib, "BulletCollision.lib" )
#pragma comment( lib, "BulletDynamics.lib" )
#pragma comment( lib, "BulletSoftBody.lib" )
#pragma comment( lib, "LinearMath.lib" )

//右手→左手位置変換
VECTOR btVGet(const btVector3 &inv){return VGet(inv.getX(), inv.getY(), -inv.getZ());}
//右手→左手回転変換
VECTOR btRotVGet(const btVector3 &inv){return VGet(-inv.getX(), -inv.getY(), inv.getZ());}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
//モデルハンドル
int Model_Handle ;

//カメラポジション
VECTOR CameraPos ;

// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;

// DXライブラリの初期化
if( DxLib_Init() < 0 )
{
// エラーが発生したら直ちに終了
return -1 ;
}

// 画面モードの変更
SetGraphMode( 1024 , 768 , 32 ) ;

// 剛体メッシュモデルを読み込む
Model_Handle = MV1LoadModel( "dice.mv1" ) ;

// カメラの座標を初期化
CameraPos.x = 0.0f ;
CameraPos.y = 5.0f ;
CameraPos.z = -20.0f ;

//モデル構造体
struct MODEL_DICE
{
VECTOR pos ;
} ;

// モデル情報の実体宣言
MODEL_DICE mdl ;
mdl.pos.x = 0.0f ;
mdl.pos.y = 20.0f;
mdl.pos.z = 0.0f ;

// ワールドの広さ
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
// プロキシの最大数(衝突物体のようなもの)
int maxProxies = 1024;
// broadphaseの作成(SAP法)
btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

// デフォルトの衝突設定とディスパッチャの作成
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

// 衝突解決ソルバ
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
// 離散動的世界の作成
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
// 重力の設定
dynamicsWorld->setGravity(btVector3(0,-10,0));
// 地面の衝突形状の作成
btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
// 地面のMotionStateの設定
btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));

// 地面の初期情報を設定
btRigidBody::btRigidBodyConstructionInfo
groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
// 地面の剛体の作成
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
// ワールドに地面の剛体を追加
dynamicsWorld->addRigidBody(groundRigidBody);

// 落下する箱の衝突形状の作成
btCollisionShape* fallShape = new btBoxShape(btVector3(1.0f, 1.0f, 1.0f));
// 箱のMotionStateの設定
btDefaultMotionState* fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(mdl.pos.x,mdl.pos.y,mdl.pos.z)));

// 質量、慣性の初期化
btScalar mass = 1;
btVector3 fallInertia(0,0,0);
fallShape->calculateLocalInertia(mass,fallInertia);
// 箱の初期情報を設定
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
// 箱の剛体の作成
btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
// ワールドに箱の剛体を追加
dynamicsWorld->addRigidBody(fallRigidBody);

// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;

//クリップ距離
SetCameraNearFar( 1.0f, 1000.0f ) ;
// カメラの位置と注視点をセット
SetCameraPositionAndTarget_UpVecY( CameraPos, VGet( 0.0f, 10.0f, 0.0f ) ) ;

// ESCキーが押されるまでループ
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{

// 画面を初期化
ClearDrawScreen() ;

// シミュレーションを進める。間隔は60Hz
dynamicsWorld->stepSimulation(1/60.f,10);

// 箱の位置姿勢情報の取得
btTransform trans;
fallRigidBody->getMotionState()->getWorldTransform(trans);

// 位置取得
mdl.pos = btVGet(trans.getOrigin()) ;
//個別取得例
//mdl.pos.x=trans.getOrigin().getX();
MV1SetPosition( Model_Handle, mdl.pos ) ;

// 角度取得
btMatrix3x3 rot = trans.getBasis();
btVector3 euler;
rot.getEulerZYX(euler[2], euler[1], euler[0]);
MV1SetRotationXYZ(Model_Handle, btRotVGet(euler));

// モデルを描画
MV1DrawModel( Model_Handle ) ;

// 裏画面の内容を表画面に反映させる
ScreenFlip() ;
}

// 読み込んだモデルの削除
MV1DeleteModel( Model_Handle ) ;
// 箱の剛体を削除
dynamicsWorld->removeRigidBody(fallRigidBody);
delete fallRigidBody->getMotionState();
delete fallRigidBody;
// 地面の剛体を削除
dynamicsWorld->removeRigidBody(groundRigidBody);
delete groundRigidBody->getMotionState();
delete groundRigidBody;
// 箱の衝突形状を削除
delete fallShape;
// 地面の衝突形状を削除
delete groundShape;
// ワールド・ソルバ・その他もろもろの削除
delete dynamicsWorld;
delete solver;
delete collisionConfiguration;
delete dispatcher;
delete broadphase;

// DXライブラリの後始末
DxLib_End() ;

// ソフトの終了
return 0 ;
}


先述サイト様の丸ぱくりです。
"Hello World"文字の代わりに、大きさ1.0fの6面体サイコロが降ってくるようにしてます。
※追記:btBoxShapeは1辺の半分の長さを指定らしいので大きさ1の物体の場合は0.5fにしないといけないようです。多分

無駄な構造体とかあるのは他プロジェクトの使い回しだから。
インデントずれはもはや仕様です。

説明は先述サイト様にあるので割愛、というかまだ全く理解できてないので。
いちいちプロジェクトを開かなくてもいいように覚え書きです。

一応サイコロ(mv1ファイル)置いときます。テクスチャが無駄に1024x1024です。


DXライブラリでBullet

DXライブラリでBullet

床も何も描画してない空間にサイコロが落ちてくるだけで、物理演算の恩恵も全くないのですが(地面y:0.0fに着いた時に跳ねるくらいかな?)
取り敢えずは基本の叩き台として色々追加して行ければいいですね。

たぶんやらないけど。


コメントの投稿

非公開コメント

プロフィール

ペチコートさん

Author:ペチコートさん
大航海時代オンライン
Zephyros、Eurosサーバーに潜伏中

偽ペチコ1号・2号
ペチコの手下達
Zephyrosサーバーに潜伏中

最新記事
月別アーカイブ
カテゴリ
リンク
最新コメント
検索フォーム
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。