Implemented view bobbing (testing simple lemniscate shape)
authorKahrl <kahrl@gmx.net>
Thu, 8 Sep 2011 11:03:55 +0000 (13:03 +0200)
committerKahrl <kahrl@gmx.net>
Thu, 8 Sep 2011 11:03:55 +0000 (13:03 +0200)
src/camera.cpp
src/camera.h
src/game.cpp

index 9eb8f1a69eb7ab78eb26afd883fdb8230d6c732d..16fad6132e1f77a286fc255587fbc020b716b720 100644 (file)
@@ -49,12 +49,15 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
        m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range
 
        m_view_bobbing_anim(0),
-       m_view_bobbing_anim_left(0)
+       m_view_bobbing_state(0)
 {
        //dstream<<__FUNCTION_NAME<<std::endl;
 
+       // note: making the camera node a child of the player node
+       // would lead to unexpected behaviour, so we don't do that.
        m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode());
-       m_cameranode = smgr->addCameraSceneNode(m_playernode);
+       m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode());
+       m_cameranode->bindTargetAndRotation(true);
 
        updateSettings();
 }
@@ -65,6 +68,21 @@ Camera::~Camera()
 
 void Camera::step(f32 dtime)
 {
+       if (m_view_bobbing_state != 0)
+       {
+               const f32 bobspeed = 0x1000000;
+               s32 offset = MYMAX(dtime * bobspeed, 1);
+               if (m_view_bobbing_state == 2)
+               {
+                       // Animation is getting turned off
+                       s32 subanim = (m_view_bobbing_anim & 0x7fffff);
+                       if (subanim < 0x400000)
+                               offset = -1 *  MYMIN(offset, subanim);
+                       else
+                               offset = MYMIN(offset, 0x800000 - subanim);
+               }
+               m_view_bobbing_anim = (m_view_bobbing_anim + offset) & 0xffffff;
+       }
 }
 
 void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
@@ -72,43 +90,66 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
        if (m_playernode == NULL || m_cameranode == NULL)
                return;
 
+       // Set player node transformation
+       m_playernode->setPosition(player->getPosition());
+       //m_playernode->setRotation(v3f(player->getPitch(), -1 * player->getYaw(), 0));
+       m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
+       m_playernode->updateAbsolutePosition();
+
+       // Compute relative camera position and target
+       v3f relative_cam_pos = player->getEyePosition() - player->getPosition();
+       v3f relative_cam_target = v3f(0,0,1);
+       relative_cam_target.rotateYZBy(player->getPitch());
+       relative_cam_target += relative_cam_pos;
+
+       f32 bobangle = m_view_bobbing_anim * 2 * M_PI / 0x1000000;
+       f32 bobangle_s = sin(bobangle);
+       f32 bobangle_c = cos(bobangle);
+       f32 bobwidth = 0.03 * cos(player->getPitch() * M_PI / 180)
+               / (bobangle_c * bobangle_c + 1);
+       f32 bobheight = bobwidth;
+       relative_cam_pos.X += bobwidth * bobangle_s;
+       relative_cam_pos.Y += bobheight * bobangle_s * bobangle_c;
+
+       // Compute absolute camera position and target
+       m_playernode->getAbsoluteTransformation().transformVect(m_camera_position, relative_cam_pos);
+       m_playernode->getAbsoluteTransformation().transformVect(m_camera_direction, relative_cam_target);
+       m_camera_direction -= m_camera_position;
+
+       // Set camera node transformation
+       m_cameranode->setPosition(m_camera_position);
+       // *100.0 helps in large map coordinates
+       m_cameranode->setTarget(m_camera_position + 100.0 * m_camera_direction);
+
        // FOV and and aspect ratio
        m_aspect = (f32)screensize.X / (f32) screensize.Y;
        m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y));
        m_cameranode->setAspectRatio(m_aspect);
        m_cameranode->setFOV(m_fov_y);
