BaseCrossDx12ドキュメント
【Sample103】物理計算
このサンプルは
Samples/Sample103ディレクトリ内にあります。
VisualStdioで該当ソリューション(VS2022では
BaseCrossDx12VS2022.sln、VS2026では
BaseCrossDx12VS2026.sln)を開いてください。
ビルド後実行すると、以下の画面が現れます。
BaseCrossDx12における物理演算
BaseCrossDx12では物理演算に
PhysXを使っています。それらは
コンポーネントとして実装されます。
RigidbodyStaticコンポーネント
以下は動かないオブジェクト
FixedBoxの
OnCreate()関数です。
void FixedBox::OnCreate() {
//Transformコンポーネントを取り出す
auto ptrTrans = GetComponent<Transform>();
auto& param = ptrTrans->GetTransParam();
//PhysX関連
PhysxCreateParam pxParam;
physx::PxBoxGeometry scale(param.scale.x * 0.5f, param.scale.y * 0.5f, param.scale.z * 0.5f);
pxParam.pGeometry = &scale;
AddComponent<RigidbodyStatic>(pxParam);
auto ptrShadow = AddComponent<Shadowmap>();
ptrShadow->AddBaseMesh(L"DEFAULT_CUBE");
auto ptrDraw = AddComponent<BcPNTStaticDraw>();
ptrDraw->AddBaseMesh(L"DEFAULT_CUBE");
ptrDraw->AddBaseTexture(L"SKY_TX");
ptrDraw->SetOwnShadowActive(true);
}
赤くなっているところが
PhysXのコンポーネント
RigidbodyStaticを実装しているところです。
台座のオブジェクトですね。
physx::PxBoxGeometry scale(param.scale.x * 0.5f, param.scale.y * 0.5f, param.scale.z * 0.5f);で形状がBoxタイプであることを指定しています。
BaseCrossDx12の計算尺とのやり取りは、
param.scale.x * 0.5f, param.scale.y * 0.5f, param.scale.z * 0.5fのようにします。あとは内部で自動計算します。
RigidbodyDynamicコンポーネント
続いて上から降ってくるオブジェクトです。
WallBox::OnCreate()は以下です。
void WallBox::OnCreate() {
auto ptrGameStage = std::dynamic_pointer_cast<GameStage>(GetStage());
//Transformコンポーネントを取り出す
auto ptrTrans = GetComponent<Transform>();
auto& param = ptrTrans->GetTransParam();
//PhysX関連
PhysxCreateParam pxParam;
physx::PxBoxGeometry scale(param.scale.x * 0.5f, param.scale.y * 0.5f, param.scale.z * 0.5f);
pxParam.pGeometry = &scale;
auto pRigDynamicComp = AddComponent<RigidbodyDynamic>(pxParam);
auto pRigDynamic = pRigDynamicComp->GetRigidDynamic();
auto ptrShadow = AddComponent<Shadowmap>();
ptrShadow->AddBaseMesh(L"DEFAULT_CUBE");
auto ptrDraw = AddComponent<BcPNTStaticDraw>();
ptrDraw->AddBaseMesh(L"DEFAULT_CUBE");
ptrDraw->AddBaseTexture(L"WALL_TX");
ptrDraw->SetOwnShadowActive(true);
//ジャンプさせる
pRigDynamic->addForce(physx::PxVec3(0, 10, 0), physx::PxForceMode::eIMPULSE);
}
ここでは、動くオブジェクトである
RigidbodyDynamicコンポーネントが実装されています。
physx::PxBoxGeometryがBoxタイプを指定しています。
プレイヤーのコンポーネント
最後に
プレイヤーです。以下は
Player::OnCreate()です。
void Player::OnCreate() {
GetStage()->SetSharedGameObject(L"Player", GetThis<Player>());
//Transformコンポーネントを取り出す
auto ptrTrans = GetComponent<Transform>();
auto& param = ptrTrans->GetTransParam();
//PhysX関連
PhysxCreateParam pxParam;
physx::PxSphereGeometry scale(param.scale.x * 0.5f);
pxParam.pGeometry = &scale;
pxParam.staticFriction = 1.0f;
pxParam.dynamicFriction = 1.0f;
pxParam.restitution = 1.0f;
auto pRigDynamicComp = AddComponent<RigidbodyDynamic>(pxParam);
auto pRigDynamic = pRigDynamicComp->GetRigidDynamic();
auto ptrShadow = AddComponent<Shadowmap>();
ptrShadow->AddBaseMesh(L"DEFAULT_SPHERE");
auto ptrDraw = AddComponent<BcPNTStaticDraw>();
ptrDraw->AddBaseMesh(L"DEFAULT_SPHERE");
ptrDraw->AddBaseTexture(L"TRACE_TX");
//透明処理
SetAlphaActive(true);
//カメラを得る
auto ptrCamera = std::dynamic_pointer_cast<MyCamera>(GetStage()->GetCamera());
if (ptrCamera) {
//MyCameraである
//MyCameraに注目するオブジェクト(プレイヤー)の設定
ptrCamera->SetTargetObject(GetThis<GameObject>());
ptrCamera->SetTargetToAt(Vec3(0, 0.25f, 0));
}
}
ここでは
physx::PxSphereGeometry scale(param.scale.x * 0.5f);のように
球体を指定しています。
あとは
auto pRigDynamicComp = AddComponent<RigidbodyDynamic>(pxParam);で動く物理計算である、
RigidbodyDynamicをコンポーネントに追加すれば実装完了です。
プレイヤーの動き
このオブジェクトはコントローラで動けるようにします。それを実装しているのは以下です。
void Player::MovePlayer() {
float elapsedTime = (float)Scene::GetElapsedTime();
auto angle = GetMoveVector();
//RigidbodyDynamicコンポーネントを取り出す
auto ptrRigid = GetComponent<RigidbodyDynamic>();
auto pRigDynamic = ptrRigid->GetRigidDynamic();
if (angle.length() > 0.0f) {
Vec3 tmpVelo = angle * m_Speed;
pRigDynamic->setLinearVelocity(bsmUtil::ToPxVec3(tmpVelo));
}
else {
pRigDynamic->setLinearVelocity(bsmUtil::ToPxVec3(Vec3(0)));
}
}
auto pRigDynamic = ptrRigid->GetRigidDynamic();のように
RigidDynamicオブジェクトを取り出し、
pRigDynamic->setLinearVelocity()関数で、
速度を変更します。物理オブジェクトでは基本的に
位置情報などを直接変更しません。
setLinearVelocityのように
間接的に操作します。
物理計算を使う場合の気を付けるべきこと
このように
物理計算を使う場合、非常に簡単に
リアルな世界を実装できます(
Sample101の記述量と比べると一目瞭然です)。しかし
BaseCrossDx12は
ゲームのフレームワークです。今後
モデルを
物理計算に使うサンプルも紹介しますが、そうなると、
現実社会のシミュレーション的な世界が構築できるようになります。
しかし考えてみてください。私たちの作りたいのは
ゲームです。このあたりをよく考えながら、今後も
BaseCrossDx12をご利用いただければ幸いです。