Smooth camera movement

This commit is contained in:
Flakebi
2014-11-18 11:54:52 +01:00
parent 497fa10695
commit 3e53787598
4 changed files with 218 additions and 49 deletions

View File

@@ -49,6 +49,7 @@ Camera* Camera::s_active_camera = NULL;
// ============================================================================
Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
{
m_smooth = false;
m_mode = CM_NORMAL;
m_index = camera_index;
m_original_kart = kart;
@@ -86,7 +87,12 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
m_rotation_range = 0.4f;
m_rotation_range = 0.0f;
m_lin_velocity = core::vector3df(0, 0, 0);
m_target_velocity = core::vector3df(0, 0, 0);
m_target_direction = core::vector3df(0, 0, 1);
m_target_up_vector = core::vector3df(0, 1, 0);
m_angular_velocity = 0;
m_target_angular_velocity = 0;
m_max_velocity = 15;
reset();
} // Camera
@@ -484,31 +490,80 @@ void Camera::update(float dt)
}
else if (UserConfigParams::m_camera_debug == 3)
{
// Compute direction
core::vector3df direction(m_camera->getTarget() - m_camera->getPosition());
core::vector3df up(m_camera->getUpVector());
// There may be a more elegant way instead of converting
core::vector3df side(Vec3(Vec3(direction).cross(Vec3(up))).toIrrVector());
core::vector3df side(direction.crossProduct(up));
// Update smooth movement
if (m_smooth)
{
// Angular velocity
if (m_angular_velocity < m_target_angular_velocity)
{
m_angular_velocity += 0.02f;
if (m_angular_velocity > m_target_angular_velocity)
m_angular_velocity = m_target_angular_velocity;
}
else if (m_angular_velocity > m_target_angular_velocity)
{
m_angular_velocity -= 0.02f;
if (m_angular_velocity < m_target_angular_velocity)
m_angular_velocity = m_target_angular_velocity;
}
// Linear velocity
core::vector3df diff(m_target_velocity - m_lin_velocity);
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
{
if (diff.getLengthSQ() > 1)
diff.setLength(1);
m_lin_velocity += diff;
}
// Camera direction
diff = m_target_direction - direction;
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
{
if (diff.getLengthSQ() > 0.02f * 0.02f)
diff.setLength(0.02f);
direction += diff;
}
// Camera rotation
diff = m_target_up_vector - up;
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
{
if (diff.getLengthSQ() > 0.02f * 0.02f)
diff.setLength(0.02f);
up += diff;
}
}
else
{
direction = m_target_direction;
up = m_target_up_vector;
side = direction.crossProduct(up);
}
// Rotate camera
core::quaternion quat;
quat.fromAngleAxis(m_angular_velocity * dt, direction);
up = quat * up;
m_target_up_vector = quat * up;
direction.normalize();
up.normalize();
side.normalize();
core::vector3df movement(direction * m_lin_velocity.Z +
up * m_lin_velocity.Y +
side * m_lin_velocity.X);
// Move camera
core::vector3df movement(direction * m_lin_velocity.Z +
up * m_lin_velocity.Y + side * m_lin_velocity.X);
core::vector3df pos = m_camera->getPosition();
pos = pos + movement * dt;
m_camera->setPosition(pos);
pos = m_camera->getTarget();
pos = pos + movement * dt;
m_camera->setTarget(pos);
// Rotate camera
btQuaternion quat(Vec3(direction), m_angular_velocity * dt);
btTransform trans(quat);
m_camera->setUpVector(Vec3(trans(Vec3(up))).toIrrVector());
// Set camera attributes
m_camera->setPosition(pos);
m_camera->setTarget(pos + direction);
m_camera->setUpVector(up);
}
else if (m_mode==CM_FINAL)
{
@@ -682,3 +737,42 @@ void Camera::activate()
} // activate
// ----------------------------------------------------------------------------
/** Sets the angular velocity for this camera. */
void Camera::setAngularVelocity(float vel)
{
if (m_smooth)
m_target_angular_velocity = vel;
else
m_angular_velocity = vel;
} // setAngularVelocity
// ----------------------------------------------------------------------------
/** Returns the current target angular velocity. */
float Camera::getAngularVelocity()
{
if (m_smooth)
return m_target_angular_velocity;
else
return m_angular_velocity;
} // getAngularVelocity
// ----------------------------------------------------------------------------
/** Sets the linear velocity for this camera. */
void Camera::setLinearVelocity(core::vector3df vel)
{
if (m_smooth)
m_target_velocity = vel;
else
m_lin_velocity = vel;
} // setLinearVelocity
// ----------------------------------------------------------------------------
/** Returns the current linear velocity. */
const core::vector3df &Camera::getLinearVelocity()
{
if (m_smooth)
return m_target_velocity;
else
return m_lin_velocity;
} // getLinearVelocity

