Merge pull request #2028 from Flakebi/fpscam
Improvements for the first person camera
This commit is contained in:
commit
248755abee
@ -50,6 +50,7 @@ Camera* Camera::s_active_camera = NULL;
|
||||
Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
{
|
||||
m_smooth = false;
|
||||
m_attached = false;
|
||||
m_mode = CM_NORMAL;
|
||||
m_index = camera_index;
|
||||
m_original_kart = kart;
|
||||
@ -91,6 +92,11 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
m_target_direction = core::vector3df(0, 0, 1);
|
||||
m_target_up_vector = core::vector3df(0, 1, 0);
|
||||
m_direction_velocity = core::vector3df(0, 0, 0);
|
||||
|
||||
m_local_position = core::vector3df(0, 0, 0);
|
||||
m_local_direction = core::vector3df(0, 0, 1);
|
||||
m_local_up = core::vector3df(0, 1, 0);
|
||||
|
||||
m_angular_velocity = 0;
|
||||
m_target_angular_velocity = 0;
|
||||
m_max_velocity = 15;
|
||||
@ -108,6 +114,42 @@ Camera::~Camera()
|
||||
s_active_camera = NULL;
|
||||
} // ~Camera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera.
|
||||
* \param x The horizontal difference of the mouse position.
|
||||
* \param y The vertical difference of the mouse position.
|
||||
*/
|
||||
void Camera::applyMouseMovement (float x, float y)
|
||||
{
|
||||
core::vector3df direction(m_target_direction);
|
||||
core::vector3df up(m_camera->getUpVector());
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
up = m_local_up;
|
||||
|
||||
core::vector3df side(direction.crossProduct(up));
|
||||
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(x, up);
|
||||
|
||||
core::quaternion quat_y;
|
||||
quat_y.fromAngleAxis(y, side);
|
||||
quat *= quat_y;
|
||||
|
||||
direction = quat * direction;
|
||||
m_target_direction = direction;
|
||||
|
||||
// Don't do that because it looks ugly and is bad to handle ;)
|
||||
/*side = direction.crossProduct(up);
|
||||
// Compute new up vector
|
||||
up = side.crossProduct(direction);
|
||||
up.normalize();
|
||||
cam->setUpVector(up);*/
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Changes the owner of this camera to the new kart.
|
||||
* \param new_kart The new kart to use this camera.
|
||||
@ -489,11 +531,21 @@ void Camera::update(float dt)
|
||||
// - the kart should not be visible, but it works)
|
||||
m_camera->setNearValue(27.0);
|
||||
}
|
||||
// Update the first person camera
|
||||
else if (UserConfigParams::m_camera_debug == 3)
|
||||
{
|
||||
core::vector3df direction(m_camera->getTarget() - m_camera->getPosition());
|
||||
core::vector3df up(m_camera->getUpVector());
|
||||
core::vector3df side(direction.crossProduct(up));
|
||||
core::vector3df pos = m_camera->getPosition();
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
{
|
||||
direction = m_local_direction;
|
||||
up = m_local_up;
|
||||
pos = m_local_position;
|
||||
}
|
||||
|
||||
// Update smooth movement
|
||||
if (m_smooth)
|
||||
@ -566,9 +618,33 @@ void Camera::update(float dt)
|
||||
// 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;
|
||||
|
||||
if (m_attached)
|
||||
{
|
||||
// Save current values
|
||||
m_local_position = pos;
|
||||
m_local_direction = direction;
|
||||
m_local_up = up;
|
||||
|
||||
// Move the camera with the kart
|
||||
btTransform t = m_kart->getTrans();
|
||||
if (stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation() != 0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
pos = Vec3(t(Vec3(pos))).toIrrVector();
|
||||
|
||||
btQuaternion q = t.getRotation();
|
||||
btMatrix3x3 mat(q);
|
||||
direction = Vec3(mat * Vec3(direction)).toIrrVector();
|
||||
up = Vec3(mat * Vec3(up)).toIrrVector();
|
||||
}
|
||||
|
||||
// Set camera attributes
|
||||
m_camera->setPosition(pos);
|
||||
m_camera->setTarget(pos + direction);
|
||||
|
@ -113,6 +113,10 @@ private:
|
||||
/** Smooth acceleration with the first person camera. */
|
||||
bool m_smooth;
|
||||
|
||||
/** Attache the first person camera to a kart.
|
||||
That means moving the kart also moves the camera. */
|
||||
bool m_attached;
|
||||
|
||||
/** The speed at which the up-vector rotates, only used for the first person camera. */
|
||||
float m_angular_velocity;
|
||||
|
||||
@ -138,6 +142,15 @@ private:
|
||||
/** The up vector the camera should have, only used for the first person camera. */
|
||||
core::vector3df m_target_up_vector;
|
||||
|
||||
/** Save the local position if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_position;
|
||||
|
||||
/** Save the local direction if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_direction;
|
||||
|
||||
/** Save the local up vector if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_up;
|
||||
|
||||
/** List of all cameras. */
|
||||
static std::vector<Camera*> m_all_cameras;
|
||||
|
||||
@ -269,6 +282,10 @@ public:
|
||||
/** Returns the kart to which this camera is attached. */
|
||||
AbstractKart* getKart() { return m_kart; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera. */
|
||||
void applyMouseMovement (float x, float y);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved smooth. */
|
||||
void setSmoothMovement (bool value) { m_smooth = value; }
|
||||
@ -277,6 +294,14 @@ public:
|
||||
/** If the first person camera should be moved smooth. */
|
||||
bool getSmoothMovement () { return m_smooth; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved with the kart. */
|
||||
void setAttachedFpsCam (bool value) { m_attached = value; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** If the first person camera should be moved with the kart. */
|
||||
bool getAttachedFpsCam () { return m_attached; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void setMaximumVelocity (float vel) { m_max_velocity = vel; }
|
||||
|
@ -67,8 +67,7 @@ using GUIEngine::EVENT_BLOCK;
|
||||
/** Initialise input
|
||||
*/
|
||||
InputManager::InputManager() : m_mode(BOOTSTRAP),
|
||||
m_mouse_val_x(-1), m_mouse_val_y(-1),
|
||||
m_mouse_reset(0)
|
||||
m_mouse_val_x(-1), m_mouse_val_y(-1)
|
||||
{
|
||||
m_device_manager = new DeviceManager();
|
||||
m_device_manager->initialize();
|
||||
@ -977,34 +976,16 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
UserConfigParams::m_fpscam_direction_speed;
|
||||
float mouse_y = ((float) diff_y) *
|
||||
-UserConfigParams::m_fpscam_direction_speed;
|
||||
|
||||
// No movement the first time it's used
|
||||
// At the moment there's also a hard limit because the mouse
|
||||
// gets reset to the middle of the screen and sometimes there
|
||||
// are more events fired than expected.
|
||||
if (m_mouse_val_x != -1 && m_mouse_reset <= 0)
|
||||
if (m_mouse_val_x != -1 &&
|
||||
(diff_x + diff_y) < 100 && (diff_x + diff_y) > -100)
|
||||
{
|
||||
// Rotate camera
|
||||
core::vector3df up(cam->getUpVector());
|
||||
core::vector3df direction(cam->getDirection());
|
||||
core::vector3df side(direction.crossProduct(up));
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(mouse_x, up);
|
||||
|
||||
core::quaternion quat_y;
|
||||
quat_y.fromAngleAxis(mouse_y, side);
|
||||
quat *= quat_y;
|
||||
|
||||
direction = quat * direction;
|
||||
cam->setDirection(direction);
|
||||
side = direction.crossProduct(up);
|
||||
|
||||
// Compute new up vector
|
||||
/*up = side.crossProduct(direction);
|
||||
up.normalize();
|
||||
// Don't do that because it looks ugly and is bad to handle ;)
|
||||
cam->setUpVector(up);*/
|
||||
cam->applyMouseMovement(mouse_x, mouse_y);
|
||||
|
||||
// Reset mouse position to the middle of the screen when
|
||||
// the mouse is far away
|
||||
@ -1016,8 +997,6 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
irr_driver->getDevice()->getCursorControl()->setPosition(mid_x, mid_y);
|
||||
m_mouse_val_x = mid_x;
|
||||
m_mouse_val_y = mid_y;
|
||||
// Ignore the next 2 movements
|
||||
m_mouse_reset = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1029,7 +1008,6 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
{
|
||||
m_mouse_val_x = event.MouseInput.X;
|
||||
m_mouse_val_y = event.MouseInput.Y;
|
||||
--m_mouse_reset;
|
||||
}
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
@ -67,10 +67,6 @@ private:
|
||||
* makes the mouse behave like an analog axis on a gamepad/joystick.
|
||||
*/
|
||||
int m_mouse_val_x, m_mouse_val_y;
|
||||
/** To detect mouse events that are not caused by the user but by resetting
|
||||
the mouse position to the center of the screen.
|
||||
If it's not 0, the movement is ignored and the value is decreased. */
|
||||
int m_mouse_reset;
|
||||
|
||||
void dispatchInput(Input::InputType, int deviceID, int btnID,
|
||||
Input::AxisDirection direction, int value);
|
||||
|
@ -97,6 +97,7 @@ enum DebugMenuCommand
|
||||
DEBUG_GUI_CAM_WHEEL,
|
||||
DEBUG_GUI_CAM_NORMAL,
|
||||
DEBUG_GUI_CAM_SMOOTH,
|
||||
DEBUG_GUI_CAM_ATTACH,
|
||||
DEBUG_HIDE_KARTS,
|
||||
DEBUG_THROTTLE_FPS,
|
||||
DEBUG_VISUAL_VALUES,
|
||||
@ -260,6 +261,7 @@ bool onEvent(const SEvent &event)
|
||||
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);
|
||||
sub->addItem(L"Attach fps camera to kart", DEBUG_GUI_CAM_ATTACH);
|
||||
|
||||
mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES);
|
||||
|
||||
@ -539,6 +541,11 @@ bool onEvent(const SEvent &event)
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setSmoothMovement(!cam->getSmoothMovement());
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_ATTACH)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setAttachedFpsCam(!cam->getAttachedFpsCam());
|
||||
}
|
||||
else if (cmdID == DEBUG_PRINT_START_POS)
|
||||
{
|
||||
if(!world) return false;
|
||||
|
Loading…
Reference in New Issue
Block a user