Smooth camera movement
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user