First try of a fps camera

This commit is contained in:
Flakebi 2014-11-15 12:21:07 +01:00
parent c594295288
commit 497fa10695
6 changed files with 277 additions and 47 deletions

View File

@ -488,8 +488,8 @@ namespace UserConfigParams
/** True if check structures should be debugged. */
PARAM_PREFIX bool m_check_debug PARAM_DEFAULT( false );
/** Special debug camera: 0: normal cameral; 1: being high over the kart.;
2: on ground level. */
/** Special debug camera: 0: normal camera; 1: being high over the kart;
2: on ground level; 3: free first person camera; */
PARAM_PREFIX int m_camera_debug PARAM_DEFAULT( false );
/** True if physics debugging should be enabled. */

View File

@ -85,6 +85,8 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
m_target_speed = 10.0f;
m_rotation_range = 0.4f;
m_rotation_range = 0.0f;
m_lin_velocity = core::vector3df(0, 0, 0);
m_angular_velocity = 0;
reset();
} // Camera
@ -335,13 +337,13 @@ void Camera::smoothMoveCamera(float dt)
1.1f * (1 + ratio / 2),
camera_distance * cos(skid_angle / 2));// defines how far camera should be from player kart.
Vec3 m_kart_camera_position_with_offset = m_kart->getTrans()(camera_offset);
core::vector3df current_target = m_kart->getXYZ().toIrrVector();// next target
current_target.Y += 0.5f;
core::vector3df wanted_position = m_kart_camera_position_with_offset.toIrrVector();// new required position of camera
if ((m_kart->getSpeed() > 5 ) || (m_kart->getSpeed() < 0 ))
{
current_position += ((wanted_position - current_position) * dt
@ -480,12 +482,38 @@ void Camera::update(float dt)
// - the kart should not be visible, but it works)
m_camera->setNearValue(27.0);
}
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());
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 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());
}
else if (m_mode==CM_FINAL)
{
handleEndCamera(dt);
}
// If an explosion is happening, stop moving the camera,
// but keep it target on the kart.
else if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))

View File

@ -110,7 +110,11 @@ private:
/** Aspect ratio for camera. */
float m_aspect;
/** Linear velocity of the camera, only used for end camera. */
/** The speed at which the up-vector rotates, only used for the first person camera. */
float m_angular_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. */
@ -247,6 +251,22 @@ public:
/** Returns the kart to which this camera is attached. */
AbstractKart* getKart() { return m_kart; }
// ------------------------------------------------------------------------
/** Sets the angular velocity for this camera. */
void setAngularVelocity (float vel) { m_angular_velocity = vel; }
// ------------------------------------------------------------------------
/** Returns the current angular velocity. */
const float getAngularVelocity () { return m_angular_velocity; }
// ------------------------------------------------------------------------
/** Sets the linear velocity for this camera. */
void setLinearVelocity (core::vector3df vel) { m_lin_velocity = vel; }
// ------------------------------------------------------------------------
/** Returns the current linear velocity. */
const core::vector3df &getLinearVelocity () { return m_lin_velocity; }
// ------------------------------------------------------------------------
/** Sets the ambient light for this camera. */
void setAmbientLight(const video::SColor &color) { m_ambient_light=color; }

View File

