3Dグラフィックの回転
Siv3D初心者 2017/11/04(Sat) 17:29
Siv3D入門者です。
http://gologius.hatenadiary.com/entry/2015/06/28/175706
上記のサイトを参考に、マウスを使ってカメラの回転の実装をしています。
ところがURL先と同じく、回転途中に急な不連続性が生じてしまい正しい動作をしません。
自分でも試行錯誤しましたが、どのようにしたらカメラが正常な動作をするのか、未だにわからず困っています。
よろしければご助言頂ければと思います。
どうぞよろしくお願いします。
Reputeless 2017/11/07(Tue) 20:12
以下のプログラムが参考になると思います。
# include <Siv3D.hpp>
Vec2 GetBorder(const Vec2& start, const Vec2& direction, const Sphere& sphere)
{
double min = 0.0, max = 2048.0;
Vec2 pos(0, 0);
while ((max - min) >= 0.001)
{
const double mid = (min + max) / 2;
pos = start + direction * mid;
if (Graphics3D::ToRay(pos).intersectsAt(sphere))
{
min = mid;
}
else
{
max = mid;
}
}
return start + direction * min;
}
void Main()
{
Window::Resize(1280, 720);
Graphics::SetBackground(Color(120, 200, 150));
Graphics3D::SetAmbientLight(ColorF(0.3));
Graphics3D::SetCamera(Camera(Vec3(0, 12, -24), Vec3(0, 0, 0), Vec3::Up, 45, 1));
const Vec3 center(5, -2, 0);
const Sphere earthSphere(6);
const Sphere rotationSphere(center, earthSphere.r * Sqrt(3));
const Texture texture(L"Example/Earth.jpg", TextureDesc::For3D);
const Array<Point> pairs =
{
{ 0,1 },{ 1,3 },{ 3,2 },{ 2,0 },
{ 0,4 },{ 1,5 },{ 3,7 },{ 2,6 },
{ 4,5 },{ 5,7 },{ 7,6 },{ 6,4 },
};
Quaternion rotation, rotation2;
Optional<Point> grabbed;
Vec3 from(0, 0, 0), to(0, 0, 0);
while (System::Update())
{
const auto onRotationSphere = Mouse::Ray().intersectsAt(rotationSphere);
Cursor::SetStyle(onRotationSphere ? CursorStyle::Hand : CursorStyle::Default);
if (onRotationSphere && Input::MouseL.clicked)
{
grabbed = Mouse::Pos();
from = to = onRotationSphere.value();
}
if (grabbed)
{
if (onRotationSphere)
{
to = onRotationSphere.value();
rotation2 = Quaternion::RotationArc(from.normalized(), to.normalized());
}
else if (Mouse::Pos() != grabbed)
{
const Vec2 pos = GetBorder(grabbed.value(), Vec2(Mouse::Pos() - grabbed.value()).normalized(), rotationSphere);
const double s = Mouse::Pos().distanceFrom(grabbed.value()) / grabbed->distanceFrom(pos);
to = Graphics3D::ToRay(pos).intersectsAt(rotationSphere).value();
rotation2 = Slerp(Quaternion::Identity(), Quaternion::RotationArc(from.normalized(), to.normalized()), s);
}
}
if (Input::MouseL.released)
{
grabbed = none;
rotation *= rotation2;
rotation2 = Quaternion::Identity();
}
const Quaternion rot = rotation * rotation2;
earthSphere.asMesh().rotated(rot).translated(center).draw(texture);
const Array<Vec3> pts =
{
rot * Vec3(-6, 6, 6), rot * Vec3(6, 6, 6),
rot * Vec3(-6, 6, -6), rot * Vec3(6, 6, -6),
rot * Vec3(-6, -6, 6), rot * Vec3(6, -6, 6),
rot * Vec3(-6, -6, -6), rot * Vec3(6, -6, -6),
};
for (const auto& pair : pairs)
{
Line3D(pts[pair.x], pts[pair.y]).movedBy(center).drawForward();
}
Graphics3D::SetRasterizerStateForward(RasterizerState::WireframeCullBack);
rotationSphere.drawForward();
Graphics3D::SetRasterizerStateForward(RasterizerState::Default3D);
}
}
Siv3D初心者 2017/11/14(Tue) 22:41
お礼が遅くなりすみませんでした。
ありがとうございます。思い通りの挙動をしてくれます。
勉強させていただきます。
ポン太郎 2017/11/16(Thu) 13:46
上記について質問させてください。
私も同じことで苦戦しています。
Reputelessさんのサンプルコードと同じ動作をして、
オブジェクトを回転させるのではなく、カメラのみを回転させるるにはどうすればよろしいでしょうか。
よろしくお願いします。
ポン太郎 2017/11/23(Thu) 12:31
「カメラを動かした3Dグラフィックの回転」というスレッドを作って書き込ませてもらいました。
困っているので、どなたかお力をお貸しください。
よろしくお願いします!