View File

@@ -110,16 +110,31 @@ private:
/** Aspect ratio for camera. */
float m_aspect;
/** Smooth acceleration with the first person camera. */
bool m_smooth;
/** The speed at which the up-vector rotates, only used for the first person camera. */
float m_angular_velocity;
/** Target angular velocity. Used for smooth movement in fps perpective. */
float m_target_angular_velocity;
/** Maximum velocity for fps camera. */
float m_max_velocity;
/** Linear velocity of the camera, used for end and first person camera.
It's stored relative to the camera direction for the first person view. */
core::vector3df m_lin_velocity;
/** Velocity of the target of the camera, only used for end camera. */
/** Velocity of the target of the camera, used for end and first person camera. */
core::vector3df m_target_velocity;
/** The target direction for the camera, only used for the first person camera. */
core::vector3df m_target_direction;
/** The up vector the camera should have, only used for the first person camera. */
core::vector3df m_target_up_vector;
/** List of all cameras. */
static std::vector<Camera*> m_all_cameras;
@@ -251,21 +266,53 @@ public:
/** Returns the kart to which this camera is attached. */
AbstractKart* getKart() { return m_kart; }
// ------------------------------------------------------------------------
/** Sets if the first person camera should be moved smooth. */
void setSmoothMovement (bool value) { m_smooth = value; }
// ------------------------------------------------------------------------
/** If the first person camera should be moved smooth. */
bool getSmoothMovement () { return m_smooth; }
// ------------------------------------------------------------------------
/** Sets the angular velocity for this camera. */
void setAngularVelocity (float vel) { m_angular_velocity = vel; }
void setMaximumVelocity (float vel) { m_max_velocity = vel; }
// ------------------------------------------------------------------------
/** Returns the current angular velocity. */
const float getAngularVelocity () { return m_angular_velocity; }
float getMaximumVelocity () { return m_max_velocity; }
// ------------------------------------------------------------------------
/** Sets the vector, the first person camera should look at. */
void setDirection (core::vector3df target) { m_target_direction = target; }
// ------------------------------------------------------------------------
/** Gets the vector, the first person camera should look at. */
const core::vector3df &getDirection () { return m_target_direction; }
// ------------------------------------------------------------------------
/** Sets the up vector, the first person camera should use. */
void setUpVector (core::vector3df target) { m_target_up_vector = target; }
// ------------------------------------------------------------------------
/** Gets the up vector, the first person camera should use. */
const core::vector3df &getUpVector () { return m_target_up_vector; }
// ------------------------------------------------------------------------
/** Sets the angular velocity for this camera. */
void setAngularVelocity (float vel);
// ------------------------------------------------------------------------
/** Returns the current target angular velocity. */
float getAngularVelocity ();
// ------------------------------------------------------------------------
/** Sets the linear velocity for this camera. */
void setLinearVelocity (core::vector3df vel) { m_lin_velocity = vel; }
void setLinearVelocity (core::vector3df vel);
// ------------------------------------------------------------------------
/** Returns the current linear velocity. */
const core::vector3df &getLinearVelocity () { return m_lin_velocity; }
const core::vector3df &getLinearVelocity ();
// ------------------------------------------------------------------------
/** Sets the ambient light for this camera. */

View File

