You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
8.4 KiB
251 lines
8.4 KiB
/*
|
|
* Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* SPDX-FileCopyrightText: Copyright (c) 2018-2021 NVIDIA CORPORATION
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
//--------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#pragma warning(disable : 4201)
|
|
#include <array>
|
|
#include <nvmath/nvmath.h>
|
|
#include <string>
|
|
|
|
namespace nvh {
|
|
/**
|
|
\class nvh::CameraManipulator
|
|
|
|
nvh::CameraManipulator is a camera manipulator help class
|
|
It allow to simply do
|
|
- Orbit (LMB)
|
|
- Pan (LMB + CTRL | MMB)
|
|
- Dolly (LMB + SHIFT | RMB)
|
|
- Look Around (LMB + ALT | LMB + CTRL + SHIFT)
|
|
|
|
In a various ways:
|
|
- examiner(orbit around object)
|
|
- walk (look up or down but stays on a plane)
|
|
- fly ( go toward the interest point)
|
|
|
|
Do use the camera manipulator, you need to do the following
|
|
- Call setWindowSize() at creation of the application and when the window size change
|
|
- Call setLookat() at creation to initialize the camera look position
|
|
- Call setMousePosition() on application mouse down
|
|
- Call mouseMove() on application mouse move
|
|
|
|
Retrieve the camera matrix by calling getMatrix()
|
|
|
|
See: appbase_vkpp.hpp
|
|
|
|
Note: There is a singleton `CameraManip` which can be use across the entire application
|
|
|
|
\code{.cpp}
|
|
// Retrieve/set camera information
|
|
CameraManip.getLookat(eye, center, up);
|
|
CameraManip.setLookat(eye, center, nvmath::vec3f(m_upVector == 0, m_upVector == 1, m_upVector == 2));
|
|
CameraManip.getFov();
|
|
CameraManip.setSpeed(navSpeed);
|
|
CameraManip.setMode(navMode == 0 ? nvh::CameraManipulator::Examine : nvh::CameraManipulator::Fly);
|
|
// On mouse down, keep mouse coordinates
|
|
CameraManip.setMousePosition(x, y);
|
|
// On mouse move and mouse button down
|
|
if(m_inputs.lmb || m_inputs.rmb || m_inputs.mmb)
|
|
{
|
|
CameraManip.mouseMove(x, y, m_inputs);
|
|
}
|
|
// Wheel changes the FOV
|
|
CameraManip.wheel(delta > 0 ? 1 : -1, m_inputs);
|
|
// Retrieve the matrix to push to the shader
|
|
m_ubo.view = CameraManip.getMatrix();
|
|
\endcode
|
|
|
|
*/
|
|
|
|
class CameraManipulator
|
|
{
|
|
public:
|
|
// clang-format off
|
|
enum Modes { Examine, Fly, Walk};
|
|
enum Actions { NoAction, Orbit, Dolly, Pan, LookAround };
|
|
struct Inputs {bool lmb=false; bool mmb=false; bool rmb=false;
|
|
bool shift=false; bool ctrl=false; bool alt=false;};
|
|
// clang-format on
|
|
|
|
struct Camera
|
|
{
|
|
nvmath::vec3f eye = nvmath::vec3f(10, 10, 10);
|
|
nvmath::vec3f ctr = nvmath::vec3f(0, 0, 0);
|
|
nvmath::vec3f up = nvmath::vec3f(0, 1, 0);
|
|
float fov = 60.0f;
|
|
|
|
bool operator!=(const Camera& rhr) const
|
|
{
|
|
return (eye != rhr.eye) || (ctr != rhr.ctr) || (up != rhr.up) || (fov != rhr.fov);
|
|
}
|
|
bool operator==(const Camera& rhr) const
|
|
{
|
|
return (eye == rhr.eye) && (ctr == rhr.ctr) && (up == rhr.up) && (fov == rhr.fov);
|
|
}
|
|
};
|
|
|
|
public:
|
|
// Main function to call from the application
|
|
// On application mouse move, call this function with the current mouse position, mouse
|
|
// button presses and keyboard modifier. The camera matrix will be updated and
|
|
// can be retrieved calling getMatrix
|
|
Actions mouseMove(int x, int y, const Inputs& inputs);
|
|
|
|
// Set the camera to look at the interest point
|
|
// instantSet = true will not interpolate to the new position
|
|
void setLookat(const nvmath::vec3f& eye, const nvmath::vec3f& center, const nvmath::vec3f& up, bool instantSet = true);
|
|
|
|
// This should be called in an application loop to update the camera matrix if this one is animated: new position, key movement
|
|
void updateAnim();
|
|
|
|
// To call when the size of the window change. This allows to do nicer movement according to the window size.
|
|
void setWindowSize(int w, int h);
|
|
|
|
// Setting the current mouse position, to call on mouse button down. Allow to compute properly the deltas
|
|
void setMousePosition(int x, int y);
|
|
|
|
Camera getCamera() const { return m_current; }
|
|
void setCamera(Camera camera, bool instantSet = true);
|
|
|
|
// Retrieve the position, interest and up vector of the camera
|
|
void getLookat(nvmath::vec3f& eye, nvmath::vec3f& center, nvmath::vec3f& up) const;
|
|
nvmath::vec3f getEye() const { return m_current.eye; }
|
|
nvmath::vec3f getCenter() const { return m_current.ctr; }
|
|
nvmath::vec3f getUp() const { return m_current.up; }
|
|
|
|
// Set the manipulator mode, from Examiner, to walk, to fly, ...
|
|
void setMode(Modes mode) { m_mode = mode; }
|
|
|
|
// Retrieve the current manipulator mode
|
|
Modes getMode() const { return m_mode; }
|
|
|
|
// Retrieving the transformation matrix of the camera
|
|
const nvmath::mat4f& getMatrix() const { return m_matrix; }
|
|
|
|
// Set the position, interest from the matrix.
|
|
// instantSet = true will not interpolate to the new position
|
|
// centerDistance is the distance of the center from the eye
|
|
void setMatrix(const nvmath::mat4f& mat_, bool instantSet = true, float centerDistance = 1.f);
|
|
|
|
// Changing the default speed movement
|
|
void setSpeed(float speed) { m_speed = speed; }
|
|
|
|
// Retrieving the current speed
|
|
float getSpeed() { return m_speed; }
|
|
|
|
// Retrieving the last mouse position
|
|
void getMousePosition(int& x, int& y);
|
|
|
|
// Main function which is called to apply a camera motion.
|
|
// It is preferable to
|
|
void motion(int x, int y, int action = 0);
|
|
|
|
void keyMotion(float dx, float dy, int action);
|
|
|
|
// To call when the mouse wheel change
|
|
void wheel(int value, const Inputs& inputs);
|
|
|
|
// Retrieve the screen dimension
|
|
int getWidth() const { return m_width; }
|
|
int getHeight() const { return m_height; }
|
|
|
|
// Field of view
|
|
void setFov(float _fov);
|
|
float getFov() { return m_current.fov; }
|
|
|
|
void setClipPlanes(nvmath::vec2f clip) { m_clipPlanes = clip; }
|
|
const nvmath::vec2f& getClipPlanes() const { return m_clipPlanes; }
|
|
|
|
|
|
// Animation duration
|
|
double getAnimationDuration() const { return m_duration; }
|
|
void setAnimationDuration(double val) { m_duration = val; }
|
|
bool isAnimated() { return m_anim_done == false; }
|
|
|
|
// Returning a default help string
|
|
const std::string& getHelp();
|
|
|
|
// Fitting the camera position and interest to see the bounding box
|
|
void fit(const nvmath::vec3f& boxMin, const nvmath::vec3f& boxMax, bool instantFit = true, bool tight = false, float aspect = 1.0f);
|
|
|
|
protected:
|
|
CameraManipulator();
|
|
|
|
private:
|
|
// Update the internal matrix.
|
|
void update() { m_matrix = nvmath::look_at(m_current.eye, m_current.ctr, m_current.up); }
|
|
|
|
// Do panning: movement parallels to the screen
|
|
void pan(float dx, float dy);
|
|
// Do orbiting: rotation around the center of interest. If invert, the interest orbit around the camera position
|
|
void orbit(float dx, float dy, bool invert = false);
|
|
// Do dolly: movement toward the interest.
|
|
void dolly(float dx, float dy);
|
|
|
|
|
|
double getSystemTime();
|
|
|
|
nvmath::vec3f computeBezier(float t, nvmath::vec3f& p0, nvmath::vec3f& p1, nvmath::vec3f& p2);
|
|
void findBezierPoints();
|
|
|
|
protected:
|
|
nvmath::mat4f m_matrix = nvmath::mat4f(1);
|
|
|
|
Camera m_current; // Current camera position
|
|
Camera m_goal; // Wish camera position
|
|
Camera m_snapshot; // Current camera the moment a set look-at is done
|
|
|
|
// Animation
|
|
std::array<nvmath::vec3f, 3> m_bezier;
|
|
double m_start_time = 0;
|
|
double m_duration = 0.5;
|
|
bool m_anim_done{true};
|
|
nvmath::vec3f m_key_vec{0, 0, 0};
|
|
|
|
// Screen
|
|
int m_width = 1;
|
|
int m_height = 1;
|
|
|
|
// Other
|
|
float m_speed = 3.f;
|
|
nvmath::vec2f m_mouse = nvmath::vec2f(0.f, 0.f);
|
|
nvmath::vec2f m_clipPlanes = nvmath::vec2f(0.001f, 100000000.f);
|
|
|
|
bool m_button = false; // Button pressed
|
|
bool m_moving = false; // Mouse is moving
|
|
float m_tbsize = 0.8f; // Trackball size;
|
|
|
|
Modes m_mode = Examine;
|
|
|
|
public:
|
|
// Factory.
|
|
static CameraManipulator& Singleton()
|
|
{
|
|
static CameraManipulator manipulator;
|
|
return manipulator;
|
|
}
|
|
};
|
|
|
|
// Global Manipulator
|
|
|
|
} // namespace nvh
|
|
|
|
#define CameraManip nvh::CameraManipulator::Singleton()
|
|
|