Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera Controller: expose complete API to python #418

Merged
merged 7 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 2 additions & 18 deletions cpp/modmesh/view/R3DWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ R3DWidget::R3DWidget(Qt3DExtras::Qt3DWindow * window, RScene * scene, QWidget *
{
m_view->setRootEntity(m_scene);

resetCamera();
cameraController()->setCamera(m_view->camera());
cameraController()->reset();

if (Toggle::instance().fixed().get_show_axis())
{
Expand Down Expand Up @@ -99,23 +100,6 @@ void R3DWidget::resizeEvent(QResizeEvent * event)
m_container->resize(event->size());
}

void R3DWidget::resetCamera() const
{
Qt3DRender::QCamera * camera = m_view->camera();

// Set up the camera.
camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(0.0f, 0.0f, 10.0f));
camera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));
camera->setUpVector(QVector3D(0.f, 1.f, 0.f));

// Set up the camera control.
auto * control = m_scene->controller();
control->setCamera(camera);
control->setLinearSpeed(50.0f);
control->setLookSpeed(180.0f);
}

Comment on lines -102 to -118
Copy link
Contributor Author

@Tucchhaa Tucchhaa Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resetCamera moved to CameraController

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving it to CameraController makes it more testable. I like it.

} /* end namespace modmesh */

// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4:
18 changes: 7 additions & 11 deletions cpp/modmesh/view/R3DWidget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,17 @@ namespace modmesh
class RScene
: public Qt3DCore::QEntity
{

public:

explicit RScene(Qt3DCore::QNode * parent = nullptr)
: Qt3DCore::QEntity(parent)
, m_controller(new ROrbitCameraController(this))
explicit RScene(QNode * parent = nullptr)
: QEntity(parent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to separate the CameraController from the scene.

{
m_controller = new ROrbitCameraController(this);
}

Qt3DExtras::QAbstractCameraController const * controller() const { return m_controller; }
Qt3DExtras::QAbstractCameraController * controller() { return m_controller; }
RCameraController * controller() const { return m_controller; }

void setCameraController(Qt3DExtras::QAbstractCameraController * controller)
void setCameraController(RCameraController * controller)
{
m_controller->deleteLater();
m_controller = controller;
Expand All @@ -73,7 +71,7 @@ class RScene

private:

Qt3DExtras::QAbstractCameraController * m_controller = nullptr;
RCameraController * m_controller;

}; /* end class RScene */

Expand All @@ -97,10 +95,8 @@ class R3DWidget
Qt3DExtras::Qt3DWindow * view() { return m_view; }
RScene * scene() { return m_scene; }
Qt3DRender::QCamera * camera() { return m_view->camera(); }
Qt3DExtras::QAbstractCameraController * qtCameraController() { return m_scene->controller(); }
CameraController * cameraController() { return dynamic_cast<CameraController *>(m_scene->controller()); }

void resetCamera() const;
RCameraController * cameraController() const { return m_scene->controller(); }

QPixmap grabPixmap() const { return m_view->screen()->grabWindow(m_view->winId()); }

Expand Down
31 changes: 24 additions & 7 deletions cpp/modmesh/view/RCameraController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,18 +212,33 @@ void RCameraInputListener::initKeyboardListeners() const
m_ty_axis->addInput(m_keyboard_ty_neg_input);
}

void RCameraController::reset()
{
constexpr float fov_deg = 45.0f;
constexpr float nearPlane = 0.1f;
constexpr float farPlane = 1000.0f;
camera()->lens()->setPerspectiveProjection(fov_deg, camera()->lens()->aspectRatio(), nearPlane, farPlane);

setPosition(m_default_position);
setViewCenter(m_default_view_center);
setUpVector(m_default_up_vector);

setLinearSpeed(m_default_linear_speed);
setLookSpeed(m_default_look_speed);
}

RFirstPersonCameraController::RFirstPersonCameraController(QNode * parent)
: QFirstPersonCameraController(parent)
: RCameraController(parent)
{
auto callback = [this](const CameraInputState & state, const float dt)
{
updateCameraPosition(state, dt);
moveCamera(state, dt);
};

m_listener = new RCameraInputListener(keyboardDevice(), mouseDevice(), callback, this);
}

void RFirstPersonCameraController::updateCameraPosition(const CameraInputState & input, const float dt)
void RFirstPersonCameraController::moveCamera(const CameraInputState & input, const float dt)
{
constexpr auto positiveY = QVector3D(0.f, 1.f, 0.f);

Expand All @@ -244,17 +259,17 @@ void RFirstPersonCameraController::updateCameraPosition(const CameraInputState &
}

ROrbitCameraController::ROrbitCameraController(QNode * parent)
: QOrbitCameraController(parent)
: RCameraController(parent)
{
auto callback = [this](const CameraInputState & state, const float dt)
{
updateCameraPosition(state, dt);
moveCamera(state, dt);
};

m_listener = new RCameraInputListener(keyboardDevice(), mouseDevice(), callback, this);
}

void ROrbitCameraController::updateCameraPosition(const CameraInputState & input, const float dt)
void ROrbitCameraController::moveCamera(const CameraInputState & input, const float dt)
{
if (camera() == nullptr)
return;
Expand Down Expand Up @@ -305,7 +320,9 @@ void ROrbitCameraController::updateCameraPosition(const CameraInputState & input

void ROrbitCameraController::zoom(const float zoomValue) const
{
const float limitSquared = zoomInLimit() * zoomInLimit();
constexpr float zoomInLimit = 2.0f; // Default Qt zoomInLimit value

const float limitSquared = zoomInLimit * zoomInLimit;
const float distanceSquared = zoomDistanceSquared(camera()->position(), camera()->viewCenter());

const float z = distanceSquared > limitSquared ? zoomValue : -0.5f;
Expand Down
88 changes: 53 additions & 35 deletions cpp/modmesh/view/RCameraController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@
*/

#include <modmesh/view/common_detail.hpp> // Must be the first include.

#include <QOrbitCameraController>
#include <QFirstPersonCameraController>
#include <QCamera>
#include <QAbstractCameraController>

#include <Qt3DLogic/QFrameAction>
#include <Qt3DInput/QActionInput>
Expand Down Expand Up @@ -128,77 +126,97 @@ class RCameraInputListener : public Qt3DCore::QEntity
Qt3DInput::QButtonAxisInput * m_keyboard_tz_neg_input;
}; /* end class RCameraInputListener */

class CameraController
class RCameraController : public Qt3DExtras::QAbstractCameraController
{
Q_OBJECT

public:
virtual ~CameraController() = default;
explicit RCameraController(Qt3DCore::QNode * parent = nullptr)
: QAbstractCameraController(parent)
{
}

virtual void updateCameraPosition(const CameraInputState & state, float dt) = 0;
void moveCamera(const InputState & state, float dt) override
{
// Do nothing in QAbstractCameraController's moveCamera
}

virtual void moveCamera(const CameraInputState & state, float dt) = 0;

virtual Qt3DRender::QCamera * getCamera() = 0;
Qt3DRender::QCamera * camera() const { return QAbstractCameraController::camera(); }
void setCamera(Qt3DRender::QCamera * camera) { QAbstractCameraController::setCamera(camera); }

virtual float getLinearSpeed() = 0;
float linearSpeed() const { return QAbstractCameraController::linearSpeed(); }
void setLinearSpeed(float value) { QAbstractCameraController::setLinearSpeed(value); }

virtual float getLookSpeed() = 0;
float lookSpeed() const { return QAbstractCameraController::lookSpeed(); }
void setLookSpeed(float value) { QAbstractCameraController::setLookSpeed(value); }

virtual CameraControllerType getType() = 0;

QVector3D position() { return getCamera()->position(); }
QVector3D position() const { return camera()->position(); }
void setPosition(const QVector3D & value) const { camera()->setPosition(value); }

QVector3D viewVector() const { return camera()->viewVector(); }

QVector3D viewCenter() const { return camera()->viewCenter(); }
void setViewCenter(const QVector3D & value) const { camera()->setViewCenter(value); }

QVector3D viewVector() { return getCamera()->viewVector(); }
QVector3D upVector() const { return camera()->upVector(); }
void setUpVector(const QVector3D & value) const { camera()->setUpVector(value); }

QVector3D viewCenter() { return getCamera()->viewCenter(); }
void reset();

QVector3D upVector() { return getCamera()->upVector(); }
QVector3D defaultPosition() const { return m_default_position; }
void setDefaultPosition(QVector3D value) { m_default_position = value; }

QVector3D defaultViewCenter() const { return m_default_view_center; }
void setDefaultViewCenter(QVector3D value) { m_default_view_center = value; }

QVector3D defaultUpVector() const { return m_default_up_vector; }
void setDefaultUpVector(QVector3D value) { m_default_up_vector = value; }

float defaultLinearSpeed() const { return m_default_linear_speed; }
void setDefaultLinearSpeed(float value) { m_default_linear_speed = value; }

float defaultLookSpeed() const { return m_default_look_speed; }
void setDefaultLookSpeed(float value) { m_default_look_speed = value; }
Comment on lines +170 to +183
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new props in CameraController to control reset behaviour


protected:
RCameraInputListener * m_listener = nullptr;

private:
Qt3DExtras::QAbstractCameraController * asQtCameraController()
{
return dynamic_cast<Qt3DExtras::QAbstractCameraController *>(this);
}
QVector3D m_default_position = QVector3D(0.0f, 0.0f, 10.0f);
Copy link
Collaborator

@tigercosmos tigercosmos Aug 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why (0, 0, 10)?

Copy link
Contributor Author

@Tucchhaa Tucchhaa Aug 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because meshes are placed at (0, 0, 0), and we don't want the camera to be inside the mesh

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can guess that, but my point is, better to have some comments for it.

Copy link
Member

@yungyuc yungyuc Aug 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because meshes are placed at (0, 0, 0), and we don't want the camera to be inside the mesh

To put the camera outside the mesh, it is not good to hard-code the default value of the member m_default_position, because the mesh may be placed anywhere.

We do not have a reasonably large number of mesh examples for the default location to show disadvantage.

I can guess that, but my point is, better to have some comments for it.

I concur, but it's OK to leave it here and deal with it in the future. As we make the code more useful, some meshes will cover the position sooner or later. We will immediately know and fix it.

QVector3D m_default_view_center = QVector3D(0.0f, 0.0f, 0.0f);
QVector3D m_default_up_vector = QVector3D(0.0f, 1.0f, 0.0f);
float m_default_linear_speed = 50.0f;
float m_default_look_speed = 180.0f;
}; /* end class CameraController */

class RFirstPersonCameraController : public Qt3DExtras::QFirstPersonCameraController
, public CameraController
class RFirstPersonCameraController : public RCameraController
{
Q_OBJECT

public:
explicit RFirstPersonCameraController(QNode * parent = nullptr);

Qt3DRender::QCamera * getCamera() override { return camera(); }
float getLinearSpeed() override { return linearSpeed(); }
float getLookSpeed() override { return lookSpeed(); }

private:
static constexpr auto lookSpeedFactorOnShiftPressed = 0.2f;

void moveCamera(const InputState & state, float dt) override {}

void updateCameraPosition(const CameraInputState & input, float dt) override;
void moveCamera(const CameraInputState & input, float dt) override;

CameraControllerType getType() override { return CameraControllerType::FirstPerson; }
}; /* end class RFirstPersonCameraController */

class ROrbitCameraController : public Qt3DExtras::QOrbitCameraController
, public CameraController
class ROrbitCameraController : public RCameraController
{
Q_OBJECT

public:
explicit ROrbitCameraController(QNode * parent = nullptr);

Qt3DRender::QCamera * getCamera() override { return camera(); }
float getLinearSpeed() override { return linearSpeed(); }
float getLookSpeed() override { return lookSpeed(); }

private:
void moveCamera(const InputState & state, float dt) override {}

void updateCameraPosition(const CameraInputState & input, float dt) override;
void moveCamera(const CameraInputState & input, float dt) override;

void zoom(float zoomValue) const;

Expand Down
4 changes: 2 additions & 2 deletions cpp/modmesh/view/RManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ void RManager::setUpCameraMovementMenuItems() const
if (viewer == nullptr || viewer->camera() == nullptr)
return;

viewer->resetCamera();
viewer->cameraController()->reset();
});

auto * move_camera_up = new RAction(
Expand Down Expand Up @@ -379,7 +379,7 @@ std::function<void()> RManager::createCameraMovementItemHandler(const std::funct
}
}

viewer->cameraController()->updateCameraPosition(input, 0.01);
viewer->cameraController()->moveCamera(input, 0.01);
};
}

Expand Down
Loading
Loading