-
        // Just so big a value that everything rendered is visible
        // Some more allowance that m_viewing_range_max * BS because of active objects etc.
        m_cameranode->setFarValue(m_viewing_range_max * BS * 10);
 
-       m_camera_position = player->getEyePosition();  // TODO bobbing
-       m_cameranode->setPosition(m_camera_position);
-
-       m_camera_direction = v3f(0,0,1);
-       m_camera_direction.rotateYZBy(player->getPitch());
-       m_camera_direction.rotateXZBy(player->getYaw());
-       // *100.0 helps in large map coordinates
-       m_cameranode->setTarget(m_camera_position + m_camera_direction * 100.0);
-
        // Render distance feedback loop
        updateViewingRange(frametime);
 
-       // Check if view bobbing is active
+       // If the player seems to be walking on solid ground,
+       // view bobbing is enabled and free_move is off,
+       // start (or continue) the view bobbing animation.
        v3f speed = player->getSpeed();
-       f32 epsilon = BS / 1000.0;
-       if (speed.X * speed.X + speed.Z * speed.Z > epsilon*epsilon &&
-                       speed.Y < epsilon &&
-                       g_settings.getBool("view_bobbing") == true &&
-                       g_settings.getBool("free_move") == false)
+       //dstream<<"speed: ("<<speed.X<<","<<speed.Y<<","<<speed.Z<<")"<<std::endl;
+       if ((hypot(speed.X, speed.Z) > BS) &&
+               (fabs(speed.Y) < BS/10) &&
+               (g_settings.getBool("view_bobbing") == true) &&
+               (g_settings.getBool("free_move") == false))
        {
-               // The player seems to be walking on solid ground.
-               // Enable view bobbing.
-               //dstream << "View bobbing active" << std::endl;
+               // Start animation
+               m_view_bobbing_state = 1;
        }
-       else
+       else if (m_view_bobbing_state == 1)
        {
-               //dstream << "View bobbing inactive" << std::endl;
+               // Stop animation
+               m_view_bobbing_state = 2;
        }
 }
 
index 88f03e66d303a47675beb671928c153793821b5d..500168f3de13bb03a01156ae36589f2b44955e02 100644 (file)
@@ -38,7 +38,7 @@ public:
 
        // Get player scene node.
        // This node is positioned at the player's torso (without any view bobbing),
-       // as given by Player::m_position, Player::m_pitch and Player::m_yaw.
+       // as given by Player::m_position. Yaw is applied but not pitch.
        // Things like wielded tools should be positioned relative to this node.
        inline scene::ISceneNode* getPlayerNode() const
        {
@@ -46,7 +46,6 @@ public:
        }
 
        // Get camera scene node.
-       // The camera node is a child of the player node.
        // It has the eye transformation and view bobbing applied.
        inline scene::ICameraSceneNode* getCameraNode() const
        {
@@ -131,10 +130,12 @@ private:
        f32 m_frametime_counter;
        f32 m_time_per_range;
 
-       // View bobbing animation frame (0 <= m_view_bobbing < 0x10000)
-       u32 m_view_bobbing_anim;
-       // Number of frames to continue the view bobbing animation.
-       u32 m_view_bobbing_anim_left;
+       // View bobbing animation frame (0 <= m_view_bobbing < 0x1000000)
+       s32 m_view_bobbing_anim;
+       // If 0, view bobbing is off (e.g. player is standing).
+       // If 1, view bobbing is on (player is walking).
+       // If 2, view bobbing is getting switched off.
+       s32 m_view_bobbing_state;
 };
 
 #endif
index fc1486b737197c6ffdfc387208c943376a90b978..24f356e466ddda964a1c75d1c558aad3ed0c764b 100644 (file)
@@ -1477,7 +1477,7 @@ void the_game(
 
                if(FIELD_OF_VIEW_TEST)
                {
-                       client.updateCamera(v3f(0,0,0), v3f(0,0,1), M_PI);
+                       client.updateCamera(v3f(0,0,0), v3f(0,0,1), camera_fov);
                }
                else
                {