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グラフィックの回転」というスレッドを作って書き込ませてもらいました。
困っているので、どなたかお力をお貸しください。
よろしくお願いします!

- WEB PATIO -