@@ -168,10 +168,10 @@ void InputManager::handleStaticAction(int key, int value)
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
core::vector3df vel(active_cam->getLinearVelocity());
vel.Z = value ? 15 : 0;
active_cam->setLinearVelocity(vel);
Camera *cam = Camera::getActiveCamera();
core::vector3df vel(cam->getLinearVelocity());
vel.Z = value ? cam->getMaximumVelocity() : 0;
cam->setLinearVelocity(vel);
break;
}
case KEY_KEY_S:
@@ -179,10 +179,10 @@ void InputManager::handleStaticAction(int key, int value)
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
core::vector3df vel(active_cam->getLinearVelocity());
vel.Z = value ? -15 : 0;
active_cam->setLinearVelocity(vel);
Camera *cam = Camera::getActiveCamera();
core::vector3df vel(cam->getLinearVelocity());
vel.Z = value ? -cam->getMaximumVelocity() : 0;
cam->setLinearVelocity(vel);
break;
}
case KEY_KEY_D:
@@ -190,10 +190,10 @@ void InputManager::handleStaticAction(int key, int value)
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
core::vector3df vel(active_cam->getLinearVelocity());
vel.X = value ? -15 : 0;
active_cam->setLinearVelocity(vel);
Camera *cam = Camera::getActiveCamera();
core::vector3df vel(cam->getLinearVelocity());
vel.X = value ? -cam->getMaximumVelocity() : 0;
cam->setLinearVelocity(vel);
break;
}
case KEY_KEY_A:
@@ -201,10 +201,10 @@ void InputManager::handleStaticAction(int key, int value)
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
core::vector3df vel(active_cam->getLinearVelocity());
vel.X = value ? 15 : 0;
active_cam->setLinearVelocity(vel);
Camera *cam = Camera::getActiveCamera();
core::vector3df vel(cam->getLinearVelocity());
vel.X = value ? cam->getMaximumVelocity() : 0;
cam->setLinearVelocity(vel);
break;
}
// Rotating the first person camera
@@ -960,6 +960,7 @@ EventPropagation InputManager::input(const SEvent& event)
{
if (UserConfigParams::m_camera_debug == 3)
{
Camera *cam = Camera::getActiveCamera();
// Center of the screen
core::vector2df screen_size = irr_driver->getCurrentScreenSize();
int mid_x = (int) screen_size.X / 2;
@@ -977,26 +978,27 @@ EventPropagation InputManager::input(const SEvent& event)
if (m_mouse_val_x != -1 && m_mouse_reset <= 0)
{
// Rotate camera
scene::ICameraSceneNode *cam = Camera::getActiveCamera()
->getCameraSceneNode();
Vec3 direction(cam->getTarget() - cam->getPosition());
core::vector3df up(cam->getUpVector());
core::vector3df direction(cam->getDirection());
core::vector3df side(direction.crossProduct(up));
direction.normalize();
Vec3 up(cam->getUpVector());
up.normalize();
btQuaternion quat(up, mouse_x);
btTransform trans(quat);
core::quaternion quat;
quat.fromAngleAxis(mouse_x, up);
quat.setRotation(direction.cross(up), mouse_y);
trans *= btTransform(quat);
core::quaternion quat_y;
quat_y.fromAngleAxis(mouse_y, side);
quat *= quat_y;
direction = quat * direction;
cam->setDirection(direction);
side = direction.crossProduct(up);
Vec3 target(trans(direction));
cam->setTarget(target.toIrrVector() + cam->getPosition());
/*Vec3 side(direction.cross(up));
// Compute new up vector
up = side.cross(direction);
/*up = side.crossProduct(direction);
up.normalize();
// Don't do that because it looks ugly and is bad to handle ;)
cam->setUpVector(up.toIrrVector());*/
cam->setUpVector(up);*/
// Reset mouse position to the middle of the screen when
// the mouse is far away
@@ -1029,6 +1031,24 @@ EventPropagation InputManager::input(const SEvent& event)
// Reset mouse position
m_mouse_val_x = m_mouse_val_y = -1;
}
else if (type == EMIE_MOUSE_WHEEL)
{
if (UserConfigParams::m_camera_debug == 3)
{
// Use scrolling to change the maximum speed
// Only test if it's more or less than 0 as it seems to be not
// reliable accross more platforms.
Camera *cam = Camera::getActiveCamera();
if (event.MouseInput.Wheel < 0)
{
cam->setMaximumVelocity(cam->getMaximumVelocity() - 3);
}
else if (event.MouseInput.Wheel > 0)
{
cam->setMaximumVelocity(cam->getMaximumVelocity() + 3);
}
}
}
/*
EMIE_LMOUSE_PRESSED_DOWN Left mouse button was pressed down.

View File

@@ -19,6 +19,7 @@
#include "debug.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "graphics/irr_driver.hpp"
#include "items/powerup_manager.hpp"
#include "items/attachment.hpp"
@@ -92,6 +93,7 @@ enum DebugMenuCommand
DEBUG_GUI_CAM_TOP,
DEBUG_GUI_CAM_WHEEL,
DEBUG_GUI_CAM_NORMAL,
DEBUG_GUI_CAM_SMOOTH,
DEBUG_HIDE_KARTS,
DEBUG_THROTTLE_FPS,
DEBUG_VISUAL_VALUES,
@@ -209,6 +211,7 @@ bool onEvent(const SEvent &event)
sub->addItem(L"Wheel view", DEBUG_GUI_CAM_WHEEL);
sub->addItem(L"First person view", DEBUG_GUI_CAM_FREE);
sub->addItem(L"Normal view", DEBUG_GUI_CAM_NORMAL);
sub->addItem(L"Toggle smooth camera", DEBUG_GUI_CAM_SMOOTH);
mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES);
@@ -482,6 +485,11 @@ bool onEvent(const SEvent &event)
UserConfigParams::m_camera_debug = 0;
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_SMOOTH)
{
Camera *cam = Camera::getActiveCamera();
cam->setSmoothMovement(!cam->getSmoothMovement());
}
else if (cmdID == DEBUG_PRINT_START_POS)
{
if(!world) return false;