From 45999b74e610b13e8cda20c0c420e152b9837ea6 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 16 Apr 2020 18:32:07 +0200 Subject: Camera: Fix shooting line offsets (#9681) Removes duplicated offset calculations from Game and use whatever the Camera class returns. This keeps the eye position nicely in sync, and gets rid of duplicated code. --- src/client/camera.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'src/client/camera.cpp') diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 871ea709d..fb1c3ff56 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -333,17 +333,21 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r fall_bobbing *= m_cache_fall_bobbing_amount; } - // Calculate players eye offset for different camera modes - v3f PlayerEyeOffset = player->getEyeOffset(); - if (m_camera_mode == CAMERA_MODE_FIRST) - 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)); - m_headnode->updateAbsolutePosition(); + // Calculate and translate the head SceneNode offsets + { + v3f eye_offset = player->getEyeOffset(); + if (m_camera_mode == CAMERA_MODE_FIRST) + eye_offset += player->eye_offset_first; + else + eye_offset += player->eye_offset_third; + + // Set head node transformation + eye_offset.Y += cameratilt * -player->hurt_tilt_strength + fall_bobbing; + m_headnode->setPosition(eye_offset); + m_headnode->setRotation(v3f(player->getPitch(), 0, + cameratilt * player->hurt_tilt_strength)); + m_headnode->updateAbsolutePosition(); + } // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); -- cgit v1.2.3 From cdbe3c5e5784b34e548c58b08579ff55b3096fb9 Mon Sep 17 00:00:00 2001 From: Danila Shutov Date: Sun, 19 Apr 2020 19:47:13 +0300 Subject: Reuse object_shader for "wielditem" and "item" entity drawtypes (#9537) --- client/shaders/wielded_shader/opengl_fragment.glsl | 127 --------------------- client/shaders/wielded_shader/opengl_vertex.glsl | 32 ------ src/client/camera.cpp | 2 +- src/client/content_cao.cpp | 9 +- src/client/wieldmesh.cpp | 17 ++- src/client/wieldmesh.h | 2 + 6 files changed, 24 insertions(+), 165 deletions(-) delete mode 100644 client/shaders/wielded_shader/opengl_fragment.glsl delete mode 100644 client/shaders/wielded_shader/opengl_vertex.glsl (limited to 'src/client/camera.cpp') diff --git a/client/shaders/wielded_shader/opengl_fragment.glsl b/client/shaders/wielded_shader/opengl_fragment.glsl deleted file mode 100644 index 546aef71d..000000000 --- a/client/shaders/wielded_shader/opengl_fragment.glsl +++ /dev/null @@ -1,127 +0,0 @@ -uniform sampler2D baseTexture; -uniform sampler2D normalTexture; -uniform sampler2D textureFlags; - -uniform vec4 skyBgColor; -uniform float fogDistance; -uniform vec3 eyePosition; - -varying vec3 vPosition; -varying vec3 worldPosition; - -varying vec3 eyeVec; -varying vec3 lightVec; - -bool normalTexturePresent = false; -bool texTileableHorizontal = false; -bool texTileableVertical = false; -bool texSeamless = false; - -const float e = 2.718281828459; -const float BS = 10.0; -const float fogStart = FOG_START; -const float fogShadingParameter = 1 / ( 1 - fogStart); - -void get_texture_flags() -{ - vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0)); - if (flags.r > 0.5) { - normalTexturePresent = true; - } - if (flags.g > 0.5) { - texTileableHorizontal = true; - } - if (flags.b > 0.5) { - texTileableVertical = true; - } - if (texTileableHorizontal && texTileableVertical) { - texSeamless = true; - } -} - -float intensity(vec3 color) -{ - return (color.r + color.g + color.b) / 3.0; -} - -float get_rgb_height(vec2 uv) -{ - if (texSeamless) { - return intensity(texture2D(baseTexture, uv).rgb); - } else { - return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb); - } -} - -vec4 get_normal_map(vec2 uv) -{ - vec4 bump = texture2D(normalTexture, uv).rgba; - bump.xyz = normalize(bump.xyz * 2.0 - 1.0); - return bump; -} - -void main(void) -{ - vec3 color; - vec4 bump; - vec2 uv = gl_TexCoord[0].st; - bool use_normalmap = false; - get_texture_flags(); - -#if USE_NORMALMAPS == 1 - if (normalTexturePresent) { - bump = get_normal_map(uv); - use_normalmap = true; - } -#endif - -#if GENERATE_NORMALMAPS == 1 - if (normalTexturePresent == false) { - float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y)); - float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP)); - float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y)); - float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); - float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); - bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0); - use_normalmap = true; - } -#endif - - vec4 base = texture2D(baseTexture, uv).rgba; - -#ifdef ENABLE_BUMPMAPPING - if (use_normalmap) { - vec3 L = normalize(lightVec); - vec3 E = normalize(eyeVec); - float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0); - float diffuse = dot(-E,bump.xyz); - color = (diffuse + 0.1 * specular) * base.rgb; - } else { - color = base.rgb; - } -#else - color = base.rgb; -#endif - - vec4 col = vec4(color.rgb, base.a); - col *= gl_Color; - // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), - // the fog will only be rendered correctly if the last operation before the - // clamp() is an addition. Else, the clamp() seems to be ignored. - // E.g. the following won't work: - // float clarity = clamp(fogShadingParameter - // * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0); - // As additions usually come for free following a multiplication, the new formula - // should be more efficient as well. - // Note: clarity = (1 - fogginess) - float clarity = clamp(fogShadingParameter - - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col = mix(skyBgColor, col, clarity); - - gl_FragColor = vec4(col.rgb, base.a); -} diff --git a/client/shaders/wielded_shader/opengl_vertex.glsl b/client/shaders/wielded_shader/opengl_vertex.glsl deleted file mode 100644 index 9f05b833a..000000000 --- a/client/shaders/wielded_shader/opengl_vertex.glsl +++ /dev/null @@ -1,32 +0,0 @@ -uniform mat4 mWorldViewProj; -uniform mat4 mWorld; - -uniform vec3 eyePosition; -uniform float animationTimer; - -varying vec3 vPosition; -varying vec3 worldPosition; - -varying vec3 eyeVec; -varying vec3 lightVec; -varying vec3 tsEyeVec; -varying vec3 tsLightVec; - -const float e = 2.718281828459; -const float BS = 10.0; - -void main(void) -{ - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = mWorldViewProj * gl_Vertex; - - vPosition = gl_Position.xyz; - worldPosition = (mWorld * gl_Vertex).xyz; - - vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0); - - lightVec = sunPosition - worldPosition; - eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; - - gl_FrontColor = gl_BackColor = gl_Color; -} diff --git a/src/client/camera.cpp b/src/client/camera.cpp index fb1c3ff56..69bd82a47 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -542,7 +542,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); - m_wieldnode->setColor(player->light_color); + m_wieldnode->setNodeLightColor(player->light_color); // Set render distance updateViewingRange(); diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 39ea4ab1e..e9e1cebd3 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -826,11 +826,12 @@ void GenericCAO::setNodeLight(u8 light) video::SColor color(255, light, light, light); if (m_prop.visual == "wielditem" || m_prop.visual == "item") { - // Since these types of visuals are using their own shader - // they should be handled separately if (m_wield_meshnode) - m_wield_meshnode->setColor(color); - } else if (m_enable_shaders) { + m_wield_meshnode->setNodeLightColor(color); + return; + } + + if (m_enable_shaders) { scene::ISceneNode *node = getSceneNode(); if (node == nullptr) diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 2c6807fab..997eb1b5b 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -347,7 +347,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che scene::SMesh *mesh = nullptr; if (m_enable_shaders) { - u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); + u32 shader_id = shdrsrc->getShader("object_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); m_material_type = shdrsrc->getShaderInfo(shader_id).material; } @@ -471,6 +471,21 @@ void WieldMeshSceneNode::setColor(video::SColor c) } } +void WieldMeshSceneNode::setNodeLightColor(video::SColor color) +{ + if (!m_meshnode) + return; + + if (m_enable_shaders) { + for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) { + video::SMaterial &material = m_meshnode->getMaterial(i); + material.EmissiveColor = color; + } + } else { + setColor(color); + } +} + void WieldMeshSceneNode::render() { // note: if this method is changed to actually do something, diff --git a/src/client/wieldmesh.h b/src/client/wieldmesh.h index 7c80a811b..933097230 100644 --- a/src/client/wieldmesh.h +++ b/src/client/wieldmesh.h @@ -87,6 +87,8 @@ public: // Must only be used if the constructor was called with lighting = false void setColor(video::SColor color); + void setNodeLightColor(video::SColor color); + scene::IMesh *getMesh() { return m_meshnode->getMesh(); } virtual void render(); -- cgit v1.2.3 From e0ea87f1f32273dba2eb5421c2a8c890479ba078 Mon Sep 17 00:00:00 2001 From: ANAND Date: Sat, 2 May 2020 16:22:11 +0530 Subject: set_fov: Add support for time-based transitions (#9705) --- doc/lua_api.txt | 15 ++++--- src/client/camera.cpp | 84 +++++++++++++++++++++++++++++-------- src/client/camera.h | 15 ++++++- src/network/clientpackethandler.cpp | 15 ++++++- src/network/networkprotocol.h | 3 +- src/player.h | 12 ++++-- src/script/lua_api/l_object.cpp | 11 +++-- src/server.cpp | 4 +- 8 files changed, 124 insertions(+), 35 deletions(-) (limited to 'src/client/camera.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f9107b623..44f62f7a7 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5998,15 +5998,18 @@ object you are working with still exists. * max: bubbles bar is not shown * See [Object properties] for more information * Is limited to range 0 ... 65535 (2^16 - 1) -* `set_fov(fov, is_multiplier)`: Sets player's FOV +* `set_fov(fov, is_multiplier, transition_time)`: Sets player's FOV * `fov`: FOV value. * `is_multiplier`: Set to `true` if the FOV value is a multiplier. Defaults to `false`. - * Set to 0 to clear FOV override. -* `get_fov()`: - * Returns player's FOV override in degrees, and a boolean depending on whether - the value is a multiplier. - * Returns 0 as first value if player's FOV hasn't been overridden. + * `transition_time`: If defined, enables smooth FOV transition. + Interpreted as the time (in seconds) to reach target FOV. + If set to 0, FOV change is instantaneous. Defaults to 0. + * Set `fov` to 0 to clear FOV override. +* `get_fov()`: Returns the following: + * Server-sent FOV value. Returns 0 if an FOV override doesn't exist. + * Boolean indicating whether the FOV value is a multiplier. + * Time (in seconds) taken for the FOV transition. Set by `set_fov`. * `set_attribute(attribute, value)`: DEPRECATED, use get_meta() instead * Sets an extra attribute with value on player. * `value` must be a string, or a number which will be converted to a diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 69bd82a47..1a5253db4 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -86,6 +86,51 @@ Camera::~Camera() m_wieldmgr->drop(); } +void Camera::notifyFovChange() +{ + LocalPlayer *player = m_client->getEnv().getLocalPlayer(); + assert(player); + + PlayerFovSpec spec = player->getFov(); + + /* + * Update m_old_fov_degrees first - it serves as the starting point of the + * upcoming transition. + * + * If an FOV transition is already active, mark current FOV as the start of + * the new transition. If not, set it to the previous transition's target FOV. + */ + if (m_fov_transition_active) + m_old_fov_degrees = m_curr_fov_degrees; + else + m_old_fov_degrees = m_server_sent_fov ? m_target_fov_degrees : m_cache_fov; + + /* + * Update m_server_sent_fov next - it corresponds to the target FOV of the + * upcoming transition. + * + * Set it to m_cache_fov, if server-sent FOV is 0. Otherwise check if + * server-sent FOV is a multiplier, and multiply it with m_cache_fov instead + * of overriding. + */ + if (spec.fov == 0.0f) { + m_server_sent_fov = false; + m_target_fov_degrees = m_cache_fov; + } else { + m_server_sent_fov = true; + m_target_fov_degrees = spec.is_multiplier ? m_cache_fov * spec.fov : spec.fov; + } + + if (spec.transition_time > 0.0f) + m_fov_transition_active = true; + + // If FOV smooth transition is active, initialize required variables + if (m_fov_transition_active) { + m_transition_time = spec.transition_time; + m_fov_diff = m_target_fov_degrees - m_old_fov_degrees; + } +} + bool Camera::successfullyCreated(std::string &error_message) { if (!m_playernode) { @@ -462,33 +507,38 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_camera_position = my_cp; /* - * Apply server-sent FOV. If server doesn't enforce FOV, - * check for zoom and set to zoom FOV. - * Otherwise, default to m_cache_fov + * Apply server-sent FOV, instantaneous or smooth transition. + * If not, check for zoom and set to zoom FOV. + * Otherwise, default to m_cache_fov. */ - - f32 fov_degrees; - PlayerFovSpec fov_spec = player->getFov(); - if (fov_spec.fov > 0.0f) { - // If server-sent FOV is a multiplier, multiply - // it with m_cache_fov instead of overriding - if (fov_spec.is_multiplier) - fov_degrees = m_cache_fov * fov_spec.fov; - else - fov_degrees = fov_spec.fov; + if (m_fov_transition_active) { + // Smooth FOV transition + // Dynamically calculate FOV delta based on frametimes + f32 delta = (frametime / m_transition_time) * m_fov_diff; + m_curr_fov_degrees += delta; + + // Mark transition as complete if target FOV has been reached + if ((m_fov_diff > 0.0f && m_curr_fov_degrees >= m_target_fov_degrees) || + (m_fov_diff < 0.0f && m_curr_fov_degrees <= m_target_fov_degrees)) { + m_fov_transition_active = false; + m_curr_fov_degrees = m_target_fov_degrees; + } + } else if (m_server_sent_fov) { + // Instantaneous FOV change + m_curr_fov_degrees = m_target_fov_degrees; } else if (player->getPlayerControl().zoom && player->getZoomFOV() > 0.001f) { // Player requests zoom, apply zoom FOV - fov_degrees = player->getZoomFOV(); + m_curr_fov_degrees = player->getZoomFOV(); } else { // Set to client's selected FOV - fov_degrees = m_cache_fov; + m_curr_fov_degrees = m_cache_fov; } - fov_degrees = rangelim(fov_degrees, 1.0f, 160.0f); + m_curr_fov_degrees = rangelim(m_curr_fov_degrees, 1.0f, 160.0f); // FOV and aspect ratio const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); m_aspect = (f32) window_size.X / (f32) window_size.Y; - m_fov_y = fov_degrees * M_PI / 180.0; + m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); diff --git a/src/client/camera.h b/src/client/camera.h index 6ec37fe10..3a59637bc 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -112,6 +112,9 @@ public: return MYMAX(m_fov_x, m_fov_y); } + // Notify about new server-sent FOV and initialize smooth FOV transition + void notifyFovChange(); + // Checks if the constructor was able to create the scene nodes bool successfullyCreated(std::string &error_message); @@ -186,6 +189,9 @@ private: Client *m_client; + // Default Client FOV (as defined by the "fov" setting) + f32 m_cache_fov; + // Absolute camera position v3f m_camera_position; // Absolute camera direction @@ -193,6 +199,14 @@ private: // Camera offset v3s16 m_camera_offset; + // Server-sent FOV variables + bool m_server_sent_fov = false; + f32 m_curr_fov_degrees, m_old_fov_degrees, m_target_fov_degrees; + + // FOV transition variables + bool m_fov_transition_active = false; + f32 m_fov_diff, m_transition_time; + v2f m_wieldmesh_offset = v2f(55.0f, -35.0f); v2f m_arm_dir; v2f m_cam_vel; @@ -230,7 +244,6 @@ private: f32 m_cache_fall_bobbing_amount; f32 m_cache_view_bobbing_amount; - f32 m_cache_fov; bool m_arm_inertia; std::list m_nametags; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index d19dc3818..6428ed752 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "util/base64.h" +#include "client/camera.h" #include "chatmessage.h" #include "client/clientmedia.h" #include "log.h" @@ -530,11 +531,21 @@ void Client::handleCommand_Movement(NetworkPacket* pkt) void Client::handleCommand_Fov(NetworkPacket *pkt) { f32 fov; - bool is_multiplier; + bool is_multiplier = false; + f32 transition_time = 0.0f; + *pkt >> fov >> is_multiplier; + // Wrap transition_time extraction within a + // try-catch to preserve backwards compat + try { + *pkt >> transition_time; + } catch (PacketError &e) {}; + LocalPlayer *player = m_env.getLocalPlayer(); - player->setFov({ fov, is_multiplier }); + assert(player); + player->setFov({ fov, is_multiplier, transition_time }); + m_camera->notifyFovChange(); } void Client::handleCommand_HP(NetworkPacket *pkt) diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 4b7345b15..73523ea42 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -384,8 +384,9 @@ enum ToClientCommand /* Sends an FOV override/multiplier to client. - float fov + f32 fov bool is_multiplier + f32 transition_time */ TOCLIENT_DEATHSCREEN = 0x37, diff --git a/src/player.h b/src/player.h index de7f427e9..3bc7762fa 100644 --- a/src/player.h +++ b/src/player.h @@ -35,7 +35,13 @@ with this program; if not, write to the Free Software Foundation, Inc., struct PlayerFovSpec { f32 fov; + + // Whether to multiply the client's FOV or to override it bool is_multiplier; + + // The time to be take to trasition to the new FOV value. + // Transition is instantaneous if omitted. Omitted by default. + f32 transition_time; }; struct PlayerControl @@ -186,12 +192,12 @@ public: void setFov(const PlayerFovSpec &spec) { - m_fov_spec = spec; + m_fov_override_spec = spec; } const PlayerFovSpec &getFov() const { - return m_fov_spec; + return m_fov_override_spec; } u32 keyPressed = 0; @@ -208,7 +214,7 @@ protected: char m_name[PLAYERNAME_SIZE]; v3f m_speed; u16 m_wield_index = 0; - PlayerFovSpec m_fov_spec = { 0.0f, false }; + PlayerFovSpec m_fov_override_spec = { 0.0f, false, 0.0f }; std::vector hud; private: diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 77e1e7dc2..dcaee10b2 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1249,7 +1249,7 @@ int ObjectRef::l_set_look_yaw(lua_State *L) return 1; } -// set_fov(self, degrees[, is_multiplier]) +// set_fov(self, degrees[, is_multiplier, transition_time]) int ObjectRef::l_set_fov(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -1258,7 +1258,11 @@ int ObjectRef::l_set_fov(lua_State *L) if (!player) return 0; - player->setFov({ static_cast(luaL_checknumber(L, 2)), readParam(L, 3) }); + player->setFov({ + static_cast(luaL_checknumber(L, 2)), + readParam(L, 3, false), + lua_isnumber(L, 4) ? static_cast(luaL_checknumber(L, 4)) : 0.0f + }); getServer(L)->SendPlayerFov(player->getPeerId()); return 0; @@ -1276,8 +1280,9 @@ int ObjectRef::l_get_fov(lua_State *L) PlayerFovSpec fov_spec = player->getFov(); lua_pushnumber(L, fov_spec.fov); lua_pushboolean(L, fov_spec.is_multiplier); + lua_pushnumber(L, fov_spec.transition_time); - return 2; + return 3; } // set_breath(self, breath) diff --git a/src/server.cpp b/src/server.cpp index a7eb52837..0346d197d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1892,10 +1892,10 @@ void Server::SendMovePlayer(session_t peer_id) void Server::SendPlayerFov(session_t peer_id) { - NetworkPacket pkt(TOCLIENT_FOV, 4 + 1, peer_id); + NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id); PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov(); - pkt << fov_spec.fov << fov_spec.is_multiplier; + pkt << fov_spec.fov << fov_spec.is_multiplier << fov_spec.transition_time; Send(&pkt); } -- cgit v1.2.3 From 36d35f2fe31a429c1510df680801940472416d45 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 14 May 2020 21:16:45 +0200 Subject: CSM: Bugfixes to camera:get_pos() and camera:get_fov() closes #9857 --- clientmods/preview/init.lua | 2 +- doc/client_lua_api.txt | 2 +- src/client/camera.cpp | 2 +- src/script/lua_api/l_camera.cpp | 59 +++++++++++++++++++++++++---------------- src/script/lua_api/l_env.cpp | 16 +++++------ 5 files changed, 47 insertions(+), 34 deletions(-) (limited to 'src/client/camera.cpp') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index d2440369a..089955d2f 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -79,7 +79,7 @@ core.register_on_item_use(function(itemstack, pointed_thing) return false end - local pos = vector.add(core.localplayer:get_pos(), core.camera:get_offset()) + local pos = core.camera:get_pos() local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 100)) local rc = core.raycast(pos, pos2) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 53442d308..c9cd8ac93 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -967,7 +967,7 @@ Please do not try to access the reference until the camera is initialized, other * `get_camera_mode()` * Returns 0, 1, or 2 as described above * `get_fov()` - * Returns: + * Returns a table with X, Y, maximum and actual FOV in degrees: ```lua { diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 1a5253db4..9b311171a 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -540,7 +540,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_aspect = (f32) window_size.X / (f32) window_size.Y; m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) - m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); + m_fov_y *= core::clamp(sqrt(16./10. / m_aspect), 1.0, 1.4); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp index 9c1470284..bfa60be67 100644 --- a/src/script/lua_api/l_camera.cpp +++ b/src/script/lua_api/l_camera.cpp @@ -51,6 +51,7 @@ void LuaCamera::create(lua_State *L, Camera *m) lua_setfield(L, objectstable, "camera"); } +// set_camera_mode(self, mode) int LuaCamera::l_set_camera_mode(lua_State *L) { Camera *camera = getobject(L, 1); @@ -67,17 +68,19 @@ int LuaCamera::l_set_camera_mode(lua_State *L) return 0; } +// get_camera_mode(self) int LuaCamera::l_get_camera_mode(lua_State *L) { Camera *camera = getobject(L, 1); if (!camera) return 0; - lua_pushnumber(L, (int)camera->getCameraMode()); + lua_pushinteger(L, (int)camera->getCameraMode()); return 1; } +// get_fov(self) int LuaCamera::l_get_fov(lua_State *L) { Camera *camera = getobject(L, 1); @@ -85,9 +88,9 @@ int LuaCamera::l_get_fov(lua_State *L) return 0; lua_newtable(L); - lua_pushnumber(L, camera->getFovX() * core::DEGTORAD); + lua_pushnumber(L, camera->getFovX() * core::RADTODEG); lua_setfield(L, -2, "x"); - lua_pushnumber(L, camera->getFovY() * core::DEGTORAD); + lua_pushnumber(L, camera->getFovY() * core::RADTODEG); lua_setfield(L, -2, "y"); lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG); lua_setfield(L, -2, "actual"); @@ -96,16 +99,18 @@ int LuaCamera::l_get_fov(lua_State *L) return 1; } +// get_pos(self) int LuaCamera::l_get_pos(lua_State *L) { Camera *camera = getobject(L, 1); if (!camera) return 0; - push_v3f(L, camera->getPosition()); + push_v3f(L, camera->getPosition() / BS); return 1; } +// get_offset(self) int LuaCamera::l_get_offset(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); @@ -115,38 +120,40 @@ int LuaCamera::l_get_offset(lua_State *L) return 1; } +// get_look_dir(self) int LuaCamera::l_get_look_dir(lua_State *L) { - LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); - sanity_check(player); - - float pitch = -1.0 * player->getPitch() * core::DEGTORAD; - float yaw = (player->getYaw() + 90.) * core::DEGTORAD; - v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), - std::cos(pitch) * std::sin(yaw)); + Camera *camera = getobject(L, 1); + if (!camera) + return 0; - push_v3f(L, v); + push_v3f(L, camera->getDirection()); return 1; } +// get_look_horizontal(self) +// FIXME: wouldn't localplayer be a better place for this? int LuaCamera::l_get_look_horizontal(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); sanity_check(player); - lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD); + lua_pushnumber(L, (player->getYaw() + 90.f) * core::DEGTORAD); return 1; } +// get_look_vertical(self) +// FIXME: wouldn't localplayer be a better place for this? int LuaCamera::l_get_look_vertical(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); sanity_check(player); - lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD); + lua_pushnumber(L, -1.0f * player->getPitch() * core::DEGTORAD); return 1; } +// get_aspect_ratio(self) int LuaCamera::l_get_aspect_ratio(lua_State *L) { Camera *camera = getobject(L, 1); @@ -215,13 +222,19 @@ void LuaCamera::Register(lua_State *L) lua_pop(L, 1); } +// clang-format off const char LuaCamera::className[] = "Camera"; -const luaL_Reg LuaCamera::methods[] = {luamethod(LuaCamera, set_camera_mode), - luamethod(LuaCamera, get_camera_mode), luamethod(LuaCamera, get_fov), - luamethod(LuaCamera, get_pos), luamethod(LuaCamera, get_offset), - luamethod(LuaCamera, get_look_dir), - luamethod(LuaCamera, get_look_vertical), - luamethod(LuaCamera, get_look_horizontal), - luamethod(LuaCamera, get_aspect_ratio), - - {0, 0}}; +const luaL_Reg LuaCamera::methods[] = { + luamethod(LuaCamera, set_camera_mode), + luamethod(LuaCamera, get_camera_mode), + luamethod(LuaCamera, get_fov), + luamethod(LuaCamera, get_pos), + luamethod(LuaCamera, get_offset), + luamethod(LuaCamera, get_look_dir), + luamethod(LuaCamera, get_look_vertical), + luamethod(LuaCamera, get_look_horizontal), + luamethod(LuaCamera, get_aspect_ratio), + + {0, 0} +}; +// clang-format on diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index cabca124d..b8a8a5ce1 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -780,8 +780,8 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) #ifndef SERVER // Client API limitations - if (getClient(L)) - radius = getClient(L)->CSMClampRadius(pos, radius); + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); #endif for (int d = start_radius; d <= radius; d++) { @@ -811,9 +811,9 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) const NodeDefManager *ndef = env->getGameDef()->ndef(); #ifndef SERVER - if (getClient(L)) { - minp = getClient(L)->CSMClampPos(minp); - maxp = getClient(L)->CSMClampPos(maxp); + if (Client *client = getClient(L)) { + minp = client->CSMClampPos(minp); + maxp = client->CSMClampPos(maxp); } #endif @@ -887,9 +887,9 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) const NodeDefManager *ndef = env->getGameDef()->ndef(); #ifndef SERVER - if (getClient(L)) { - minp = getClient(L)->CSMClampPos(minp); - maxp = getClient(L)->CSMClampPos(maxp); + if (Client *client = getClient(L)) { + minp = client->CSMClampPos(minp); + maxp = client->CSMClampPos(maxp); } #endif -- cgit v1.2.3 From dc6318b84aa8c079330b2adc711113f7d4b55961 Mon Sep 17 00:00:00 2001 From: Paramat Date: Sun, 5 Jul 2020 23:45:21 +0100 Subject: Apply camera smoothing to 'air stepheight' (#10025) Recent changes to collision code have changed the behaviour of the 'touching_ground' bool in movement code. This had the effect of disabling camera smoothing when 'air stepheight' occurred when jumping onto a node while pressing forwards against the node, causing an unpleasant sharp camera movement. Rewrite the conditions for camera smoothing such that it is applied when jumping. --- src/client/camera.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/client/camera.cpp') diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 9b311171a..abc55e4b7 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -342,9 +342,13 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r if (player->getParent()) player_position = player->getParent()->getPosition(); - if(player->touching_ground && - player_position.Y > old_player_position.Y) - { + // Smooth the camera movement when the player instantly moves upward due to stepheight. + // To smooth the 'not touching_ground' stepheight, smoothing is necessary when jumping + // or swimming (for when moving from liquid to land). + // Disable smoothing if climbing or flying, to avoid upwards offset of player model + // when seen in 3rd person view. + bool flying = g_settings->getBool("free_move") && m_client->checkLocalPrivilege("fly"); + if (player_position.Y > old_player_position.Y && !player->is_climbing && !flying) { f32 oldy = old_player_position.Y; f32 newy = player_position.Y; f32 t = std::exp(-23 * frametime); @@ -607,14 +611,11 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r 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) && - (!g_settings->getBool("free_move") || !m_client->checkLocalPrivilege("fly"))) { + if ((walking || swimming || climbing) && !flying) { // Start animation m_view_bobbing_state = 1; m_view_bobbing_speed = MYMIN(speed.getLength(), 70); - } - else if (m_view_bobbing_state == 1) - { + } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; -- cgit v1.2.3