図1305a
中央で回転する球は点の集合です。プレイヤーで当たってみましょう。
図1305b
void PointsBall::OnCreate() { vector<VertexPositionNormalTexture> vertices; vector<uint16_t> indices; //球体を作成 MeshUtill::CreateSphere(1.0f, 28,vertices, indices); for (auto& v : vertices) { LocalData tempLocalData; tempLocalData.m_LocalPosition = v.position; //各頂点をインスタンスの位置に設定 m_LocalDataVec.push_back(tempLocalData); } //描画用メッシュの作成 float helfSize = 0.04f; Col4 col(1.0f, 1.0f, 0.0f, 1.0f); //頂点配列 vector<VertexPositionColorTexture> meshVertices = { { VertexPositionColorTexture(Vec3(-helfSize, helfSize, 0),col, Vec2(0.0f, 0.0f)) }, { VertexPositionColorTexture(Vec3(helfSize, helfSize, 0),col, Vec2(1.0f, 0.0f)) }, { VertexPositionColorTexture(Vec3(-helfSize, -helfSize, 0),col, Vec2(0.0f, 1.0f)) }, { VertexPositionColorTexture(Vec3(helfSize, -helfSize, 0),col, Vec2(1.0f, 1.0f)) }, }; //インデックス配列 vector<uint16_t> meshIndex = { 0, 1, 2, 1, 3, 2 }; //2次元平面とする(頂点数が少ないため) m_MeshRes = MeshResource::CreateMeshResource(meshVertices, meshIndex, true); //全体の位置関連 auto ptrTransform = GetComponent<Transform>(); ptrTransform->SetScale(Vec3(m_Scale)); ptrTransform->SetRotation(Vec3(0)); ptrTransform->SetPosition(m_Position); //描画コンポーネントの追加(インスタンス描画) auto PtrDraw = AddComponent<PCTStaticInstanceDraw>(); PtrDraw->SetMeshResource(m_MeshRes); PtrDraw->SetTextureResource(L"SPARK_TX"); PtrDraw->SetDepthStencilState(DepthStencilState::Read); //各頂点ごとに行列を作成 for (auto& v : m_LocalDataVec) { Mat4x4 tempMat; tempMat.affineTransformation( Vec3(1.0f), Vec3(0.0f), Quat(), v.m_LocalPosition ); //インスタンス描画の行列として設定 PtrDraw->AddMatrix(tempMat); } SetAlphaActive(true); }
//球体を作成
MeshUtill::CreateSphere(1.0f, 28,vertices, indices);
for (auto& v : vertices) { LocalData tempLocalData; tempLocalData.m_LocalPosition = v.position; //各頂点をインスタンスの位置に設定 m_LocalDataVec.push_back(tempLocalData); }
struct LocalData { LocalState m_State; Vec3 m_LocalPosition; Mat4x4 m_FixedMatrix; Vec3 m_Velocity; LocalData() : m_State(LocalState::Roll), m_LocalPosition(0.0f), m_FixedMatrix(), m_Velocity(0.0f) {} };
enum class LocalState { Roll, Down, Fix };
//各頂点をインスタンスの位置に設定 m_LocalDataVec.push_back(tempLocalData);
//描画用メッシュの作成 float helfSize = 0.04f; Col4 col(1.0f, 1.0f, 0.0f, 1.0f); //頂点配列 vector<VertexPositionColorTexture> meshVertices = { { VertexPositionColorTexture(Vec3(-helfSize, helfSize, 0),col, Vec2(0.0f, 0.0f)) }, { VertexPositionColorTexture(Vec3(helfSize, helfSize, 0),col, Vec2(1.0f, 0.0f)) }, { VertexPositionColorTexture(Vec3(-helfSize, -helfSize, 0),col, Vec2(0.0f, 1.0f)) }, { VertexPositionColorTexture(Vec3(helfSize, -helfSize, 0),col, Vec2(1.0f, 1.0f)) }, }; //インデックス配列 vector<uint16_t> meshIndex = { 0, 1, 2, 1, 3, 2 }; //2次元平面とする(頂点数が少ないため) m_MeshRes = MeshResource::CreateMeshResource(meshVertices, meshIndex, true);
//全体の位置関連 auto ptrTransform = GetComponent<Transform>(); ptrTransform->SetScale(Vec3(m_Scale)); ptrTransform->SetRotation(Vec3(0)); ptrTransform->SetPosition(m_Position);
//描画コンポーネントの追加(インスタンス描画) auto PtrDraw = AddComponent<PCTStaticInstanceDraw>(); PtrDraw->SetMeshResource(m_MeshRes); PtrDraw->SetTextureResource(L"SPARK_TX"); PtrDraw->SetDepthStencilState(DepthStencilState::Read); //各頂点ごとに行列を作成 for (auto& v : m_LocalDataVec) { Mat4x4 tempMat; tempMat.affineTransformation( Vec3(1.0f), Vec3(0.0f), Quat(), v.m_LocalPosition ); //インスタンス描画の行列として設定 PtrDraw->AddMatrix(tempMat); } SetAlphaActive(true);
void PointsBall::OnUpdate() { //ステートのUpdate UpdateState(); //各インスタンスのUpdate UpdateInstances(); }
//ステートのUpdate void PointsBall::UpdateState() { if (m_MatVec.size() != m_LocalDataVec.size()) { //m_MatVecがまだ初期化されてない可能性がある return; } //各定数 const float baseY = m_Scale * 0.02f; const float velocityPower = 3.0f; const Vec3 gravity(0, -9.8f, 0); float elapsedTime = App::GetApp()->GetElapsedTime(); auto playerSh = GetStage()->GetSharedGameObject<Player>(L"Player"); auto playerPos = playerSh->GetComponent<Transform>()->GetWorldPosition(); //各頂点でループ for (size_t i = 0; i < m_LocalDataVec.size(); i++) { switch (m_LocalDataVec[i].m_State) { case LocalState::Roll: //回転している状態 { auto len = length(playerPos - m_MatVec[i].transInMatrix()); if (len < 0.4f) { //lenが0.4未満なら衝突してると判断 //ステートを変更 //衝突していたら球から飛び出すように速度を設定 m_LocalDataVec[i].m_State = LocalState::Down; m_LocalDataVec[i].m_Velocity = playerPos - m_MatVec[i].transInMatrix(); m_LocalDataVec[i].m_Velocity.normalize(); m_LocalDataVec[i].m_Velocity.y = 1.0f; m_LocalDataVec[i].m_Velocity *= velocityPower; } } break; case LocalState::Down: //落下中の状態 if (m_MatVec[i].transInMatrix().y <= baseY) { //落下終了 m_LocalDataVec[i].m_State = LocalState::Fix; //終了時の行列を保存 //Y値を0.1にする m_MatVec[i]._42 = baseY; //m_LocalDataVecとm_MatVecは各インスタンスは同じインデックスである m_LocalDataVec[i].m_FixedMatrix = m_MatVec[i]; } else { m_LocalDataVec[i].m_Velocity += gravity * elapsedTime; m_LocalDataVec[i].m_LocalPosition += m_LocalDataVec[i].m_Velocity * elapsedTime; } break; case LocalState::Fix: //落下終了の状態 break; } } }
//lenが0.4未満なら衝突してると判断
//ステートを変更
//衝突していたら球から飛び出すように速度を設定
m_LocalDataVec[i].m_State = LocalState::Down;
m_LocalDataVec[i].m_Velocity = playerPos - m_MatVec[i].transInMatrix();
m_LocalDataVec[i].m_Velocity.normalize();
m_LocalDataVec[i].m_Velocity.y = 1.0f;
m_LocalDataVec[i].m_Velocity *= velocityPower;
if (m_MatVec[i].transInMatrix().y <= baseY) {
//終了時の行列を保存 //Y値を0.1にする m_MatVec[i]._42 = baseY;
//m_LocalDataVecとm_MatVecは各インスタンスは同じインデックスである
m_LocalDataVec[i].m_FixedMatrix = m_MatVec[i];
void PointsBall::UpdateInstances() {
float elapsedTime = App::GetApp()->GetElapsedTime();
auto ptrDraw = GetComponent<PCTStaticInstanceDraw>();
auto camera = OnGetDrawCamera();
//カメラのレイを作成しておく
auto lay = camera->GetAt() - camera->GetEye();
lay.normalize();
Quat qtCamera;
//回転は常にカメラを向くようにする
qtCamera.facing(lay);
auto ptrTransform = GetComponent<Transform>();
//全体を回転させる
auto worldQt = ptrTransform->GetQuaternion();
Quat spanQt(Vec3(0, 1, 0), elapsedTime);
worldQt *= spanQt;
ptrTransform->SetQuaternion(worldQt);
//行列の配列をクリア
m_MatVec.clear();
Mat4x4 worldMat;
for (auto& v : m_LocalDataVec) {
if (v.m_State == LocalState::Fix) {
//落下終了の状態
worldMat.affineTransformation(
v.m_FixedMatrix.scaleInMatrix(),
Vec3(0.0f),
qtCamera,
v.m_FixedMatrix.transInMatrix()
);
}
else {
Mat4x4 localMat;
localMat.affineTransformation(
Vec3(1.0f),
Vec3(0.0f),
Quat(),
v.m_LocalPosition
);
worldMat = localMat * ptrTransform->GetWorldMatrix();
worldMat.affineTransformation(
worldMat.scaleInMatrix(),
Vec3(0.0f),
qtCamera,
worldMat.transInMatrix()
);
}
m_MatVec.push_back(worldMat);
}
//インスタンス行列の更新
ptrDraw->UpdateMultiMatrix(m_MatVec);
}
if (v.m_State == LocalState::Fix) {
worldMat.affineTransformation( v.m_FixedMatrix.scaleInMatrix(), Vec3(0.0f), qtCamera, v.m_FixedMatrix.transInMatrix() );
worldMat = localMat * ptrTransform->GetWorldMatrix(); worldMat.affineTransformation( worldMat.scaleInMatrix(), Vec3(0.0f), qtCamera, worldMat.transInMatrix() );
m_MatVec.push_back(worldMat);
//インスタンス行列の更新 ptrDraw->UpdateMultiMatrix(m_MatVec);