#include "camera.h"
#include "debug.h"
#include "client.h"
-#include "main.h" // for g_settings
#include "map.h"
-#include "clientmap.h" // MapDrawControl
+#include "clientmap.h" // MapDrawControl
#include "player.h"
#include <cmath>
#include "settings.h"
#include "wieldmesh.h"
-#include "noise.h" // easeCurve
+#include "noise.h" // easeCurve
#include "gamedef.h"
#include "sound.h"
#include "event.h"
m_camera_mode(CAMERA_MODE_FIRST)
{
- //dstream<<__FUNCTION_NAME<<std::endl;
+ //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.
// all other 3D scene nodes and before the GUI.
m_wieldmgr = smgr->createNewSceneManager();
m_wieldmgr->addCameraSceneNode();
- m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, true);
+ m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, false);
m_wieldnode->setItem(ItemStack(), m_gamedef);
m_wieldnode->drop(); // m_wieldmgr grabbed it
- m_wieldlightnode = m_wieldmgr->addLightSceneNode(NULL, v3f(0.0, 50.0, 0.0));
+
+ /* TODO: Add a callback function so these can be updated when a setting
+ * changes. At this point in time it doesn't matter (e.g. /set
+ * is documented to change server settings only)
+ *
+ * TODO: Local caching of settings is not optimal and should at some stage
+ * be updated to use a global settings object for getting thse values
+ * (as opposed to the this local caching). This can be addressed in
+ * a later release.
+ */
+ m_cache_fall_bobbing_amount = g_settings->getFloat("fall_bobbing_amount");
+ m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount");
+ m_cache_wanted_fps = g_settings->getFloat("wanted_fps");
+ m_cache_fov = g_settings->getFloat("fov");
+ m_cache_view_bobbing = g_settings->getBool("view_bobbing");
}
Camera::~Camera()
m_wieldmgr->drop();
}
-bool Camera::successfullyCreated(std::wstring& error_message)
+bool Camera::successfullyCreated(std::string &error_message)
{
- if (m_playernode == NULL)
- {
- error_message = L"Failed to create the player scene node";
- return false;
- }
- if (m_headnode == NULL)
- {
- error_message = L"Failed to create the head scene node";
- return false;
- }
- if (m_cameranode == NULL)
- {
- error_message = L"Failed to create the camera scene node";
- return false;
- }
- if (m_wieldmgr == NULL)
- {
- error_message = L"Failed to create the wielded item scene manager";
- return false;
- }
- if (m_wieldnode == NULL)
- {
- error_message = L"Failed to create the wielded item scene node";
- return false;
+ if (!m_playernode) {
+ error_message = "Failed to create the player scene node";
+ } else if (!m_headnode) {
+ error_message = "Failed to create the head scene node";
+ } else if (!m_cameranode) {
+ error_message = "Failed to create the camera scene node";
+ } else if (!m_wieldmgr) {
+ error_message = "Failed to create the wielded item scene manager";
+ } else if (!m_wieldnode) {
+ error_message = "Failed to create the wielded item scene node";
+ } else {
+ error_message.clear();
}
- return true;
+ return error_message.empty();
}
// Returns the fractional part of x
{
//f32 offset = dtime * m_view_bobbing_speed * 0.035;
f32 offset = dtime * m_view_bobbing_speed * 0.030;
- if (m_view_bobbing_state == 2)
- {
-#if 0
- // Animation is getting turned off
- if (m_view_bobbing_anim < 0.5)
- m_view_bobbing_anim -= offset;
- else
- m_view_bobbing_anim += offset;
- if (m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1)
- {
- m_view_bobbing_anim = 0;
- m_view_bobbing_state = 0;
- }
-#endif
-#if 1
+ if (m_view_bobbing_state == 2) {
// Animation is getting turned off
- if(m_view_bobbing_anim < 0.25)
- {
+ if (m_view_bobbing_anim < 0.25) {
m_view_bobbing_anim -= offset;
- } else if(m_view_bobbing_anim > 0.75) {
+ } else if (m_view_bobbing_anim > 0.75) {
m_view_bobbing_anim += offset;
}
- if(m_view_bobbing_anim < 0.5)
- {
+
+ if (m_view_bobbing_anim < 0.5) {
m_view_bobbing_anim += offset;
- if(m_view_bobbing_anim > 0.5)
+ if (m_view_bobbing_anim > 0.5)
m_view_bobbing_anim = 0.5;
} else {
m_view_bobbing_anim -= offset;
- if(m_view_bobbing_anim < 0.5)
+ if (m_view_bobbing_anim < 0.5)
m_view_bobbing_anim = 0.5;
}
- if(m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1 ||
- fabs(m_view_bobbing_anim - 0.5) < 0.01)
- {
+
+ if (m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1 ||
+ fabs(m_view_bobbing_anim - 0.5) < 0.01) {
m_view_bobbing_anim = 0;
m_view_bobbing_state = 0;
}
-#endif
}
- else
- {
+ else {
float was = m_view_bobbing_anim;
m_view_bobbing_anim = my_modf(m_view_bobbing_anim + offset);
bool step = (was == 0 ||
(was < 0.5f && m_view_bobbing_anim >= 0.5f) ||
(was > 0.5f && m_view_bobbing_anim <= 0.5f));
- if(step)
- {
+ if(step) {
MtEvent *e = new SimpleTriggerEvent("ViewBobbingStep");
m_gamedef->event()->put(e);
}
{
f32 oldy = old_player_position.Y;
f32 newy = player_position.Y;
- f32 t = exp(-10*frametime);
+ f32 t = exp(-23*frametime);
player_position.Y = oldy * t + newy * (1-t);
}
// Amplify according to the intensity of the impact
fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5;
- fall_bobbing *= g_settings->getFloat("fall_bobbing_amount");
+ fall_bobbing *= m_cache_fall_bobbing_amount;
}
// Calculate players eye offset for different camera modes
PlayerEyeOffset += player->eye_offset_first;
else
PlayerEyeOffset += player->eye_offset_third;
-
+
// Set head node transformation
m_headnode->setPosition(PlayerEyeOffset+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0));
m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
//rel_cam_target += 0.03 * bobvec;
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * M_PI);
float f = 1.0;
- f *= g_settings->getFloat("view_bobbing_amount");
+ f *= m_cache_view_bobbing_amount;
rel_cam_pos += bobvec * f;
//rel_cam_target += 0.995 * bobvec * f;
rel_cam_target += bobvec * f;
// Seperate camera position for calculation
v3f my_cp = m_camera_position;
-
+
// Reposition the camera for third person view
if (m_camera_mode > CAMERA_MODE_FIRST)
{
// Calculate new position
bool abort = false;
- for (int i = BS; i <= BS*2; i++)
+ for (int i = BS; i <= BS*2.75; i++)
{
my_cp.X = m_camera_position.X + m_camera_direction.X*-i;
my_cp.Z = m_camera_position.Z + m_camera_direction.Z*-i;
(((s16)(my_cp.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP);
m_camera_offset.Z += CAMERA_OFFSET_STEP*
(((s16)(my_cp.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP);
-
+
// Set camera node transformation
m_cameranode->setPosition(my_cp-intToFloat(m_camera_offset, BS));
m_cameranode->setUpVector(abs_cam_up);
m_camera_position = my_cp;
// Get FOV setting
- f32 fov_degrees = g_settings->getFloat("fov");
+ f32 fov_degrees = m_cache_fov;
fov_degrees = MYMAX(fov_degrees, 10.0);
fov_degrees = MYMIN(fov_degrees, 170.0);
wield_position.X -= 50 * sin(pow(digfrac, 0.8f) * M_PI);
wield_position.Y += 24 * sin(digfrac * 1.8 * M_PI);
wield_position.Z += 25 * 0.5;
-
+
// Euler angles are PURE EVIL, so why not use quaternions?
core::quaternion quat_begin(wield_rotation * core::DEGTORAD);
core::quaternion quat_end(v3f(80, 30, 100) * core::DEGTORAD);
m_wieldnode->setPosition(wield_position);
m_wieldnode->setRotation(wield_rotation);
- // Shine light upon the wield mesh
- video::SColor black(255,0,0,0);
- m_wieldmgr->setAmbientLight(player->light_color.getInterpolated(black, 0.7));
- m_wieldlightnode->getLightData().DiffuseColor = player->light_color.getInterpolated(black, 0.3);
- m_wieldlightnode->setPosition(v3f(30+5*sin(2*player->getYaw()*M_PI/180), -50, 0));
+ m_wieldnode->setColor(player->light_color);
// Render distance feedback loop
updateViewingRange(frametime, busytime);
- // If the player seems to be walking on solid ground,
+ // If the player is walking, swimming, or climbing,
// view bobbing is enabled and free_move is off,
// start (or continue) the view bobbing animation.
v3f speed = player->getSpeed();
- if ((hypot(speed.X, speed.Z) > BS) &&
- (player->touching_ground) &&
- (g_settings->getBool("view_bobbing") == true) &&
- (g_settings->getBool("free_move") == false ||
- !m_gamedef->checkLocalPrivilege("fly")))
+ const bool movement_XZ = hypot(speed.X, speed.Z) > BS;
+ const bool movement_Y = fabs(speed.Y) > BS;
+
+ const bool walking = movement_XZ && player->touching_ground;
+ const bool swimming = (movement_XZ || player->swimming_vertical) && player->in_liquid;
+ const bool climbing = movement_Y && player->is_climbing;
+ if ((walking || swimming || climbing) &&
+ m_cache_view_bobbing &&
+ (!g_settings->getBool("free_move") || !m_gamedef->checkLocalPrivilege("fly")))
{
// Start animation
m_view_bobbing_state = 1;
return;
m_frametime_counter = 0.2; // Same as ClientMap::updateDrawList interval
- /*dstream<<__FUNCTION_NAME
+ /*dstream<<FUNCTION_NAME
<<": Collected "<<m_added_frames<<" frames, total of "
<<m_added_busytime<<"s."<<std::endl;
<<std::endl;*/
// Get current viewing range and FPS settings
- f32 viewing_range_min = g_settings->getS16("viewing_range_nodes_min");
+ f32 viewing_range_min = g_settings->getFloat("viewing_range_nodes_min");
viewing_range_min = MYMAX(15.0, viewing_range_min);
- f32 viewing_range_max = g_settings->getS16("viewing_range_nodes_max");
+ f32 viewing_range_max = g_settings->getFloat("viewing_range_nodes_max");
viewing_range_max = MYMAX(viewing_range_min, viewing_range_max);
-
+
// Immediately apply hard limits
if(m_draw_control.wanted_range < viewing_range_min)
m_draw_control.wanted_range = viewing_range_min;
else
m_cameranode->setFarValue(viewing_range_max * BS * 10);
- f32 wanted_fps = g_settings->getFloat("wanted_fps");
+ f32 wanted_fps = m_cache_wanted_fps;
wanted_fps = MYMAX(wanted_fps, 1.0);
f32 wanted_frametime = 1.0 / wanted_fps;
}
new_range += wanted_range_change;
-
+
//f32 new_range_unclamped = new_range;
new_range = MYMAX(new_range, viewing_range_min);
new_range = MYMIN(new_range, viewing_range_max);
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
cam->setAspectRatio(m_cameranode->getAspectRatio());
cam->setFOV(72.0*M_PI/180.0);
- cam->setNearValue(0.1);
+ cam->setNearValue(10);
cam->setFarValue(1000);
if (translation != NULL)
{