@ -44,6 +44,7 @@
#include "utils/string_utils.hpp"
#include <ISceneManager.h>
#include <ICameraSceneNode.h>
#include <ISceneNode.h>
#include <map>
@ -66,7 +67,8 @@ using GUIEngine::EVENT_BLOCK;
/** Initialise input
*/
InputManager::InputManager() : m_mode(BOOTSTRAP),
m_mouse_val_x(0), m_mouse_val_y(0)
m_mouse_val_x(-1), m_mouse_val_y(-1),
m_mouse_reset(0)
{
m_device_manager = new DeviceManager();
m_device_manager->initialize();
@ -107,6 +109,7 @@ void InputManager::handleStaticAction(int key, int value)
world->onFirePressed(NULL);
}
switch (key)
{
#ifdef DEBUG
@ -138,6 +141,7 @@ void InputManager::handleStaticAction(int key, int value)
control_is_pressed = value!=0;
break;
// Flying up and down
case KEY_KEY_I:
{
if (!world || !UserConfigParams::m_artist_debug_mode) break;
@ -158,6 +162,71 @@ void InputManager::handleStaticAction(int key, int value)
kart->flyDown();
break;
}
// Moving the first person camera
case KEY_KEY_W:
{
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);
break;
}
case KEY_KEY_S:
{
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);
break;
}
case KEY_KEY_D:
{
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);
break;
}
case KEY_KEY_A:
{
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);
break;
}
// Rotating the first person camera
case KEY_KEY_Q:
{
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
active_cam->setAngularVelocity(value ? 1 : 0);
break;
}
case KEY_KEY_E:
{
if (!world || !UserConfigParams::m_artist_debug_mode ||
UserConfigParams::m_camera_debug != 3) break;
Camera *active_cam = Camera::getActiveCamera();
active_cam->setAngularVelocity(value ? -1 : 0);
break;
}
case KEY_SNAPSHOT:
case KEY_PRINT:
// on windows we don't get a press event, only release. So
@ -170,12 +239,12 @@ void InputManager::handleStaticAction(int key, int value)
if (UserConfigParams::m_artist_debug_mode && world)
{
AbstractKart* kart = world->getLocalPlayerKart(0);
if (control_is_pressed)
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
else
kart->setPowerup(PowerupManager::POWERUP_RUBBERBALL, 10000);
#ifdef FORCE_RESCUE_ON_FIRST_KART
// Can be useful for debugging places where the AI gets into
// a rescue loop: rescue, drive, crash, rescue to same place
@ -187,7 +256,7 @@ void InputManager::handleStaticAction(int key, int value)
if (UserConfigParams::m_artist_debug_mode && world)
{
AbstractKart* kart = world->getLocalPlayerKart(0);
kart->setPowerup(PowerupManager::POWERUP_PLUNGER, 10000);
}
break;
@ -288,8 +357,7 @@ void InputManager::handleStaticAction(int key, int value)
default:
break;
} // switch
}
} // handleStaticAction
//-----------------------------------------------------------------------------
/**
@ -386,7 +454,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
}
else m_sensed_input_high_gamepad.insert(input_id);
}
// At least with xbox controller they can come to a 'rest' with a value of
// At least with xbox controller they can come to a 'rest' with a value of
// around 6000! So in order to detect that an axis was released, we need to
// test with a rather high deadzone value
else if ( abs(value) < Input::MAX_VALUE/3.0f )
@ -816,8 +884,20 @@ EventPropagation InputManager::input(const SEvent& event)
// escape is a little special
if (key == KEY_ESCAPE)
{
StateManager::get()->escapePressed();
return EVENT_BLOCK;
// Exit from first person view if activated
if (!GUIEngine::ModalDialog::isADialogActive() &&
StateManager::get()->getGameState() == GUIEngine::GAME &&
UserConfigParams::m_camera_debug == 3)
{
UserConfigParams::m_camera_debug = 0;
irr_driver->getDevice()->getCursorControl()->setVisible(true);
return EVENT_BLOCK;
}
else
{
StateManager::get()->escapePressed();
return EVENT_BLOCK;
}
}
// 'backspace' in a text control must never be mapped, since user
// can be in a text area trying to erase text (and if it's mapped
@ -871,16 +951,83 @@ EventPropagation InputManager::input(const SEvent& event)
return EVENT_BLOCK; // Don't propagate key up events
}
}
#if 0 // in case we ever use mouse in-game...
else if(event.EventType == EET_MOUSE_INPUT_EVENT)
// Use the mouse to change the looking direction when first person view is activated
else if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
const int type = event.MouseInput.Event;
if(type == EMIE_MOUSE_MOVED)
if (type == EMIE_MOUSE_MOVED)
{
// m_mouse_x = event.MouseInput.X;
// m_mouse_y = event.MouseInput.Y;
//const int wheel = event.MouseInput.Wheel;
if (UserConfigParams::m_camera_debug == 3)
{
// Center of the screen
core::vector2df screen_size = irr_driver->getCurrentScreenSize();
int mid_x = (int) screen_size.X / 2;
int mid_y = (int) screen_size.Y / 2;
//const int wheel = event.MouseInput.Wheel;
// Relative mouse movement
int diff_x = event.MouseInput.X - m_mouse_val_x;
int diff_y = event.MouseInput.Y - m_mouse_val_y;
float mouse_x = ((float) diff_x) / 150;
float mouse_y = ((float) diff_y) / -150;
// 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)
{
// Rotate camera
scene::ICameraSceneNode *cam = Camera::getActiveCamera()
->getCameraSceneNode();
Vec3 direction(cam->getTarget() - cam->getPosition());
direction.normalize();
Vec3 up(cam->getUpVector());
up.normalize();
btQuaternion quat(up, mouse_x);
btTransform trans(quat);
quat.setRotation(direction.cross(up), mouse_y);
trans *= btTransform(quat);
Vec3 target(trans(direction));
cam->setTarget(target.toIrrVector() + cam->getPosition());
/*Vec3 side(direction.cross(up));
// Compute new up vector
up = side.cross(direction);
up.normalize();
// Don't do that because it looks ugly and is bad to handle ;)
cam->setUpVector(up.toIrrVector());*/
// Reset mouse position to the middle of the screen when
// the mouse is far away
if (event.MouseInput.X < mid_x / 2 ||
event.MouseInput.X > (mid_x + mid_x / 2) ||
event.MouseInput.Y < mid_y / 2 ||
event.MouseInput.Y > (mid_y + mid_y / 2))
{
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
{
m_mouse_val_x = event.MouseInput.X;
m_mouse_val_y = event.MouseInput.Y;
}
}
else
{
m_mouse_val_x = event.MouseInput.X;
m_mouse_val_y = event.MouseInput.Y;
--m_mouse_reset;
}
return EVENT_BLOCK;
}
else
// Reset mouse position
m_mouse_val_x = m_mouse_val_y = -1;
}
/*
@ -896,7 +1043,6 @@ EventPropagation InputManager::input(const SEvent& event)
how fast.
*/
}
#endif
// block events in all modes but initial menus (except in text boxes to
// allow typing, and except in modal dialogs in-game)
@ -964,7 +1110,7 @@ void InputManager::setMode(InputDriverMode new_mode)
// Reset the helper values for the relative mouse movement
// supresses to the notification of them as an input.
m_mouse_val_x = m_mouse_val_y = 0;
m_mouse_val_x = m_mouse_val_y = -1;
//irr_driver->showPointer();
m_mode = MENU;
@ -1040,7 +1186,7 @@ void InputManager::setMode(InputDriverMode new_mode)
// Reset the helper values for the relative mouse movement
// supresses to the notification of them as an input.
m_mouse_val_x = m_mouse_val_y = 0;
m_mouse_val_x = m_mouse_val_y = -1;
m_mode = new_mode;
break;

