Mat4x4が適用されたBoxの座標の取得
Siv3D勉強中の学生 2024/10/22(Tue) 02:23
ルービックキューブのアニメーションを作成するために、27個のBoxと54枚のPlaneの使用を考えています。
Boxでキューブの内部を、Planeで表面の色を表現します。
回転の描画を行うため、特定の条件(例えば、x > 0)を満たすBoxとPlaneだけを回転させたいと考えています。そのために、各Boxの3次元座標を取得する方法を教えてください また、より良い書き方があれば教えてください。
以下は、現在書いてるコードの概要です。簡略化のため、Planeは除いています。ここでの「R回転」は、キューブの右側の回転を意味します。
#include <Siv3D.hpp>
void Main()
{
// 背景色の設定
const ColorF bgColor = ColorF{0.1, 0.15, 0.2}.removeSRGBCurve();
const MSRenderTexture renderTexture{Scene::Size(), TextureFormat::R8G8B8A8_Unorm_SRGB, HasDepth::Yes};
Graphics3D::SetGlobalAmbientColor(ColorF{0.6, 0.65, 0.7});
BasicCamera3D camera{renderTexture.size(), 30_deg};
const int boxCount = 27;
double boxSize = 10;
bool isRightRotating = false;
double rotatedAngle = 0.0; // 現在の回転角度を保持
double targetAngle = 0.0; // 目標の回転角度を保持
Vec3 middlePosition = {0, boxSize, 0}; // 上段真ん中の座標
Array<Vec3> boxPosition{}; // 各Boxの3D位置を保持
// boxPositionの初期化
for (int i : step(3))
{
boxPosition.push_back(middlePosition);
for (int k : step(8))
{
double x = middlePosition.x + boxSize * Round(Cos(Math::Pi / 4 * k));
double z = middlePosition.z + boxSize * Round(Sin(Math::Pi / 4 * k));
boxPosition.push_back(Vec3(x, middlePosition.y, z));
}
middlePosition.y -= 10;
}
// Boxの数だけMat4x4を用意
std::array<Mat4x4, boxCount> boxMat{};
for (int i : step(boxCount))
{
boxMat[i] = Mat4x4::Translate(boxPosition[i]); // 各Boxの初期位置に基づいて変換行列を作成
}
while (System::Update())
{
camera.setView(Vec3{50, 50, 50}, Vec3{});
Graphics3D::SetCameraTransform(camera);
const ScopedRenderTarget3D target{renderTexture.clear(bgColor)};
{
// R回転中であれば回転処理を行う
if (isRightRotating)
{
rotatedAngle += 1_deg; // 徐々に回転角度を増加させる
// Z > 0 の位置にあるBoxに対して変換行列を更新
for (int i : step(boxCount))
{
// BoxのZ座標が0より大きいか確認
if (/*ここでBoxの座標を取得したい*/)
{
boxMat[i] *= Mat4x4::RotateZ(1_deg); // Z軸周りに回転
}
}
// 現在の回転角度が目標の回転角度を超えた場合
if (rotatedAngle >= targetAngle)
{
isRightRotating = false; // 回転を停止
}
}
// Boxの表示
for (int i : step(boxCount))
{
Box(10).draw(boxMat[i], Palette::White); // 各Boxを描画
}
// 3D シーンを 2D シーンに描画
{
Graphics3D::Flush();
renderTexture.resolve();
Shader::LinearToScreen(renderTexture);
}
if (SimpleGUI::Button(U"R", Vec2{10, 130}))
{
isRightRotating = true; // Rボタンが押されたら回転を開始
targetAngle = rotatedAngle + 90; // 新しい目標角度を設定
}
}
}
}
よろしくお願いします。
Reputeless 2024/10/23(Wed) 11:47
効率的かはわかりませんが、私だったらこう実装するかもというのを書きました。
https://gist.github.com/Reputeless/fab9050e7b2abd40f363952f3e6944cd
疑問点や、さらに追加でリクエストがあればコメントしてください。
Siv3D勉強中の学生 2024/10/24(Thu) 02:40
Reputeless 2024/10/29(Tue) 16:07
次のように Mat4x4::transformPoint() で Vec3 を変換します。
https://gist.github.com/Reputeless/ff225a23187ffd6f2e998d98627185d5