View File

@ -66,7 +66,11 @@ private:
* values exceed the deadzone value the input is reported to the game. This
* makes the mouse behave like an analog axis on a gamepad/joystick.
*/
int m_mouse_val_x, m_mouse_val_y;
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);

View File

@ -43,8 +43,8 @@ using namespace gui;
namespace Debug {
/** This is to let mouse input events go through when the debug menu is
* visible, otherwise GUI events would be blocked while in a race...
/** This is to let mouse input events go through when the debug menu is
* visible, otherwise GUI events would be blocked while in a race...
*/
static bool g_debug_menu_visible = false;
@ -86,7 +86,12 @@ enum DebugMenuCommand
DEBUG_ATTACHMENT_PARACHUTE,
DEBUG_ATTACHMENT_BOMB,
DEBUG_ATTACHMENT_ANVIL,
DEBUG_TOGGLE_GUI,
DEBUG_GUI_TOGGLE,
DEBUG_GUI_HIDE_KARTS,
DEBUG_GUI_CAM_FREE,
DEBUG_GUI_CAM_TOP,
DEBUG_GUI_CAM_WHEEL,
DEBUG_GUI_CAM_NORMAL,
DEBUG_HIDE_KARTS,
DEBUG_THROTTLE_FPS,
DEBUG_VISUAL_VALUES,
@ -153,11 +158,11 @@ bool onEvent(const SEvent &event)
{
// root menu
gui::IGUIEnvironment* guienv = irr_driver->getGUI();
core::rect<s32> r(event.MouseInput.X, event.MouseInput.Y,
core::rect<s32> r(event.MouseInput.X, event.MouseInput.Y,
event.MouseInput.Y+100, event.MouseInput.Y+100);
IGUIContextMenu* mnu = guienv->addContextMenu(r, NULL);
int graphicsMenuIndex = mnu->addItem(L"Graphics >",-1,true,true);
// graphics menu
IGUIContextMenu* sub = mnu->getSubMenu(graphicsMenuIndex);
@ -189,25 +194,32 @@ bool onEvent(const SEvent &event)
sub->addItem(L"Switch", DEBUG_POWERUP_SWITCH );
sub->addItem(L"Zipper", DEBUG_POWERUP_ZIPPER );
sub->addItem(L"Nitro", DEBUG_POWERUP_NITRO );
mnu->addItem(L"Attachments >",-1,true, true);
sub = mnu->getSubMenu(2);
sub->addItem(L"Bomb", DEBUG_ATTACHMENT_BOMB);
sub->addItem(L"Anvil", DEBUG_ATTACHMENT_ANVIL);
sub->addItem(L"Parachute", DEBUG_ATTACHMENT_PARACHUTE);
mnu->addItem(L"GUI >",-1,true, true);
sub = mnu->getSubMenu(3);
sub->addItem(L"Toggle GUI", DEBUG_GUI_TOGGLE);
sub->addItem(L"Hide karts", DEBUG_GUI_HIDE_KARTS);
sub->addItem(L"Top view", DEBUG_GUI_CAM_TOP);
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);
mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES);
mnu->addItem(L"Profiler",DEBUG_PROFILER);
if (UserConfigParams::m_profiler_enabled)
mnu->addItem(L"Toggle capture profiler report",
mnu->addItem(L"Toggle capture profiler report",
DEBUG_PROFILER_GENERATE_REPORT);
mnu->addItem(L"Do not limit FPS", DEBUG_THROTTLE_FPS);
mnu->addItem(L"FPS",DEBUG_FPS);
mnu->addItem(L"Save replay", DEBUG_SAVE_REPLAY);
mnu->addItem(L"Save history", DEBUG_SAVE_HISTORY);
mnu->addItem(L"Toggle GUI", DEBUG_TOGGLE_GUI);
mnu->addItem(L"Hide karts", DEBUG_HIDE_KARTS);
mnu->addItem(L"Print position", DEBUG_PRINT_START_POS);
g_debug_menu_visible = true;
@ -222,7 +234,7 @@ bool onEvent(const SEvent &event)
if (event.EventType == EET_GUI_EVENT)
{
if (event.GUIEvent.Caller != NULL &&
if (event.GUIEvent.Caller != NULL &&
event.GUIEvent.Caller->getType() == EGUIET_CONTEXT_MENU )
{
IGUIContextMenu *menu = (IGUIContextMenu*)event.GUIEvent.Caller;
@ -244,14 +256,14 @@ bool onEvent(const SEvent &event)
}
else if (cmdID == DEBUG_GRAPHICS_RESET)
{
if (physics)
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
}
else if (cmdID == DEBUG_GRAPHICS_WIREFRAME)
{
if (physics)
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
@ -259,7 +271,7 @@ bool onEvent(const SEvent &event)
}
else if (cmdID == DEBUG_GRAPHICS_MIPMAP_VIZ)
{
if (physics)
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
@ -414,7 +426,7 @@ bool onEvent(const SEvent &event)
else if (cmdID == DEBUG_POWERUP_NITRO)
{
if (!world) return false;
const unsigned int num_local_players =
const unsigned int num_local_players =
race_manager->getNumLocalPlayers();
for(unsigned int i = 0; i < num_local_players; i++)
{
@ -434,13 +446,13 @@ bool onEvent(const SEvent &event)
{
addAttachment(Attachment::ATTACH_PARACHUTE);
}
else if (cmdID == DEBUG_TOGGLE_GUI)
else if (cmdID == DEBUG_GUI_TOGGLE)
{
if (!world) return false;
RaceGUIBase* gui = world->getRaceGUI();
if (gui != NULL) gui->m_enabled = !gui->m_enabled;
}
else if (cmdID == DEBUG_HIDE_KARTS)
else if (cmdID == DEBUG_GUI_HIDE_KARTS)
{
if (!world) return false;
for (unsigned int n = 0; n<world->getNumKarts(); n++)
@ -450,6 +462,26 @@ bool onEvent(const SEvent &event)
kart->getNode()->setVisible(false);
}
}
else if (cmdID == DEBUG_GUI_CAM_TOP)
{
UserConfigParams::m_camera_debug = 1;
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_WHEEL)
{
UserConfigParams::m_camera_debug = 2;
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_FREE)
{
UserConfigParams::m_camera_debug = 3;
irr_driver->getDevice()->getCursorControl()->setVisible(false);
}
else if (cmdID == DEBUG_GUI_CAM_NORMAL)
{
UserConfigParams::m_camera_debug = 0;
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_PRINT_START_POS)
{
if(!world) return false;
@ -458,7 +490,7 @@ bool onEvent(const SEvent &event)
AbstractKart *kart = world->getKart(i);
Log::warn(kart->getIdent().c_str(),
"<start position=\"%d\" x=\"%f\" y=\"%f\" z=\"%f\" h=\"%f\"/>",
i, kart->getXYZ().getX(), kart->getXYZ().getY(),
i, kart->getXYZ().getX(), kart->getXYZ().getY(),
kart->getXYZ().getZ(),kart->getHeading()*RAD_TO_DEGREE
);
}
@ -467,14 +499,14 @@ bool onEvent(const SEvent &event)
{
#if !defined(__APPLE__)
DebugSliderDialog *dsd = new DebugSliderDialog();
dsd->setSliderHook( "red_slider", 0, 255,
dsd->setSliderHook( "red_slider", 0, 255,
[](){ return int(irr_driver->getAmbientLight().r * 255.f); },
[](int v){
video::SColorf ambient = irr_driver->getAmbientLight();
ambient.setColorComponentValue(0, v / 255.f);
irr_driver->setAmbientLight(ambient); }
);
dsd->setSliderHook("green_slider", 0, 255,
dsd->setSliderHook("green_slider", 0, 255,
[](){ return int(irr_driver->getAmbientLight().g * 255.f); },
[](int v){
video::SColorf ambient = irr_driver->getAmbientLight();
@ -488,7 +520,7 @@ bool onEvent(const SEvent &event)
ambient.setColorComponentValue(2, v / 255.f);
irr_driver->setAmbientLight(ambient); }
);
dsd->setSliderHook("ssao_radius", 0, 100,
dsd->setSliderHook("ssao_radius", 0, 100,
[](){ return int(irr_driver->getSSAORadius() * 10.f); },
[](int v){irr_driver->setSSAORadius(v / 10.f); }
);
@ -511,7 +543,7 @@ bool onEvent(const SEvent &event)
} // onEvent
// ----------------------------------------------------------------------------
/** Returns if the debug menu is visible.
/** Returns if the debug menu is visible.
*/
bool isOpen()
{